Prevent crash when passing empty array to MeshEmitter

This commit is contained in:
Yuri Roubinsky 2021-11-25 10:26:31 +03:00
parent ab6e370a9e
commit 93bb34cfb4
2 changed files with 94 additions and 64 deletions

View file

@ -318,7 +318,6 @@ String VisualShaderNodeParticleMeshEmitter::get_input_port_name(int p_port) cons
String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code; String code;
if (mesh.is_valid()) {
if (is_output_port_connected(0)) { // position if (is_output_port_connected(0)) { // position
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n"; code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_vx") + ";\n";
} }
@ -338,7 +337,6 @@ String VisualShaderNodeParticleMeshEmitter::generate_global(Shader::Mode p_mode,
if (is_output_port_connected(5)) { // uv2 if (is_output_port_connected(5)) { // uv2
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n"; code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv2") + ";\n";
} }
}
return code; return code;
} }
@ -503,69 +501,99 @@ void VisualShaderNodeParticleMeshEmitter::_update_textures() {
Vector<Vector2> uvs; Vector<Vector2> uvs;
Vector<Vector2> uvs2; Vector<Vector2> uvs2;
const int surface_count = mesh->get_surface_count();
if (use_all_surfaces) { if (use_all_surfaces) {
for (int i = 0; i < max_surface_index; i++) { for (int i = 0; i < surface_count; i++) {
const Array surface_arrays = mesh->surface_get_arrays(i);
const int surface_arrays_size = surface_arrays.size();
// position // position
Array vertex_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_VERTEX]; if (surface_arrays_size > Mesh::ARRAY_VERTEX) {
Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX];
for (int j = 0; j < vertex_array.size(); j++) { for (int j = 0; j < vertex_array.size(); j++) {
vertices.push_back((Vector3)vertex_array[j]); vertices.push_back((Vector3)vertex_array[j]);
} }
}
// normal // normal
Array normal_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_NORMAL]; if (surface_arrays_size > Mesh::ARRAY_NORMAL) {
Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL];
for (int j = 0; j < normal_array.size(); j++) { for (int j = 0; j < normal_array.size(); j++) {
normals.push_back((Vector3)normal_array[j]); normals.push_back((Vector3)normal_array[j]);
} }
}
// color // color
Array color_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_COLOR]; if (surface_arrays_size > Mesh::ARRAY_COLOR) {
Array color_array = surface_arrays[Mesh::ARRAY_COLOR];
for (int j = 0; j < color_array.size(); j++) { for (int j = 0; j < color_array.size(); j++) {
colors.push_back((Color)color_array[j]); colors.push_back((Color)color_array[j]);
} }
}
// uv // uv
Array uv_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV]; if (surface_arrays_size > Mesh::ARRAY_TEX_UV) {
Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV];
for (int j = 0; j < uv_array.size(); j++) { for (int j = 0; j < uv_array.size(); j++) {
uvs.push_back((Vector2)uv_array[j]); uvs.push_back((Vector2)uv_array[j]);
} }
}
// uv2 // uv2
Array uv2_array = mesh->surface_get_arrays(i)[Mesh::ARRAY_TEX_UV2]; if (surface_arrays_size > Mesh::ARRAY_TEX_UV2) {
Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2];
for (int j = 0; j < uv2_array.size(); j++) { for (int j = 0; j < uv2_array.size(); j++) {
uvs2.push_back((Vector2)uv2_array[j]); uvs2.push_back((Vector2)uv2_array[j]);
} }
} }
}
} else { } else {
if (surface_index >= 0 && surface_index < surface_count) {
const Array surface_arrays = mesh->surface_get_arrays(surface_index);
const int surface_arrays_size = surface_arrays.size();
// position // position
Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX]; if (surface_arrays_size > Mesh::ARRAY_VERTEX) {
Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX];
for (int i = 0; i < vertex_array.size(); i++) { for (int i = 0; i < vertex_array.size(); i++) {
vertices.push_back((Vector3)vertex_array[i]); vertices.push_back((Vector3)vertex_array[i]);
} }
}
// normal // normal
Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL]; if (surface_arrays_size > Mesh::ARRAY_NORMAL) {
Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL];
for (int i = 0; i < normal_array.size(); i++) { for (int i = 0; i < normal_array.size(); i++) {
normals.push_back((Vector3)normal_array[i]); normals.push_back((Vector3)normal_array[i]);
} }
}
// color // color
Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR]; if (surface_arrays_size > Mesh::ARRAY_COLOR) {
Array color_array = surface_arrays[Mesh::ARRAY_COLOR];
for (int i = 0; i < color_array.size(); i++) { for (int i = 0; i < color_array.size(); i++) {
colors.push_back((Color)color_array[i]); colors.push_back((Color)color_array[i]);
} }
}
// uv // uv
Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV]; if (surface_arrays_size > Mesh::ARRAY_TEX_UV) {
Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV];
for (int j = 0; j < uv_array.size(); j++) { for (int j = 0; j < uv_array.size(); j++) {
uvs.push_back((Vector2)uv_array[j]); uvs.push_back((Vector2)uv_array[j]);
} }
}
// uv2 // uv2
Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2]; if (surface_arrays_size > Mesh::ARRAY_TEX_UV2) {
Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2];
for (int j = 0; j < uv2_array.size(); j++) { for (int j = 0; j < uv2_array.size(); j++) {
uvs2.push_back((Vector2)uv2_array[j]); uvs2.push_back((Vector2)uv2_array[j]);
} }
} }
}
}
_update_texture(vertices, position_texture); _update_texture(vertices, position_texture);
_update_texture(normals, normal_texture); _update_texture(normals, normal_texture);
@ -579,12 +607,6 @@ void VisualShaderNodeParticleMeshEmitter::set_mesh(Ref<Mesh> p_mesh) {
return; return;
} }
if (p_mesh.is_valid()) {
max_surface_index = p_mesh->get_surface_count();
} else {
max_surface_index = 0;
}
if (mesh.is_valid()) { if (mesh.is_valid()) {
Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures); Callable callable = callable_mp(this, &VisualShaderNodeParticleMeshEmitter::_update_textures);
@ -623,7 +645,16 @@ bool VisualShaderNodeParticleMeshEmitter::is_use_all_surfaces() const {
} }
void VisualShaderNodeParticleMeshEmitter::set_surface_index(int p_surface_index) { void VisualShaderNodeParticleMeshEmitter::set_surface_index(int p_surface_index) {
if (p_surface_index == surface_index || p_surface_index < 0 || p_surface_index >= max_surface_index) { if (mesh.is_valid()) {
if (mesh->get_surface_count() > 0) {
p_surface_index = CLAMP(p_surface_index, 0, mesh->get_surface_count() - 1);
} else {
p_surface_index = 0;
}
} else if (p_surface_index < 0) {
p_surface_index = 0;
}
if (surface_index == p_surface_index) {
return; return;
} }
surface_index = p_surface_index; surface_index = p_surface_index;

View file

@ -111,7 +111,6 @@ class VisualShaderNodeParticleMeshEmitter : public VisualShaderNodeParticleEmitt
Ref<Mesh> mesh; Ref<Mesh> mesh;
bool use_all_surfaces = true; bool use_all_surfaces = true;
int surface_index = 0; int surface_index = 0;
int max_surface_index = 0;
Ref<ImageTexture> position_texture; Ref<ImageTexture> position_texture;
Ref<ImageTexture> normal_texture; Ref<ImageTexture> normal_texture;