|
|
@ -959,10 +959,14 @@ void SetModelMeshMaterial(Model *model, int meshId, int materialId) |
|
|
|
} |
|
|
|
|
|
|
|
// Load model animations from file |
|
|
|
ModelAnimation *LoadModelAnimations(const char *filename, int *animCount) |
|
|
|
ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount) |
|
|
|
{ |
|
|
|
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number |
|
|
|
#define IQM_VERSION 2 // only IQM version 2 supported |
|
|
|
|
|
|
|
unsigned int fileSize = 0; |
|
|
|
unsigned char *fileData = LoadFileData(fileName, &fileSize); |
|
|
|
unsigned char *fileDataPtr = fileData; |
|
|
|
|
|
|
|
typedef struct IQMHeader { |
|
|
|
char magic[16]; |
|
|
@ -995,72 +999,66 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount) |
|
|
|
unsigned int flags; |
|
|
|
} IQMAnim; |
|
|
|
|
|
|
|
FILE *iqmFile = NULL; |
|
|
|
IQMHeader iqm; |
|
|
|
|
|
|
|
iqmFile = fopen(filename,"rb"); |
|
|
|
|
|
|
|
if (!iqmFile) |
|
|
|
{ |
|
|
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", filename); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
// In case file can not be read, return an empty model |
|
|
|
if (fileDataPtr == NULL) return NULL; |
|
|
|
|
|
|
|
// Read IQM header |
|
|
|
fread(&iqm, sizeof(IQMHeader), 1, iqmFile); |
|
|
|
IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr; |
|
|
|
|
|
|
|
if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC))) |
|
|
|
if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0) |
|
|
|
{ |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", filename); |
|
|
|
fclose(iqmFile); |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (iqm.version != IQM_VERSION) |
|
|
|
if (iqmHeader->version != IQM_VERSION) |
|
|
|
{ |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version incorrect", filename); |
|
|
|
fclose(iqmFile); |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
// Get bones data |
|
|
|
IQMPose *poses = RL_MALLOC(iqm.num_poses*sizeof(IQMPose)); |
|
|
|
fseek(iqmFile, iqm.ofs_poses, SEEK_SET); |
|
|
|
fread(poses, iqm.num_poses*sizeof(IQMPose), 1, iqmFile); |
|
|
|
IQMPose *poses = RL_MALLOC(iqmHeader->num_poses*sizeof(IQMPose)); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_poses, SEEK_SET); |
|
|
|
//fread(poses, iqmHeader->num_poses*sizeof(IQMPose), 1, iqmFile); |
|
|
|
memcpy(poses, fileDataPtr + iqmHeader->ofs_poses, iqmHeader->num_poses*sizeof(IQMPose)); |
|
|
|
|
|
|
|
// Get animations data |
|
|
|
*animCount = iqm.num_anims; |
|
|
|
IQMAnim *anim = RL_MALLOC(iqm.num_anims*sizeof(IQMAnim)); |
|
|
|
fseek(iqmFile, iqm.ofs_anims, SEEK_SET); |
|
|
|
fread(anim, iqm.num_anims*sizeof(IQMAnim), 1, iqmFile); |
|
|
|
ModelAnimation *animations = RL_MALLOC(iqm.num_anims*sizeof(ModelAnimation)); |
|
|
|
*animCount = iqmHeader->num_anims; |
|
|
|
IQMAnim *anim = RL_MALLOC(iqmHeader->num_anims*sizeof(IQMAnim)); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_anims, SEEK_SET); |
|
|
|
//fread(anim, iqmHeader->num_anims*sizeof(IQMAnim), 1, iqmFile); |
|
|
|
memcpy(anim, fileDataPtr + iqmHeader->ofs_anims, iqmHeader->num_anims*sizeof(IQMAnim)); |
|
|
|
|
|
|
|
ModelAnimation *animations = RL_MALLOC(iqmHeader->num_anims*sizeof(ModelAnimation)); |
|
|
|
|
|
|
|
// frameposes |
|
|
|
unsigned short *framedata = RL_MALLOC(iqm.num_frames*iqm.num_framechannels*sizeof(unsigned short)); |
|
|
|
fseek(iqmFile, iqm.ofs_frames, SEEK_SET); |
|
|
|
fread(framedata, iqm.num_frames*iqm.num_framechannels*sizeof(unsigned short), 1, iqmFile); |
|
|
|
unsigned short *framedata = RL_MALLOC(iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short)); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_frames, SEEK_SET); |
|
|
|
//fread(framedata, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short), 1, iqmFile); |
|
|
|
memcpy(framedata, fileDataPtr + iqmHeader->ofs_frames, iqmHeader->num_frames*iqmHeader->num_framechannels*sizeof(unsigned short)); |
|
|
|
|
|
|
|
for (unsigned int a = 0; a < iqm.num_anims; a++) |
|
|
|
for (unsigned int a = 0; a < iqmHeader->num_anims; a++) |
|
|
|
{ |
|
|
|
animations[a].frameCount = anim[a].num_frames; |
|
|
|
animations[a].boneCount = iqm.num_poses; |
|
|
|
animations[a].bones = RL_MALLOC(iqm.num_poses*sizeof(BoneInfo)); |
|
|
|
animations[a].boneCount = iqmHeader->num_poses; |
|
|
|
animations[a].bones = RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo)); |
|
|
|
animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *)); |
|
|
|
//animations[a].framerate = anim.framerate; // TODO: Use framerate? |
|
|
|
|
|
|
|
for (unsigned int j = 0; j < iqm.num_poses; j++) |
|
|
|
for (unsigned int j = 0; j < iqmHeader->num_poses; j++) |
|
|
|
{ |
|
|
|
strcpy(animations[a].bones[j].name, "ANIMJOINTNAME"); |
|
|
|
animations[a].bones[j].parent = poses[j].parent; |
|
|
|
} |
|
|
|
|
|
|
|
for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(iqm.num_poses*sizeof(Transform)); |
|
|
|
for (unsigned int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(iqmHeader->num_poses*sizeof(Transform)); |
|
|
|
|
|
|
|
int dcounter = anim[a].first_frame*iqm.num_framechannels; |
|
|
|
int dcounter = anim[a].first_frame*iqmHeader->num_framechannels; |
|
|
|
|
|
|
|
for (unsigned int frame = 0; frame < anim[a].num_frames; frame++) |
|
|
|
{ |
|
|
|
for (unsigned int i = 0; i < iqm.num_poses; i++) |
|
|
|
for (unsigned int i = 0; i < iqmHeader->num_poses; i++) |
|
|
|
{ |
|
|
|
animations[a].framePoses[frame][i].translation.x = poses[i].channeloffset[0]; |
|
|
|
|
|
|
@ -1161,13 +1159,13 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
RL_FREE(fileData); |
|
|
|
|
|
|
|
RL_FREE(framedata); |
|
|
|
RL_FREE(poses); |
|
|
|
RL_FREE(anim); |
|
|
|
|
|
|
|
fclose(iqmFile); |
|
|
|
|
|
|
|
return animations; |
|
|
|
} |
|
|
|
|
|
|
@ -3042,12 +3040,16 @@ static Model LoadOBJ(const char *fileName) |
|
|
|
// Load IQM mesh data |
|
|
|
static Model LoadIQM(const char *fileName) |
|
|
|
{ |
|
|
|
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number |
|
|
|
#define IQM_VERSION 2 // only IQM version 2 supported |
|
|
|
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number |
|
|
|
#define IQM_VERSION 2 // only IQM version 2 supported |
|
|
|
|
|
|
|
#define BONE_NAME_LENGTH 32 // BoneInfo name string length |
|
|
|
#define MESH_NAME_LENGTH 32 // Mesh name string length |
|
|
|
#define MATERIAL_NAME_LENGTH 32 // Material name string length |
|
|
|
|
|
|
|
unsigned int fileSize = 0; |
|
|
|
unsigned char *fileData = LoadFileData(fileName, &fileSize); |
|
|
|
unsigned char *fileDataPtr = fileData; |
|
|
|
|
|
|
|
// IQM file structs |
|
|
|
//----------------------------------------------------------------------------------- |
|
|
@ -3134,13 +3136,10 @@ static Model LoadIQM(const char *fileName) |
|
|
|
|
|
|
|
Model model = { 0 }; |
|
|
|
|
|
|
|
FILE *iqmFile = NULL; |
|
|
|
IQMHeader iqm; |
|
|
|
|
|
|
|
IQMMesh *imesh; |
|
|
|
IQMTriangle *tri; |
|
|
|
IQMVertexArray *va; |
|
|
|
IQMJoint *ijoint; |
|
|
|
IQMMesh *imesh = NULL; |
|
|
|
IQMTriangle *tri = NULL; |
|
|
|
IQMVertexArray *va = NULL; |
|
|
|
IQMJoint *ijoint = NULL; |
|
|
|
|
|
|
|
float *vertex = NULL; |
|
|
|
float *normal = NULL; |
|
|
@ -3148,36 +3147,33 @@ static Model LoadIQM(const char *fileName) |
|
|
|
char *blendi = NULL; |
|
|
|
unsigned char *blendw = NULL; |
|
|
|
|
|
|
|
iqmFile = fopen(fileName, "rb"); |
|
|
|
|
|
|
|
if (iqmFile == NULL) |
|
|
|
{ |
|
|
|
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open IQM file", fileName); |
|
|
|
return model; |
|
|
|
} |
|
|
|
// In case file can not be read, return an empty model |
|
|
|
if (fileDataPtr == NULL) return model; |
|
|
|
|
|
|
|
fread(&iqm, sizeof(IQMHeader), 1, iqmFile); // Read IQM header |
|
|
|
// Read IQM header |
|
|
|
IQMHeader *iqmHeader = (IQMHeader *)fileDataPtr; |
|
|
|
|
|
|
|
if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC))) |
|
|
|
if (memcmp(iqmHeader->magic, IQM_MAGIC, sizeof(IQM_MAGIC)) != 0) |
|
|
|
{ |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file is not a valid model", fileName); |
|
|
|
fclose(iqmFile); |
|
|
|
return model; |
|
|
|
} |
|
|
|
|
|
|
|
if (iqm.version != IQM_VERSION) |
|
|
|
if (iqmHeader->version != IQM_VERSION) |
|
|
|
{ |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqm.version); |
|
|
|
fclose(iqmFile); |
|
|
|
TRACELOG(LOG_WARNING, "MODEL: [%s] IQM file version not supported (%i)", fileName, iqmHeader->version); |
|
|
|
return model; |
|
|
|
} |
|
|
|
|
|
|
|
//fileDataPtr += sizeof(IQMHeader); // Move file data pointer |
|
|
|
|
|
|
|
// Meshes data processing |
|
|
|
imesh = RL_MALLOC(sizeof(IQMMesh)*iqm.num_meshes); |
|
|
|
fseek(iqmFile, iqm.ofs_meshes, SEEK_SET); |
|
|
|
fread(imesh, sizeof(IQMMesh)*iqm.num_meshes, 1, iqmFile); |
|
|
|
imesh = RL_MALLOC(sizeof(IQMMesh)*iqmHeader->num_meshes); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_meshes, SEEK_SET); |
|
|
|
//fread(imesh, sizeof(IQMMesh)*iqmHeader->num_meshes, 1, iqmFile); |
|
|
|
memcpy(imesh, fileDataPtr + iqmHeader->ofs_meshes, iqmHeader->num_meshes*sizeof(IQMMesh)); |
|
|
|
|
|
|
|
model.meshCount = iqm.num_meshes; |
|
|
|
model.meshCount = iqmHeader->num_meshes; |
|
|
|
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh)); |
|
|
|
|
|
|
|
model.materialCount = model.meshCount; |
|
|
@ -3189,11 +3185,13 @@ static Model LoadIQM(const char *fileName) |
|
|
|
|
|
|
|
for (int i = 0; i < model.meshCount; i++) |
|
|
|
{ |
|
|
|
fseek(iqmFile, iqm.ofs_text + imesh[i].name, SEEK_SET); |
|
|
|
fread(name, sizeof(char)*MESH_NAME_LENGTH, 1, iqmFile); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_text + imesh[i].name, SEEK_SET); |
|
|
|
//fread(name, sizeof(char)*MESH_NAME_LENGTH, 1, iqmFile); |
|
|
|
memcpy(name, fileDataPtr + iqmHeader->ofs_text + imesh[i].name, MESH_NAME_LENGTH*sizeof(char)); |
|
|
|
|
|
|
|
fseek(iqmFile, iqm.ofs_text + imesh[i].material, SEEK_SET); |
|
|
|
fread(material, sizeof(char)*MATERIAL_NAME_LENGTH, 1, iqmFile); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_text + imesh[i].material, SEEK_SET); |
|
|
|
//fread(material, sizeof(char)*MATERIAL_NAME_LENGTH, 1, iqmFile); |
|
|
|
memcpy(material, fileDataPtr + iqmHeader->ofs_text + imesh[i].material, MATERIAL_NAME_LENGTH*sizeof(char)); |
|
|
|
|
|
|
|
model.materials[i] = LoadMaterialDefault(); |
|
|
|
|
|
|
@ -3220,9 +3218,10 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} |
|
|
|
|
|
|
|
// Triangles data processing |
|
|
|
tri = RL_MALLOC(iqm.num_triangles*sizeof(IQMTriangle)); |
|
|
|
fseek(iqmFile, iqm.ofs_triangles, SEEK_SET); |
|
|
|
fread(tri, iqm.num_triangles*sizeof(IQMTriangle), 1, iqmFile); |
|
|
|
tri = RL_MALLOC(iqmHeader->num_triangles*sizeof(IQMTriangle)); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_triangles, SEEK_SET); |
|
|
|
//fread(tri, iqmHeader->num_triangles*sizeof(IQMTriangle), 1, iqmFile); |
|
|
|
memcpy(tri, fileDataPtr + iqmHeader->ofs_triangles, iqmHeader->num_triangles*sizeof(IQMTriangle)); |
|
|
|
|
|
|
|
for (int m = 0; m < model.meshCount; m++) |
|
|
|
{ |
|
|
@ -3239,21 +3238,23 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} |
|
|
|
|
|
|
|
// Vertex arrays data processing |
|
|
|
va = RL_MALLOC(iqm.num_vertexarrays*sizeof(IQMVertexArray)); |
|
|
|
fseek(iqmFile, iqm.ofs_vertexarrays, SEEK_SET); |
|
|
|
fread(va, iqm.num_vertexarrays*sizeof(IQMVertexArray), 1, iqmFile); |
|
|
|
va = RL_MALLOC(iqmHeader->num_vertexarrays*sizeof(IQMVertexArray)); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_vertexarrays, SEEK_SET); |
|
|
|
//fread(va, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray), 1, iqmFile); |
|
|
|
memcpy(va, fileDataPtr + iqmHeader->ofs_vertexarrays, iqmHeader->num_vertexarrays*sizeof(IQMVertexArray)); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < iqm.num_vertexarrays; i++) |
|
|
|
for (unsigned int i = 0; i < iqmHeader->num_vertexarrays; i++) |
|
|
|
{ |
|
|
|
switch (va[i].type) |
|
|
|
{ |
|
|
|
case IQM_POSITION: |
|
|
|
{ |
|
|
|
vertex = RL_MALLOC(iqm.num_vertexes*3*sizeof(float)); |
|
|
|
fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
fread(vertex, iqm.num_vertexes*3*sizeof(float), 1, iqmFile); |
|
|
|
vertex = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float)); |
|
|
|
//fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
//fread(vertex, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile); |
|
|
|
memcpy(vertex, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float)); |
|
|
|
|
|
|
|
for (unsigned int m = 0; m < iqm.num_meshes; m++) |
|
|
|
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++) |
|
|
|
{ |
|
|
|
int vCounter = 0; |
|
|
|
for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++) |
|
|
@ -3266,11 +3267,12 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} break; |
|
|
|
case IQM_NORMAL: |
|
|
|
{ |
|
|
|
normal = RL_MALLOC(iqm.num_vertexes*3*sizeof(float)); |
|
|
|
fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
fread(normal, iqm.num_vertexes*3*sizeof(float), 1, iqmFile); |
|
|
|
normal = RL_MALLOC(iqmHeader->num_vertexes*3*sizeof(float)); |
|
|
|
//fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
//fread(normal, iqmHeader->num_vertexes*3*sizeof(float), 1, iqmFile); |
|
|
|
memcpy(normal, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*3*sizeof(float)); |
|
|
|
|
|
|
|
for (unsigned int m = 0; m < iqm.num_meshes; m++) |
|
|
|
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++) |
|
|
|
{ |
|
|
|
int vCounter = 0; |
|
|
|
for (unsigned int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++) |
|
|
@ -3283,11 +3285,12 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} break; |
|
|
|
case IQM_TEXCOORD: |
|
|
|
{ |
|
|
|
text = RL_MALLOC(iqm.num_vertexes*2*sizeof(float)); |
|
|
|
fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
fread(text, iqm.num_vertexes*2*sizeof(float), 1, iqmFile); |
|
|
|
text = RL_MALLOC(iqmHeader->num_vertexes*2*sizeof(float)); |
|
|
|
//fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
//fread(text, iqmHeader->num_vertexes*2*sizeof(float), 1, iqmFile); |
|
|
|
memcpy(text, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*2*sizeof(float)); |
|
|
|
|
|
|
|
for (unsigned int m = 0; m < iqm.num_meshes; m++) |
|
|
|
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++) |
|
|
|
{ |
|
|
|
int vCounter = 0; |
|
|
|
for (unsigned int i = imesh[m].first_vertex*2; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*2; i++) |
|
|
@ -3299,11 +3302,12 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} break; |
|
|
|
case IQM_BLENDINDEXES: |
|
|
|
{ |
|
|
|
blendi = RL_MALLOC(iqm.num_vertexes*4*sizeof(char)); |
|
|
|
fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
fread(blendi, iqm.num_vertexes*4*sizeof(char), 1, iqmFile); |
|
|
|
blendi = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(char)); |
|
|
|
//fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
//fread(blendi, iqmHeader->num_vertexes*4*sizeof(char), 1, iqmFile); |
|
|
|
memcpy(blendi, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(char)); |
|
|
|
|
|
|
|
for (unsigned int m = 0; m < iqm.num_meshes; m++) |
|
|
|
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++) |
|
|
|
{ |
|
|
|
int boneCounter = 0; |
|
|
|
for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++) |
|
|
@ -3315,11 +3319,12 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} break; |
|
|
|
case IQM_BLENDWEIGHTS: |
|
|
|
{ |
|
|
|
blendw = RL_MALLOC(iqm.num_vertexes*4*sizeof(unsigned char)); |
|
|
|
fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
fread(blendw, iqm.num_vertexes*4*sizeof(unsigned char), 1, iqmFile); |
|
|
|
blendw = RL_MALLOC(iqmHeader->num_vertexes*4*sizeof(unsigned char)); |
|
|
|
//fseek(iqmFile, va[i].offset, SEEK_SET); |
|
|
|
//fread(blendw, iqmHeader->num_vertexes*4*sizeof(unsigned char), 1, iqmFile); |
|
|
|
memcpy(blendw, fileDataPtr + va[i].offset, iqmHeader->num_vertexes*4*sizeof(unsigned char)); |
|
|
|
|
|
|
|
for (unsigned int m = 0; m < iqm.num_meshes; m++) |
|
|
|
for (unsigned int m = 0; m < iqmHeader->num_meshes; m++) |
|
|
|
{ |
|
|
|
int boneCounter = 0; |
|
|
|
for (unsigned int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++) |
|
|
@ -3333,20 +3338,22 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} |
|
|
|
|
|
|
|
// Bones (joints) data processing |
|
|
|
ijoint = RL_MALLOC(iqm.num_joints*sizeof(IQMJoint)); |
|
|
|
fseek(iqmFile, iqm.ofs_joints, SEEK_SET); |
|
|
|
fread(ijoint, iqm.num_joints*sizeof(IQMJoint), 1, iqmFile); |
|
|
|
ijoint = RL_MALLOC(iqmHeader->num_joints*sizeof(IQMJoint)); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_joints, SEEK_SET); |
|
|
|
//fread(ijoint, iqmHeader->num_joints*sizeof(IQMJoint), 1, iqmFile); |
|
|
|
memcpy(ijoint, fileDataPtr + iqmHeader->ofs_joints, iqmHeader->num_joints*sizeof(IQMJoint)); |
|
|
|
|
|
|
|
model.boneCount = iqm.num_joints; |
|
|
|
model.bones = RL_MALLOC(iqm.num_joints*sizeof(BoneInfo)); |
|
|
|
model.bindPose = RL_MALLOC(iqm.num_joints*sizeof(Transform)); |
|
|
|
model.boneCount = iqmHeader->num_joints; |
|
|
|
model.bones = RL_MALLOC(iqmHeader->num_joints*sizeof(BoneInfo)); |
|
|
|
model.bindPose = RL_MALLOC(iqmHeader->num_joints*sizeof(Transform)); |
|
|
|
|
|
|
|
for (unsigned int i = 0; i < iqm.num_joints; i++) |
|
|
|
for (unsigned int i = 0; i < iqmHeader->num_joints; i++) |
|
|
|
{ |
|
|
|
// Bones |
|
|
|
model.bones[i].parent = ijoint[i].parent; |
|
|
|
fseek(iqmFile, iqm.ofs_text + ijoint[i].name, SEEK_SET); |
|
|
|
fread(model.bones[i].name, BONE_NAME_LENGTH*sizeof(char), 1, iqmFile); |
|
|
|
//fseek(iqmFile, iqmHeader->ofs_text + ijoint[i].name, SEEK_SET); |
|
|
|
//fread(model.bones[i].name, BONE_NAME_LENGTH*sizeof(char), 1, iqmFile); |
|
|
|
memcpy(model.bones[i].name, fileDataPtr + iqmHeader->ofs_text + ijoint[i].name, BONE_NAME_LENGTH*sizeof(char)); |
|
|
|
|
|
|
|
// Bind pose (base pose) |
|
|
|
model.bindPose[i].translation.x = ijoint[i].translate[0]; |
|
|
@ -3375,7 +3382,8 @@ static Model LoadIQM(const char *fileName) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fclose(iqmFile); |
|
|
|
RL_FREE(fileData); |
|
|
|
|
|
|
|
RL_FREE(imesh); |
|
|
|
RL_FREE(tri); |
|
|
|
RL_FREE(va); |
|
|
@ -3490,7 +3498,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *image, const char *texPath, Co |
|
|
|
|
|
|
|
int width, height; |
|
|
|
unsigned char *raw = stbi_load_from_memory(data, size, &width, &height, NULL, 4); |
|
|
|
free(data); |
|
|
|
RL_FREE(data); |
|
|
|
|
|
|
|
rimage.data = raw; |
|
|
|
rimage.width = width; |
|
|
@ -3524,7 +3532,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *image, const char *texPath, Co |
|
|
|
|
|
|
|
int width, height; |
|
|
|
unsigned char *raw = stbi_load_from_memory(data, (int)image->buffer_view->size, &width, &height, NULL, 4); |
|
|
|
free(data); |
|
|
|
RL_FREE(data); |
|
|
|
|
|
|
|
rimage.data = raw; |
|
|
|
rimage.width = width; |
|
|
@ -3688,14 +3696,14 @@ static Model LoadGLTF(const char *fileName) |
|
|
|
{ |
|
|
|
cgltf_accessor *acc = data->meshes[i].primitives[p].attributes[j].data; |
|
|
|
model.meshes[primitiveIndex].vertexCount = (int)acc->count; |
|
|
|
model.meshes[primitiveIndex].vertices = RL_MALLOC(k">sizeof(float)*model.meshes[primitiveIndex].vertexCount*3); |
|
|
|
model.meshes[primitiveIndex].vertices = RL_MALLOC(model.meshes[primitiveIndex].vertexCount*3*sizeof(float)); |
|
|
|
|
|
|
|
LOAD_ACCESSOR(float, 3, acc, model.meshes[primitiveIndex].vertices) |
|
|
|
} |
|
|
|
else if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_normal) |
|
|
|
{ |
|
|
|
cgltf_accessor *acc = data->meshes[i].primitives[p].attributes[j].data; |
|
|
|
model.meshes[primitiveIndex].normals = RL_MALLOC(k">sizeof(float)*acc->count*3); |
|
|
|
model.meshes[primitiveIndex].normals = RL_MALLOC(acc->count*3*sizeof(float)); |
|
|
|
|
|
|
|
LOAD_ACCESSOR(float, 3, acc, model.meshes[primitiveIndex].normals) |
|
|
|
} |
|
|
@ -3705,7 +3713,7 @@ static Model LoadGLTF(const char *fileName) |
|
|
|
|
|
|
|
if (acc->component_type == cgltf_component_type_r_32f) |
|
|
|
{ |
|
|
|
model.meshes[primitiveIndex].texcoords = RL_MALLOC(k">sizeof(float)*acc->count*2); |
|
|
|
model.meshes[primitiveIndex].texcoords = RL_MALLOC(acc->count*2*sizeof(float)); |
|
|
|
LOAD_ACCESSOR(float, 2, acc, model.meshes[primitiveIndex].texcoords) |
|
|
|
} |
|
|
|
else |
|
|
@ -3723,7 +3731,7 @@ static Model LoadGLTF(const char *fileName) |
|
|
|
if (acc->component_type == cgltf_component_type_r_16u) |
|
|
|
{ |
|
|
|
model.meshes[primitiveIndex].triangleCount = (int)acc->count/3; |
|
|
|
model.meshes[primitiveIndex].indices = RL_MALLOC(k">sizeof(unsigned short)*model.meshes[primitiveIndex].triangleCount*3); |
|
|
|
model.meshes[primitiveIndex].indices = RL_MALLOC(model.meshes[primitiveIndex].triangleCount*3*sizeof(unsigned short)); |
|
|
|
LOAD_ACCESSOR(unsigned short, 1, acc, model.meshes[primitiveIndex].indices) |
|
|
|
} |
|
|
|
else |
|
|
|