REVIEWED: [rmodels] LoadGLFT(), avoid loading attributes already loaded, issue a warning. FIX: #4996

This commit is contained in:
Ray
2025-08-20 16:39:45 +02:00
parent c3c33e9654
commit 99cb82a82c

View File

@@ -5488,14 +5488,16 @@ static Model LoadGLTF(const char *fileName)
// Other possible materials not supported by raylib pipeline: // Other possible materials not supported by raylib pipeline:
// has_clearcoat, has_transmission, has_volume, has_ior, has specular, has_sheen // has_clearcoat, has_transmission, has_volume, has_ior, has specular, has_sheen
} }
//----------------------------------------------------------------------------------------------------
// Visit each node in the hierarchy and process any mesh linked from it // Load meshes data
// Each primitive within a glTF node becomes a Raylib Mesh //
// The local-to-world transform of each node is used to transform the // NOTE: Visit each node in the hierarchy and process any mesh linked from it
// points/normals/tangents of the created Mesh(es) // - Each primitive within a glTF node becomes a raylib Mesh
// Any glTF mesh linked from more than one Node (i.e. instancing) // - The local-to-world transform of each node is used to transform the points/normals/tangents of the created Mesh(es)
// is turned into multiple Mesh's, as each Node will have its own transform applied // - Any glTF mesh linked from more than one Node (i.e. instancing) is turned into multiple Mesh's, as each Node will have its own transform applied
// NOTE: The code below disregards the scenes defined in the file, all nodes are used //
// WARNING: The code below disregards the scenes defined in the file, all nodes are used
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
int meshIndex = 0; int meshIndex = 0;
for (unsigned int i = 0; i < data->nodes_count; i++) for (unsigned int i = 0; i < data->nodes_count; i++)
@@ -5503,8 +5505,7 @@ static Model LoadGLTF(const char *fileName)
cgltf_node *node = &(data->nodes[i]); cgltf_node *node = &(data->nodes[i]);
cgltf_mesh *mesh = node->mesh; cgltf_mesh *mesh = node->mesh;
if (!mesh) if (!mesh) continue;
continue;
cgltf_float worldTransform[16]; cgltf_float worldTransform[16];
cgltf_node_transform_world(node, worldTransform); cgltf_node_transform_world(node, worldTransform);
@@ -5536,6 +5537,9 @@ static Model LoadGLTF(const char *fileName)
// WARNING: SPECS: POSITION accessor MUST have its min and max properties defined // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined
if (model.meshes[meshIndex].vertices != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data already loaded", fileName);
else
{
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f)) if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
{ {
// Init raylib mesh vertices to copy glTF attribute data // Init raylib mesh vertices to copy glTF attribute data
@@ -5557,10 +5561,14 @@ static Model LoadGLTF(const char *fileName)
} }
else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName); else TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data format not supported, use vec3 float", fileName);
} }
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL, vec3, float else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal) // NORMAL, vec3, float
{ {
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data; cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
if (model.meshes[meshIndex].normals != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data already loaded", fileName);
else
{
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f)) if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
{ {
// Init raylib mesh normals to copy glTF attribute data // Init raylib mesh normals to copy glTF attribute data
@@ -5579,12 +5587,16 @@ static Model LoadGLTF(const char *fileName)
normals[3*k+2] = nt.z; normals[3*k+2] = nt.z;
} }
} }
else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal attribute data format not supported, use vec3 float", fileName); else TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data format not supported, use vec3 float", fileName);
}
} }
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_tangent) // TANGENT, vec4, float, w is tangent basis sign
{ {
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data; cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
if (model.meshes[meshIndex].tangents != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Tangents attribute data already loaded", fileName);
else
{
if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f)) if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))
{ {
// Init raylib mesh tangent to copy glTF attribute data // Init raylib mesh tangent to copy glTF attribute data
@@ -5603,7 +5615,8 @@ static Model LoadGLTF(const char *fileName)
tangents[4*k+2] = tt.z; tangents[4*k+2] = tt.z;
} }
} }
else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent attribute data format not supported, use vec4 float", fileName); else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangents attribute data format not supported, use vec4 float", fileName);
}
} }
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) // TEXCOORD_n, vec2, float/u8n/u16n else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_texcoord) // TEXCOORD_n, vec2, float/u8n/u16n
{ {
@@ -5669,6 +5682,9 @@ static Model LoadGLTF(const char *fileName)
// WARNING: SPECS: All components of each COLOR_n accessor element MUST be clamped to [0.0, 1.0] range // WARNING: SPECS: All components of each COLOR_n accessor element MUST be clamped to [0.0, 1.0] range
if (model.meshes[meshIndex].colors != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Colors attribute data already loaded", fileName);
else
{
if (attribute->type == cgltf_type_vec3) // RGB if (attribute->type == cgltf_type_vec3) // RGB
{ {
if (attribute->component_type == cgltf_component_type_r_8u) if (attribute->component_type == cgltf_component_type_r_8u)
@@ -5775,8 +5791,9 @@ static Model LoadGLTF(const char *fileName)
} }
else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName); else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
} }
}
// NOTE: Attributes related to animations are processed separately // NOTE: Attributes related to animations data are processed after mesh data loading
} }
// Load primitive indices data (if provided) // Load primitive indices data (if provided)
@@ -5786,6 +5803,9 @@ static Model LoadGLTF(const char *fileName)
model.meshes[meshIndex].triangleCount = (int)attribute->count/3; model.meshes[meshIndex].triangleCount = (int)attribute->count/3;
if (model.meshes[meshIndex].indices != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Indices attribute data already loaded", fileName);
else
{
if (attribute->component_type == cgltf_component_type_r_16u) if (attribute->component_type == cgltf_component_type_r_16u)
{ {
// Init raylib mesh indices to copy glTF attribute data // Init raylib mesh indices to copy glTF attribute data
@@ -5809,9 +5829,7 @@ static Model LoadGLTF(const char *fileName)
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName); TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
} }
else else TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
{
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
} }
} }
else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh else model.meshes[meshIndex].triangleCount = model.meshes[meshIndex].vertexCount/3; // Unindexed mesh
@@ -5834,8 +5852,9 @@ static Model LoadGLTF(const char *fileName)
meshIndex++; // Move to next mesh meshIndex++; // Move to next mesh
} }
} }
//----------------------------------------------------------------------------------------------------
// Load glTF meshes animation data // Load animation data
// REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skins
// REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes // REF: https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#skinned-mesh-attributes
// //
@@ -5863,10 +5882,8 @@ static Model LoadGLTF(const char *fileName)
}; };
MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale)); MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));
} }
}
if (data->skins_count > 1) if (data->skins_count > 1) TRACELOG(LOG_WARNING, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
{
TRACELOG(LOG_WARNING, "MODEL: [%s] can only load one skin (armature) per model, but gltf skins_count == %i", fileName, data->skins_count);
} }
meshIndex = 0; meshIndex = 0;
@@ -5875,8 +5892,7 @@ static Model LoadGLTF(const char *fileName)
cgltf_node *node = &(data->nodes[i]); cgltf_node *node = &(data->nodes[i]);
cgltf_mesh *mesh = node->mesh; cgltf_mesh *mesh = node->mesh;
if (!mesh) if (!mesh) continue;
continue;
for (unsigned int p = 0; p < mesh->primitives_count; p++) for (unsigned int p = 0; p < mesh->primitives_count; p++)
{ {
@@ -6039,6 +6055,7 @@ static Model LoadGLTF(const char *fileName)
meshIndex++; // Move to next mesh meshIndex++; // Move to next mesh
} }
} }
//----------------------------------------------------------------------------------------------------
// Free all cgltf loaded data // Free all cgltf loaded data
cgltf_free(data); cgltf_free(data);