@@ -314,6 +314,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transf
314314 Vector<Vector2> uv2s = surfaces[i].arrays [RS::ARRAY_TEX_UV2];
315315 Vector<int > bones = surfaces[i].arrays [RS::ARRAY_BONES];
316316 Vector<float > weights = surfaces[i].arrays [RS::ARRAY_WEIGHTS];
317+ Vector<Color> colors = surfaces[i].arrays [RS::ARRAY_COLOR];
317318
318319 unsigned int index_count = indices.size ();
319320 unsigned int vertex_count = vertices.size ();
@@ -368,6 +369,7 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transf
368369 const Vector2 *uvs_ptr = uvs.ptr ();
369370 const Vector2 *uv2s_ptr = uv2s.ptr ();
370371 const float *tangents_ptr = tangents.ptr ();
372+ const Color *colors_ptr = colors.ptr ();
371373
372374 for (unsigned int j = 0 ; j < vertex_count; j++) {
373375 const Vector3 &v = vertices_ptr[j];
@@ -385,7 +387,8 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transf
385387 bool is_tang_aligned = !tangents_ptr || (tangents_ptr[j * 4 + 3 ] < 0 ) == (tangents_ptr[idx.second * 4 + 3 ] < 0 );
386388 ERR_FAIL_INDEX (idx.second , normals.size ());
387389 bool is_normals_close = normals[idx.second ].dot (n) > normal_merge_threshold;
388- if (is_uvs_close && is_uv2s_close && is_normals_close && is_tang_aligned) {
390+ bool is_col_close = (!colors_ptr || colors_ptr[j].is_equal_approx (colors_ptr[idx.second ]));
391+ if (is_uvs_close && is_uv2s_close && is_normals_close && is_tang_aligned && is_col_close) {
389392 vertex_remap.push_back (idx.first );
390393 merged_normals[idx.first ] += normals[idx.second ];
391394 merged_normals_counts[idx.first ]++;
@@ -424,23 +427,50 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transf
424427 unsigned int merged_vertex_count = merged_vertices.size ();
425428 const Vector3 *merged_vertices_ptr = merged_vertices.ptr ();
426429 const int32_t *merged_indices_ptr = merged_indices.ptr ();
430+ Vector3 *merged_normals_ptr = merged_normals.ptr ();
427431
428432 {
429433 const int *counts_ptr = merged_normals_counts.ptr ();
430- Vector3 *merged_normals_ptrw = merged_normals.ptr ();
431434 for (unsigned int j = 0 ; j < merged_vertex_count; j++) {
432- merged_normals_ptrw [j] /= counts_ptr[j];
435+ merged_normals_ptr [j] /= counts_ptr[j];
433436 }
434437 }
435438
436- const float normal_weights[3 ] = {
437- // Give some weight to normal preservation, may be worth exposing as an import setting
438- 2 .0f , 2 .0f , 2 .0f
439- };
440-
441439 Vector<float > merged_vertices_f32 = vector3_to_float32_array (merged_vertices_ptr, merged_vertex_count);
442440 float scale = SurfaceTool::simplify_scale_func (merged_vertices_f32.ptr (), merged_vertex_count, sizeof (float ) * 3 );
443441
442+ const size_t attrib_count = 6 ; // 3 for normal + 3 for color (if present)
443+
444+ float attrib_weights[attrib_count] = {};
445+
446+ // Give more weight to normal preservation
447+ attrib_weights[0 ] = attrib_weights[1 ] = attrib_weights[2 ] = 2 .0f ;
448+
449+ // Give some weight to colors but only if present to avoid redundant computations during simplification
450+ if (colors_ptr) {
451+ attrib_weights[3 ] = attrib_weights[4 ] = attrib_weights[5 ] = 1 .0f ;
452+ }
453+
454+ LocalVector<float > merged_attribs;
455+ merged_attribs.resize (merged_vertex_count * attrib_count);
456+ float *merged_attribs_ptr = merged_attribs.ptr ();
457+
458+ memset (merged_attribs_ptr, 0 , merged_attribs.size () * sizeof (float ));
459+
460+ for (unsigned int j = 0 ; j < merged_vertex_count; ++j) {
461+ merged_attribs_ptr[j * attrib_count + 0 ] = merged_normals_ptr[j].x ;
462+ merged_attribs_ptr[j * attrib_count + 1 ] = merged_normals_ptr[j].y ;
463+ merged_attribs_ptr[j * attrib_count + 2 ] = merged_normals_ptr[j].z ;
464+
465+ if (colors_ptr) {
466+ unsigned int rj = vertex_inverse_remap[j];
467+
468+ merged_attribs_ptr[j * attrib_count + 3 ] = colors_ptr[rj].r ;
469+ merged_attribs_ptr[j * attrib_count + 4 ] = colors_ptr[rj].g ;
470+ merged_attribs_ptr[j * attrib_count + 5 ] = colors_ptr[rj].b ;
471+ }
472+ }
473+
444474 unsigned int index_target = 12 ; // Start with the smallest target, 4 triangles
445475 unsigned int last_index_count = 0 ;
446476
@@ -451,17 +481,16 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, Array p_bone_transf
451481 PackedInt32Array new_indices;
452482 new_indices.resize (index_count);
453483
454- Vector<float > merged_normals_f32 = vector3_to_float32_array (merged_normals.ptr (), merged_normals.size ());
455484 const int simplify_options = SurfaceTool::SIMPLIFY_LOCK_BORDER;
456485
457486 size_t new_index_count = SurfaceTool::simplify_with_attrib_func (
458487 (unsigned int *)new_indices.ptrw (),
459488 (const uint32_t *)merged_indices_ptr, index_count,
460489 merged_vertices_f32.ptr (), merged_vertex_count,
461490 sizeof (float ) * 3 , // Vertex stride
462- merged_normals_f32. ptr () ,
463- sizeof (float ) * 3 , // Attribute stride
464- normal_weights, 3 ,
491+ merged_attribs_ptr ,
492+ sizeof (float ) * attrib_count , // Attribute stride
493+ attrib_weights, attrib_count ,
465494 nullptr , // Vertex lock
466495 index_target,
467496 max_mesh_error,
0 commit comments