Merge branch 'master' into rlsw

This commit is contained in:
Ray 2025-08-31 12:27:48 +02:00 • committed by GitHub
commit c32a4b6586
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -12,7 +12,7 @@
* #define SUPPORT_FILEFORMAT_GLTF
* #define SUPPORT_FILEFORMAT_VOX
* #define SUPPORT_FILEFORMAT_M3D
* Selected desired fileformats to be supported for model data loading.
* Selected desired fileformats to be supported for model data loading
*
* #define SUPPORT_MESH_GENERATION
* Support procedural mesh generation functions, uses external par_shapes.h library
@ -2298,7 +2298,7 @@ void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame)
if (firstMeshWithBones != -1)
{
// Update all bones and boneMatrices of first mesh with bones.
// Update all bones and boneMatrices of first mesh with bones
for (int boneId = 0; boneId < anim.boneCount; boneId++)
{
Transform *bindTransform = &model.bindPose[boneId];
@ -3722,7 +3722,7 @@ void GenMeshTangents(Mesh *mesh)
}
// Gram-Schmidt orthogonalization to make tangent orthogonal to normal
// T_prime = T - N * dot(N, T)
// T_prime = T - N*dot(N, T)
Vector3 orthogonalized = Vector3Subtract(tangent, Vector3Scale(normal, Vector3DotProduct(normal, tangent)));
// Handle cases where orthogonalized vector is too small
@ -4292,7 +4292,7 @@ static Model LoadOBJ(const char *fileName)
if (fileText == NULL)
{
TRACELOG(LOG_ERROR, "MODEL: [%s] Unable to read obj file", fileName);
TRACELOG(LOG_WARNING, "MODEL: [%s] Unable to read obj file", fileName);
return model;
}
@ -4308,7 +4308,7 @@ static Model LoadOBJ(const char *fileName)
if (ret != TINYOBJ_SUCCESS)
{
TRACELOG(LOG_ERROR, "MODEL: Unable to read obj data %s", fileName);
TRACELOG(LOG_WARNING, "MODEL: Unable to read obj data %s", fileName);
return model;
}
@ -4473,9 +4473,17 @@ static Model LoadOBJ(const char *fileName)
for (int i = 0; i < 3; i++) model.meshes[meshIndex].vertices[localMeshVertexCount*3 + i] = objAttributes.vertices[vertIndex*3 + i];
for (int i = 0; i < 3; i++) model.meshes[meshIndex].normals[localMeshVertexCount*3 + i] = objAttributes.normals[normalIndex*3 + i];
for (int i = 0; i < 2; i++) model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + i] = objAttributes.texcoords[texcordIndex*2 + i];
if (objAttributes.normals != NULL && normalIndex != TINYOBJ_INVALID_INDEX && normalIndex >= 0)
{
for (int i = 0; i < 3; i++) model.meshes[meshIndex].normals[localMeshVertexCount*3 + i] = objAttributes.normals[normalIndex*3 + i];
}
else
{
model.meshes[meshIndex].normals[localMeshVertexCount*3 + 0] = 0.0f;
model.meshes[meshIndex].normals[localMeshVertexCount*3 + 1] = 1.0f;
model.meshes[meshIndex].normals[localMeshVertexCount*3 + 2] = 0.0f;
}
model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1];
@ -4493,8 +4501,6 @@ static Model LoadOBJ(const char *fileName)
tinyobj_shapes_free(objShapes, objShapeCount);
tinyobj_materials_free(objMaterials, objMaterialCount);
for (int i = 0; i < model.meshCount; i++) UploadMesh(model.meshes + i, true);
// Restore current working directory
if (CHDIR(currentDir) != 0)
{
@ -5285,8 +5291,7 @@ static Model LoadGLTF(const char *fileName)
> Texcoords: vec2: float
> Colors: vec4: u8, u16, f32 (normalized)
> Indices: u16, u32 (truncated to u16)
- Scenes defined in the glTF file are ignored. All nodes in the file
are used.
- Scenes defined in the glTF file are ignored. All nodes in the file are used
***********************************************************************************************/
@ -5341,8 +5346,8 @@ static Model LoadGLTF(const char *fileName)
int primitivesCount = 0;
// NOTE: We will load every primitive in the glTF as a separate raylib Mesh.
// Determine total number of meshes needed from the node hierarchy.
// NOTE: We will load every primitive in the glTF as a separate raylib Mesh
// Determine total number of meshes needed from the node hierarchy
for (unsigned int i = 0; i < data->nodes_count; i++)
{
cgltf_node *node = &(data->nodes[i]);
@ -5483,15 +5488,16 @@ static Model LoadGLTF(const char *fileName)
// Other possible materials not supported by raylib pipeline:
// 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.
// Each primitive within a glTF node becomes a Raylib Mesh.
// The local-to-world transform of each node is used to transform the
// points/normals/tangents of the created Mesh(es).
// 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.
// Load meshes data
//
// NOTE: Visit each node in the hierarchy and process any mesh linked from it
// - Each primitive within a glTF node becomes a raylib Mesh
// - The local-to-world transform of each node is used to transform the points/normals/tangents of the created Mesh(es)
// - 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
//
// WARNING: The code below disregards the scenes defined in the file, all nodes are used
//----------------------------------------------------------------------------------------------------
int meshIndex = 0;
for (unsigned int i = 0; i < data->nodes_count; i++)
@ -5499,8 +5505,7 @@ static Model LoadGLTF(const char *fileName)
cgltf_node *node = &(data->nodes[i]);
cgltf_mesh *mesh = node->mesh;
if (!mesh)
continue;
if (!mesh) continue;
cgltf_float worldTransform[16];
cgltf_node_transform_world(node, worldTransform);
@ -5531,75 +5536,87 @@ static Model LoadGLTF(const char *fileName)
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
// WARNING: SPECS: POSITION accessor MUST have its min and max properties defined
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
if (model.meshes[meshIndex].vertices != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Vertices attribute data already loaded", fileName);
else
{
// Init raylib mesh vertices to copy glTF attribute data
model.meshes[meshIndex].vertexCount = (int)attribute->count;
model.meshes[meshIndex].vertices = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
// Load 3 components of float data type into mesh.vertices
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)
// Transform the vertices
float *vertices = model.meshes[meshIndex].vertices;
for (unsigned int k = 0; k < attribute->count; k++)
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
{
Vector3 vt = Vector3Transform((Vector3){ vertices[3*k], vertices[3*k+1], vertices[3*k+2] }, worldMatrix);
vertices[3*k] = vt.x;
vertices[3*k+1] = vt.y;
vertices[3*k+2] = vt.z;
// Init raylib mesh vertices to copy glTF attribute data
model.meshes[meshIndex].vertexCount = (int)attribute->count;
model.meshes[meshIndex].vertices = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
// Load 3 components of float data type into mesh.vertices
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].vertices)
// Transform the vertices
float *vertices = model.meshes[meshIndex].vertices;
for (unsigned int k = 0; k < attribute->count; k++)
{
Vector3 vt = Vector3Transform((Vector3){ vertices[3*k], vertices[3*k+1], vertices[3*k+2] }, worldMatrix);
vertices[3*k] = vt.x;
vertices[3*k+1] = vt.y;
vertices[3*k+2] = vt.z;
}
}
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
{
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
if (model.meshes[meshIndex].normals != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data already loaded", fileName);
else
{
// Init raylib mesh normals to copy glTF attribute data
model.meshes[meshIndex].normals = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
// Load 3 components of float data type into mesh.normals
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)
// Transform the normals
float *normals = model.meshes[meshIndex].normals;
for (unsigned int k = 0; k < attribute->count; k++)
if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f))
{
Vector3 nt = Vector3Transform((Vector3){ normals[3*k], normals[3*k+1], normals[3*k+2] }, worldMatrixNormals);
normals[3*k] = nt.x;
normals[3*k+1] = nt.y;
normals[3*k+2] = nt.z;
// Init raylib mesh normals to copy glTF attribute data
model.meshes[meshIndex].normals = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
// Load 3 components of float data type into mesh.normals
LOAD_ATTRIBUTE(attribute, 3, float, model.meshes[meshIndex].normals)
// Transform the normals
float *normals = model.meshes[meshIndex].normals;
for (unsigned int k = 0; k < attribute->count; k++)
{
Vector3 nt = Vector3Transform((Vector3){ normals[3*k], normals[3*k+1], normals[3*k+2] }, worldMatrixNormals);
normals[3*k] = nt.x;
normals[3*k+1] = nt.y;
normals[3*k+2] = nt.z;
}
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Normals attribute data format not supported, use vec3 float", fileName);
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Normal 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
{
cgltf_accessor *attribute = mesh->primitives[p].attributes[j].data;
if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))
if (model.meshes[meshIndex].tangents != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Tangents attribute data already loaded", fileName);
else
{
// Init raylib mesh tangent to copy glTF attribute data
model.meshes[meshIndex].tangents = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
// Load 4 components of float data type into mesh.tangents
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)
// Transform the tangents
float *tangents = model.meshes[meshIndex].tangents;
for (unsigned int k = 0; k < attribute->count; k++)
if ((attribute->type == cgltf_type_vec4) && (attribute->component_type == cgltf_component_type_r_32f))
{
Vector3 tt = Vector3Transform((Vector3){ tangents[4*k], tangents[4*k+1], tangents[4*k+2] }, worldMatrix);
tangents[4*k] = tt.x;
tangents[4*k+1] = tt.y;
tangents[4*k+2] = tt.z;
// Init raylib mesh tangent to copy glTF attribute data
model.meshes[meshIndex].tangents = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
// Load 4 components of float data type into mesh.tangents
LOAD_ATTRIBUTE(attribute, 4, float, model.meshes[meshIndex].tangents)
// Transform the tangents
float *tangents = model.meshes[meshIndex].tangents;
for (unsigned int k = 0; k < attribute->count; k++)
{
Vector3 tt = Vector3Transform((Vector3){ tangents[4*k], tangents[4*k+1], tangents[4*k+2] }, worldMatrix);
tangents[4*k] = tt.x;
tangents[4*k+1] = tt.y;
tangents[4*k+2] = tt.z;
}
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangents attribute data format not supported, use vec4 float", fileName);
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Tangent 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
{
@ -5665,114 +5682,118 @@ 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
if (attribute->type == cgltf_type_vec3) // RGB
if (model.meshes[meshIndex].colors != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Colors attribute data already loaded", fileName);
else
{
if (attribute->component_type == cgltf_component_type_r_8u)
if (attribute->type == cgltf_type_vec3) // RGB
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*3*sizeof(unsigned char));
LOAD_ATTRIBUTE(attribute, 3, unsigned char, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
if (attribute->component_type == cgltf_component_type_r_8u)
{
model.meshes[meshIndex].colors[c] = temp[k];
model.meshes[meshIndex].colors[c + 1] = temp[k + 1];
model.meshes[meshIndex].colors[c + 2] = temp[k + 2];
model.meshes[meshIndex].colors[c + 3] = 255;
}
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
RL_FREE(temp);
// Load data into a temp buffer to be converted to raylib data type
unsigned char *temp = (unsigned char *)RL_MALLOC(attribute->count*3*sizeof(unsigned char));
LOAD_ATTRIBUTE(attribute, 3, unsigned char, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
{
model.meshes[meshIndex].colors[c] = temp[k];
model.meshes[meshIndex].colors[c + 1] = temp[k + 1];
model.meshes[meshIndex].colors[c + 2] = temp[k + 2];
model.meshes[meshIndex].colors[c + 3] = 255;
}
RL_FREE(temp);
}
else if (attribute->component_type == cgltf_component_type_r_16u)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*3*sizeof(unsigned short));
LOAD_ATTRIBUTE(attribute, 3, unsigned short, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
{
model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[k]/65535.0f)*255.0f);
model.meshes[meshIndex].colors[c + 1] = (unsigned char)(((float)temp[k + 1]/65535.0f)*255.0f);
model.meshes[meshIndex].colors[c + 2] = (unsigned char)(((float)temp[k + 2]/65535.0f)*255.0f);
model.meshes[meshIndex].colors[c + 3] = 255;
}
RL_FREE(temp);
}
else if (attribute->component_type == cgltf_component_type_r_32f)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
float *temp = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
LOAD_ATTRIBUTE(attribute, 3, float, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
{
model.meshes[meshIndex].colors[c] = (unsigned char)(temp[k]*255.0f);
model.meshes[meshIndex].colors[c + 1] = (unsigned char)(temp[k + 1]*255.0f);
model.meshes[meshIndex].colors[c + 2] = (unsigned char)(temp[k + 2]*255.0f);
model.meshes[meshIndex].colors[c + 3] = 255;
}
RL_FREE(temp);
}
else TRACELOG(LOG_WARNING, "MODEL: [%s] Color attribute data format not supported", fileName);
}
else if (attribute->component_type == cgltf_component_type_r_16u)
else if (attribute->type == cgltf_type_vec4) // RGBA
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*3*sizeof(unsigned short));
LOAD_ATTRIBUTE(attribute, 3, unsigned short, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
if (attribute->component_type == cgltf_component_type_r_8u)
{
model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[k]/65535.0f)*255.0f);
model.meshes[meshIndex].colors[c + 1] = (unsigned char)(((float)temp[k + 1]/65535.0f)*255.0f);
model.meshes[meshIndex].colors[c + 2] = (unsigned char)(((float)temp[k + 2]/65535.0f)*255.0f);
model.meshes[meshIndex].colors[c + 3] = 255;
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load 4 components of unsigned char data type into mesh.colors
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)
}
RL_FREE(temp);
}
else if (attribute->component_type == cgltf_component_type_r_32f)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
float *temp = (float *)RL_MALLOC(attribute->count*3*sizeof(float));
LOAD_ATTRIBUTE(attribute, 3, float, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0, k = 0; c < (attribute->count*4 - 3); c += 4, k += 3)
else if (attribute->component_type == cgltf_component_type_r_16u)
{
model.meshes[meshIndex].colors[c] = (unsigned char)(temp[k]*255.0f);
model.meshes[meshIndex].colors[c + 1] = (unsigned char)(temp[k + 1]*255.0f);
model.meshes[meshIndex].colors[c + 2] = (unsigned char)(temp[k + 2]*255.0f);
model.meshes[meshIndex].colors[c + 3] = 255;
}
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
RL_FREE(temp);
// Load data into a temp buffer to be converted to raylib data type
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*4*sizeof(unsigned short));
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[c]/65535.0f)*255.0f);
RL_FREE(temp);
}
else if (attribute->component_type == cgltf_component_type_r_32f)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
float *temp = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
LOAD_ATTRIBUTE(attribute, 4, float, temp);
// Convert data to raylib color data type (4 bytes), we expect the color data normalized
for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f);
RL_FREE(temp);
}
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);
}
else if (attribute->type == cgltf_type_vec4) // RGBA
{
if (attribute->component_type == cgltf_component_type_r_8u)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load 4 components of unsigned char data type into mesh.colors
LOAD_ATTRIBUTE(attribute, 4, unsigned char, model.meshes[meshIndex].colors)
}
else if (attribute->component_type == cgltf_component_type_r_16u)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
unsigned short *temp = (unsigned short *)RL_MALLOC(attribute->count*4*sizeof(unsigned short));
LOAD_ATTRIBUTE(attribute, 4, unsigned short, temp);
// Convert data to raylib color data type (4 bytes)
for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(((float)temp[c]/65535.0f)*255.0f);
RL_FREE(temp);
}
else if (attribute->component_type == cgltf_component_type_r_32f)
{
// Init raylib mesh color to copy glTF attribute data
model.meshes[meshIndex].colors = (unsigned char *)RL_MALLOC(attribute->count*4*sizeof(unsigned char));
// Load data into a temp buffer to be converted to raylib data type
float *temp = (float *)RL_MALLOC(attribute->count*4*sizeof(float));
LOAD_ATTRIBUTE(attribute, 4, float, temp);
// Convert data to raylib color data type (4 bytes), we expect the color data normalized
for (unsigned int c = 0; c < attribute->count*4; c++) model.meshes[meshIndex].colors[c] = (unsigned char)(temp[c]*255.0f);
RL_FREE(temp);
}
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)
@ -5782,32 +5803,33 @@ static Model LoadGLTF(const char *fileName)
model.meshes[meshIndex].triangleCount = (int)attribute->count/3;
if (attribute->component_type == cgltf_component_type_r_16u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
// Load unsigned short data type into mesh.indices
LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)
}
else if (attribute->component_type == cgltf_component_type_r_8u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
}
else if (attribute->component_type == cgltf_component_type_r_32u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
}
if (model.meshes[meshIndex].indices != NULL) TRACELOG(LOG_WARNING, "MODEL: [%s] Indices attribute data already loaded", fileName);
else
{
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data format not supported, use u16", fileName);
if (attribute->component_type == cgltf_component_type_r_16u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
// Load unsigned short data type into mesh.indices
LOAD_ATTRIBUTE(attribute, 1, unsigned short, model.meshes[meshIndex].indices)
}
else if (attribute->component_type == cgltf_component_type_r_8u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned char, model.meshes[meshIndex].indices, unsigned short)
}
else if (attribute->component_type == cgltf_component_type_r_32u)
{
// Init raylib mesh indices to copy glTF attribute data
model.meshes[meshIndex].indices = (unsigned short *)RL_MALLOC(attribute->count*sizeof(unsigned short));
LOAD_ATTRIBUTE_CAST(attribute, 1, unsigned int, model.meshes[meshIndex].indices, unsigned short);
TRACELOG(LOG_WARNING, "MODEL: [%s] Indices data converted from u32 to u16, possible loss of data", fileName);
}
else 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
@ -5830,8 +5852,9 @@ static Model LoadGLTF(const char *fileName)
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#skinned-mesh-attributes
//
@ -5859,10 +5882,8 @@ static Model LoadGLTF(const char *fileName)
};
MatrixDecompose(worldMatrix, &(model.bindPose[i].translation), &(model.bindPose[i].rotation), &(model.bindPose[i].scale));
}
}
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);
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);
}
meshIndex = 0;
@ -5871,8 +5892,7 @@ static Model LoadGLTF(const char *fileName)
cgltf_node *node = &(data->nodes[i]);
cgltf_mesh *mesh = node->mesh;
if (!mesh)
continue;
if (!mesh) continue;
for (unsigned int p = 0; p < mesh->primitives_count; p++)
{
@ -6035,6 +6055,7 @@ static Model LoadGLTF(const char *fileName)
meshIndex++; // Move to next mesh
}
}
//----------------------------------------------------------------------------------------------------
// Free all cgltf loaded data
cgltf_free(data);