Refactored the new names and structure of extracted functions.

This commit is contained in:
Hristo Stamenov 2021-06-19 15:21:07 +03:00
parent 3501c86b33
commit 659c6faa05

View File

@ -118,10 +118,13 @@ static ModelAnimation *LoadIQMModelAnimations(const char *fileName, int *animCou
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount); // Load GLTF animation data
static void LoadGLTFModelIndices(Model *model, cgltf_accessor *indexAccessor, int primitiveIndex);
static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex);
static void LoadGLTFBoneAttribute(Model *model, cgltf_accessor *jointsAccessor, const cgltf_data *data, int primitiveIndex);
static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data);
static void LoadGLTFMesh(cgltf_data *data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char* fileName);
static void LoadGLTFNode(cgltf_data *data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char* fileName);
static void InitGLTFBones(Model *model, const cgltf_data *data);
static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex);
static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount);
#endif
//----------------------------------------------------------------------------------
@ -4158,253 +4161,6 @@ static bool GLTFReadValue(cgltf_accessor* acc, unsigned int index, void *variabl
return true;
}
static void ProcessGLTFMesh(cgltf_data *data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char* fileName)
{
for (unsigned int p = 0; p < mesh->primitives_count; p++)
{
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
{
if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_position)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
outModel->meshes[(*primitiveIndex)].vertexCount = (int)acc->count;
int bufferSize = outModel->meshes[(*primitiveIndex)].vertexCount*3*sizeof(float);
outModel->meshes[(*primitiveIndex)].vertices = RL_MALLOC(bufferSize);
outModel->meshes[(*primitiveIndex)].animVertices = RL_MALLOC(bufferSize);
if (acc->component_type == cgltf_component_type_r_32f)
{
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].vertices + (a*3), 3, sizeof(float));
}
}
else if (acc->component_type == cgltf_component_type_r_32u)
{
int readValue[3];
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 3, sizeof(int));
outModel->meshes[(*primitiveIndex)].vertices[(a*3) + 0] = (float)readValue[0];
outModel->meshes[(*primitiveIndex)].vertices[(a*3) + 1] = (float)readValue[1];
outModel->meshes[(*primitiveIndex)].vertices[(a*3) + 2] = (float)readValue[2];
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short vertices
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF vertices must be float or int", fileName);
}
for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
{
Vector3 vertex = {
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 0)],
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 1)],
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 2)],
};
vertex = Vector3Transform(vertex, currentTransform);
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 0)] = vertex.x;
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 1)] = vertex.y;
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 2)] = vertex.z;
}
memcpy(outModel->meshes[(*primitiveIndex)].animVertices, outModel->meshes[(*primitiveIndex)].vertices, bufferSize);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
int bufferSize = (int)(acc->count*3*sizeof(float));
outModel->meshes[(*primitiveIndex)].normals = RL_MALLOC(bufferSize);
outModel->meshes[(*primitiveIndex)].animNormals = RL_MALLOC(bufferSize);
if (acc->component_type == cgltf_component_type_r_32f)
{
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].normals + (a*3), 3, sizeof(float));
}
}
else if (acc->component_type == cgltf_component_type_r_32u)
{
int readValue[3];
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 3, sizeof(int));
outModel->meshes[(*primitiveIndex)].normals[(a*3) + 0] = (float)readValue[0];
outModel->meshes[(*primitiveIndex)].normals[(a*3) + 1] = (float)readValue[1];
outModel->meshes[(*primitiveIndex)].normals[(a*3) + 2] = (float)readValue[2];
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short normals
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF normals must be float or int", fileName);
}
for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
{
Vector3 normal = {
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 0)],
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 1)],
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 2)],
};
normal = Vector3Transform(normal, currentTransform);
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 0)] = normal.x;
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 1)] = normal.y;
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 2)] = normal.z;
}
memcpy(outModel->meshes[(*primitiveIndex)].animNormals, outModel->meshes[(*primitiveIndex)].normals, bufferSize);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_texcoord)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
if (acc->component_type == cgltf_component_type_r_32f)
{
outModel->meshes[(*primitiveIndex)].texcoords = RL_MALLOC(acc->count*2*sizeof(float));
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].texcoords + (a*2), 2, sizeof(float));
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short texture coordinates
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF texture coordinates must be float", fileName);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
LoadGLTFBoneAttribute(outModel, acc, data, *primitiveIndex);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
outModel->meshes[(*primitiveIndex)].boneWeights = RL_MALLOC(acc->count*4*sizeof(float));
if (acc->component_type == cgltf_component_type_r_32f)
{
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].boneWeights + (a*4), 4, sizeof(float));
}
}
else if (acc->component_type == cgltf_component_type_r_32u)
{
unsigned int readValue[4];
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 4, sizeof(unsigned int));
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 0] = (float)readValue[0];
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 1] = (float)readValue[1];
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 2] = (float)readValue[2];
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 3] = (float)readValue[3];
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short weights
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF normals must be float or int", fileName);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_color)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
outModel->meshes[(*primitiveIndex)].colors = RL_MALLOC(acc->count*4*sizeof(unsigned char));
if (acc->component_type == cgltf_component_type_r_8u)
{
for (int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].colors + (a*4), 4, sizeof(unsigned char));
}
}
if (acc->component_type == cgltf_component_type_r_16u)
{
TRACELOG(LOG_WARNING, "MODEL: [%s] converting glTF colors to unsigned char", fileName);
for (int a = 0; a < acc->count; a++)
{
unsigned short readValue[4];
for (int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 4, sizeof(unsigned short));
// 257 = 65535/255
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 0] = (unsigned char)(readValue[0]/257);
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 1] = (unsigned char)(readValue[1]/257);
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 2] = (unsigned char)(readValue[2]/257);
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 3] = (unsigned char)(readValue[3]/257);
}
}
}
else
{
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF colors must be uchar or ushort", fileName);
}
}
}
cgltf_accessor *acc = mesh->primitives[p].indices;
LoadGLTFModelIndices(outModel, acc, *primitiveIndex);
if (mesh->primitives[p].material)
{
// Compute the offset
outModel->meshMaterial[(*primitiveIndex)] = (int)(mesh->primitives[p].material - data->materials);
}
else
{
outModel->meshMaterial[(*primitiveIndex)] = outModel->materialCount - 1;
}
BindGLTFPrimitiveToBones(outModel, data, *primitiveIndex);
(*primitiveIndex) = (*primitiveIndex) + 1;
}
}
static void ProcessGLTFNode(cgltf_data *data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char* fileName)
{
Matrix nodeTransform = { node->matrix[0], node->matrix[4], node->matrix[8], node->matrix[12],
node->matrix[1], node->matrix[5], node->matrix[9], node->matrix[13],
node->matrix[2], node->matrix[6], node->matrix[10], node->matrix[14],
node->matrix[3], node->matrix[7], node->matrix[11], node->matrix[15] };
currentTransform = MatrixMultiply(nodeTransform, currentTransform);
if(node->mesh != NULL)
{
ProcessGLTFMesh(data, node->mesh, outModel, currentTransform, primitiveIndex, fileName);
}
for(unsigned int i = 0; i < node->children_count; i++)
{
ProcessGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName);
}
}
static void GetPrimitiveCount(cgltf_node* node, int* outCount)
{
if(node->mesh != NULL)
{
*outCount += node->mesh->primitives_count;
}
for(unsigned int i = 0; i < node->children_count; i++)
{
GetPrimitiveCount(node->children[i], outCount);
}
}
// LoadGLTF loads in model data from given filename, supporting both .gltf and .glb
static Model LoadGLTF(const char *fileName)
{
@ -4453,7 +4209,7 @@ static Model LoadGLTF(const char *fileName)
int primitivesCount = 0;
for (unsigned int i = 0; i < data->scene->nodes_count; i++)
{
GetPrimitiveCount(data->scene->nodes[i], &primitivesCount);
GetGLTFPrimitiveCount(data->scene->nodes[i], &primitivesCount);
}
// Process glTF data and map to model
@ -4473,7 +4229,7 @@ static Model LoadGLTF(const char *fileName)
for(unsigned int i = 0; i < data->scene->nodes_count; i++)
{
Matrix staticTransform = MatrixIdentity();
ProcessGLTFNode(data, data->scene->nodes[i], &model, staticTransform, &primitiveIndex, fileName);
LoadGLTFNode(data, data->scene->nodes[i], &model, staticTransform, &primitiveIndex, fileName);
}
cgltf_free(data);
@ -4985,4 +4741,252 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
return animations;
}
void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char* fileName)
{
for (unsigned int p = 0; p < mesh->primitives_count; p++)
{
for (unsigned int j = 0; j < mesh->primitives[p].attributes_count; j++)
{
if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_position)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
outModel->meshes[(*primitiveIndex)].vertexCount = (int)acc->count;
int bufferSize = outModel->meshes[(*primitiveIndex)].vertexCount*3*sizeof(float);
outModel->meshes[(*primitiveIndex)].vertices = RL_MALLOC(bufferSize);
outModel->meshes[(*primitiveIndex)].animVertices = RL_MALLOC(bufferSize);
if (acc->component_type == cgltf_component_type_r_32f)
{
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].vertices + (a*3), 3, sizeof(float));
}
}
else if (acc->component_type == cgltf_component_type_r_32u)
{
int readValue[3];
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 3, sizeof(int));
outModel->meshes[(*primitiveIndex)].vertices[(a*3) + 0] = (float)readValue[0];
outModel->meshes[(*primitiveIndex)].vertices[(a*3) + 1] = (float)readValue[1];
outModel->meshes[(*primitiveIndex)].vertices[(a*3) + 2] = (float)readValue[2];
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short vertices
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF vertices must be float or int", fileName);
}
for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
{
Vector3 vertex = {
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 0)],
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 1)],
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 2)],
};
vertex = Vector3Transform(vertex, currentTransform);
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 0)] = vertex.x;
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 1)] = vertex.y;
outModel->meshes[(*primitiveIndex)].vertices[(v * 3 + 2)] = vertex.z;
}
memcpy(outModel->meshes[(*primitiveIndex)].animVertices, outModel->meshes[(*primitiveIndex)].vertices, bufferSize);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_normal)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
int bufferSize = (int)(acc->count*3*sizeof(float));
outModel->meshes[(*primitiveIndex)].normals = RL_MALLOC(bufferSize);
outModel->meshes[(*primitiveIndex)].animNormals = RL_MALLOC(bufferSize);
if (acc->component_type == cgltf_component_type_r_32f)
{
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].normals + (a*3), 3, sizeof(float));
}
}
else if (acc->component_type == cgltf_component_type_r_32u)
{
int readValue[3];
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 3, sizeof(int));
outModel->meshes[(*primitiveIndex)].normals[(a*3) + 0] = (float)readValue[0];
outModel->meshes[(*primitiveIndex)].normals[(a*3) + 1] = (float)readValue[1];
outModel->meshes[(*primitiveIndex)].normals[(a*3) + 2] = (float)readValue[2];
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short normals
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF normals must be float or int", fileName);
}
for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
{
Vector3 normal = {
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 0)],
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 1)],
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 2)],
};
normal = Vector3Transform(normal, currentTransform);
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 0)] = normal.x;
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 1)] = normal.y;
outModel->meshes[(*primitiveIndex)].normals[(v * 3 + 2)] = normal.z;
}
memcpy(outModel->meshes[(*primitiveIndex)].animNormals, outModel->meshes[(*primitiveIndex)].normals, bufferSize);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_texcoord)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
if (acc->component_type == cgltf_component_type_r_32f)
{
outModel->meshes[(*primitiveIndex)].texcoords = RL_MALLOC(acc->count*2*sizeof(float));
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].texcoords + (a*2), 2, sizeof(float));
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short texture coordinates
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF texture coordinates must be float", fileName);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_joints)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
LoadGLTFBoneAttribute(outModel, acc, data, *primitiveIndex);
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_weights)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
outModel->meshes[(*primitiveIndex)].boneWeights = RL_MALLOC(acc->count*4*sizeof(float));
if (acc->component_type == cgltf_component_type_r_32f)
{
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].boneWeights + (a*4), 4, sizeof(float));
}
}
else if (acc->component_type == cgltf_component_type_r_32u)
{
unsigned int readValue[4];
for (unsigned int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 4, sizeof(unsigned int));
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 0] = (float)readValue[0];
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 1] = (float)readValue[1];
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 2] = (float)readValue[2];
outModel->meshes[(*primitiveIndex)].boneWeights[(a*4) + 3] = (float)readValue[3];
}
}
else
{
// TODO: Support normalized unsigned byte/unsigned short weights
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF normals must be float or int", fileName);
}
}
else if (mesh->primitives[p].attributes[j].type == cgltf_attribute_type_color)
{
cgltf_accessor *acc = mesh->primitives[p].attributes[j].data;
outModel->meshes[(*primitiveIndex)].colors = RL_MALLOC(acc->count*4*sizeof(unsigned char));
if (acc->component_type == cgltf_component_type_r_8u)
{
for (int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, outModel->meshes[(*primitiveIndex)].colors + (a*4), 4, sizeof(unsigned char));
}
}
if (acc->component_type == cgltf_component_type_r_16u)
{
TRACELOG(LOG_WARNING, "MODEL: [%s] converting glTF colors to unsigned char", fileName);
for (int a = 0; a < acc->count; a++)
{
unsigned short readValue[4];
for (int a = 0; a < acc->count; a++)
{
GLTFReadValue(acc, a, readValue, 4, sizeof(unsigned short));
// 257 = 65535/255
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 0] = (unsigned char)(readValue[0]/257);
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 1] = (unsigned char)(readValue[1]/257);
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 2] = (unsigned char)(readValue[2]/257);
outModel->meshes[(*primitiveIndex)].colors[(a*4) + 3] = (unsigned char)(readValue[3]/257);
}
}
}
else
{
TRACELOG(LOG_WARNING, "MODEL: [%s] glTF colors must be uchar or ushort", fileName);
}
}
}
cgltf_accessor *acc = mesh->primitives[p].indices;
LoadGLTFModelIndices(outModel, acc, *primitiveIndex);
if (mesh->primitives[p].material)
{
// Compute the offset
outModel->meshMaterial[(*primitiveIndex)] = (int)(mesh->primitives[p].material - data->materials);
}
else
{
outModel->meshMaterial[(*primitiveIndex)] = outModel->materialCount - 1;
}
BindGLTFPrimitiveToBones(outModel, data, *primitiveIndex);
(*primitiveIndex) = (*primitiveIndex) + 1;
}
}
void LoadGLTFNode(cgltf_data* data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char* fileName)
{
Matrix nodeTransform = { node->matrix[0], node->matrix[4], node->matrix[8], node->matrix[12],
node->matrix[1], node->matrix[5], node->matrix[9], node->matrix[13],
node->matrix[2], node->matrix[6], node->matrix[10], node->matrix[14],
node->matrix[3], node->matrix[7], node->matrix[11], node->matrix[15] };
currentTransform = MatrixMultiply(nodeTransform, currentTransform);
if(node->mesh != NULL)
{
LoadGLTFMesh(data, node->mesh, outModel, currentTransform, primitiveIndex, fileName);
}
for(unsigned int i = 0; i < node->children_count; i++)
{
LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName);
}
}
static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount)
{
if(node->mesh != NULL)
{
*outCount += node->mesh->primitives_count;
}
for(unsigned int i = 0; i < node->children_count; i++)
{
GetGLTFPrimitiveCount(node->children[i], outCount);
}
}
#endif