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,26 +318,24 @@ 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"; }
}
if (is_output_port_connected(1)) { // normal if (is_output_port_connected(1)) { // normal
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n"; code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_nm") + ";\n";
} }
if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha if (is_output_port_connected(2) || is_output_port_connected(3)) { // color & alpha
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n"; code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_col") + ";\n";
} }
if (is_output_port_connected(4)) { // uv if (is_output_port_connected(4)) { // uv
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n"; code += "uniform sampler2D " + make_unique_id(p_type, p_id, "mesh_uv") + ";\n";
} }
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,67 +501,97 @@ 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) {
for (int j = 0; j < vertex_array.size(); j++) { Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX];
vertices.push_back((Vector3)vertex_array[j]); for (int j = 0; j < vertex_array.size(); 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) {
for (int j = 0; j < normal_array.size(); j++) { Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL];
normals.push_back((Vector3)normal_array[j]); for (int j = 0; j < normal_array.size(); 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) {
for (int j = 0; j < color_array.size(); j++) { Array color_array = surface_arrays[Mesh::ARRAY_COLOR];
colors.push_back((Color)color_array[j]); for (int j = 0; j < color_array.size(); 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) {
for (int j = 0; j < uv_array.size(); j++) { Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV];
uvs.push_back((Vector2)uv_array[j]); for (int j = 0; j < uv_array.size(); 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) {
for (int j = 0; j < uv2_array.size(); j++) { Array uv2_array = surface_arrays[Mesh::ARRAY_TEX_UV2];
uvs2.push_back((Vector2)uv2_array[j]); for (int j = 0; j < uv2_array.size(); j++) {
uvs2.push_back((Vector2)uv2_array[j]);
}
} }
} }
} else { } else {
// position if (surface_index >= 0 && surface_index < surface_count) {
Array vertex_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_VERTEX]; const Array surface_arrays = mesh->surface_get_arrays(surface_index);
for (int i = 0; i < vertex_array.size(); i++) { const int surface_arrays_size = surface_arrays.size();
vertices.push_back((Vector3)vertex_array[i]);
}
// normal // position
Array normal_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_NORMAL]; if (surface_arrays_size > Mesh::ARRAY_VERTEX) {
for (int i = 0; i < normal_array.size(); i++) { Array vertex_array = surface_arrays[Mesh::ARRAY_VERTEX];
normals.push_back((Vector3)normal_array[i]); for (int i = 0; i < vertex_array.size(); i++) {
} vertices.push_back((Vector3)vertex_array[i]);
}
}
// color // normal
Array color_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_COLOR]; if (surface_arrays_size > Mesh::ARRAY_NORMAL) {
for (int i = 0; i < color_array.size(); i++) { Array normal_array = surface_arrays[Mesh::ARRAY_NORMAL];
colors.push_back((Color)color_array[i]); for (int i = 0; i < normal_array.size(); i++) {
} normals.push_back((Vector3)normal_array[i]);
}
}
// uv // color
Array uv_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV]; if (surface_arrays_size > Mesh::ARRAY_COLOR) {
for (int j = 0; j < uv_array.size(); j++) { Array color_array = surface_arrays[Mesh::ARRAY_COLOR];
uvs.push_back((Vector2)uv_array[j]); for (int i = 0; i < color_array.size(); i++) {
} colors.push_back((Color)color_array[i]);
}
}
// uv2 // uv
Array uv2_array = mesh->surface_get_arrays(surface_index)[Mesh::ARRAY_TEX_UV2]; if (surface_arrays_size > Mesh::ARRAY_TEX_UV) {
for (int j = 0; j < uv2_array.size(); j++) { Array uv_array = surface_arrays[Mesh::ARRAY_TEX_UV];
uvs2.push_back((Vector2)uv2_array[j]); for (int j = 0; j < uv_array.size(); j++) {
uvs.push_back((Vector2)uv_array[j]);
}
}
// 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++) {
uvs2.push_back((Vector2)uv2_array[j]);
}
}
} }
} }
@ -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;