riqm.h 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. /**********************************************************************************************
  2. *
  3. * riqm - InterQuake Model format (IQM) loader for animated meshes
  4. *
  5. * CONFIGURATION:
  6. *
  7. * #define RIQM_IMPLEMENTATION
  8. * Generates the implementation of the library into the included file.
  9. * If not defined, the library is in header only mode and can be included in other headers
  10. * or source files without problems. But only ONE file should hold the implementation.
  11. *
  12. *
  13. * LICENSE: zlib/libpng
  14. *
  15. * Copyright (c) 2018 Jonas Daeyaert (@culacant) and Ramon Santamaria (@raysan5)
  16. *
  17. * This software is provided "as-is", without any express or implied warranty. In no event
  18. * will the authors be held liable for any damages arising from the use of this software.
  19. *
  20. * Permission is granted to anyone to use this software for any purpose, including commercial
  21. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  22. *
  23. * 1. The origin of this software must not be misrepresented; you must not claim that you
  24. * wrote the original software. If you use this software in a product, an acknowledgment
  25. * in the product documentation would be appreciated but is not required.
  26. *
  27. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  28. * as being the original software.
  29. *
  30. * 3. This notice may not be removed or altered from any source distribution.
  31. *
  32. **********************************************************************************************/
  33. #ifndef RIQM_H
  34. #define RIQM_H
  35. //#define RIQM_STATIC
  36. #ifdef RIQM_STATIC
  37. #define RIQMDEF static // Functions just visible to module including this file
  38. #else
  39. #ifdef __cplusplus
  40. #define RIQMDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
  41. #else
  42. #define RIQMDEF extern // Functions visible from other files
  43. #endif
  44. #endif
  45. //----------------------------------------------------------------------------------
  46. // Types and Structures Definition
  47. //----------------------------------------------------------------------------------
  48. #define JOINT_NAME_LENGTH 32 // Joint name string length
  49. #define MESH_NAME_LENGTH 32 // Mesh name string length
  50. typedef struct Joint {
  51. char name[JOINT_NAME_LENGTH];
  52. int parent;
  53. } Joint;
  54. typedef struct Pose {
  55. Vector3 translation;
  56. Quaternion rotation;
  57. Vector3 scale;
  58. } Pose;
  59. typedef struct Animation {
  60. int jointCount;
  61. Joint *joints; // NOTE: Joints in anims do not have names
  62. int frameCount;
  63. float framerate;
  64. Pose **framepose;
  65. } Animation;
  66. typedef struct AnimatedMesh {
  67. //Mesh mesh;
  68. // Mesh struct defines:
  69. //-------------------------
  70. int vertexCount;
  71. int triangleCount;
  72. float *vertices;
  73. float *normals;
  74. float *texcoords;
  75. unsigned short *triangles; //equivalent to mes.indices
  76. unsigned int vaoId;
  77. unsigned int vboId[7];
  78. //-------------------------
  79. char name[MESH_NAME_LENGTH];
  80. float *animVertices;
  81. float *animNormals;
  82. float *weightBias;
  83. int *weightId;
  84. } AnimatedMesh;
  85. typedef struct AnimatedModel {
  86. int meshCount;
  87. AnimatedMesh *mesh;
  88. int materialCount;
  89. int *meshMaterialId;
  90. Material *materials;
  91. int jointCount;
  92. Joint *joints;
  93. Pose *basepose;
  94. Matrix transform;
  95. } AnimatedModel;
  96. //----------------------------------------------------------------------------------
  97. // Module Functions Declaration
  98. //----------------------------------------------------------------------------------
  99. // Loading/Unloading functions
  100. RIQMDEF AnimatedModel LoadAnimatedModel(const char *filename);
  101. RIQMDEF void UnloadAnimatedModel(AnimatedModel model);
  102. RIQMDEF Animation LoadAnimation(const char *filename);
  103. RIQMDEF void UnloadAnimation(Animation anim);
  104. RIQMDEF AnimatedModel AnimatedModelAddTexture(AnimatedModel model,const char *filename); // GENERIC!
  105. RIQMDEF AnimatedModel SetMeshMaterial(AnimatedModel model,int meshid, int textureid); // GENERIC!
  106. // Usage functionality
  107. RIQMDEF bool CheckSkeletonsMatch(AnimatedModel model, Animation anim);
  108. RIQMDEF void AnimateModel(AnimatedModel model, Animation anim, int frame);
  109. RIQMDEF void DrawAnimatedModel(AnimatedModel model,Vector3 position,float scale,Color tint);
  110. RIQMDEF void DrawAnimatedModelEx(AnimatedModel model,Vector3 position,Vector3 rotationAxis,float rotationAngle, Vector3 scale,Color tint);
  111. #endif // RIQM_H
  112. /***********************************************************************************
  113. *
  114. * RIQM IMPLEMENTATION
  115. *
  116. ************************************************************************************/
  117. #if defined(RIQM_IMPLEMENTATION)
  118. //#include "utils.h" // Required for: fopen() Android mapping
  119. #include <stdio.h> // Required for: FILE, fopen(), fclose(), feof(), fseek(), fread()
  120. #include <stdlib.h> // Required for: malloc(), free()
  121. #include <string.h> // Required for: strncmp(),strcpy()
  122. #include "raymath.h" // Required for: Vector3, Quaternion functions
  123. #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
  124. #include "glad.h" // Required for OpenGL functions > TO BE REMOVED!
  125. //----------------------------------------------------------------------------------
  126. // Defines and Macros
  127. //----------------------------------------------------------------------------------
  128. #define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
  129. #define IQM_VERSION 2 // only IQM version 2 supported
  130. #define ANIMJOINTNAME "ANIMJOINT" // default joint name (used in Animation)
  131. //----------------------------------------------------------------------------------
  132. // Types and Structures Definition
  133. //----------------------------------------------------------------------------------
  134. // iqm file structs
  135. typedef struct IQMHeader {
  136. char magic[16];
  137. unsigned int version;
  138. unsigned int filesize;
  139. unsigned int flags;
  140. unsigned int num_text, ofs_text;
  141. unsigned int num_meshes, ofs_meshes;
  142. unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
  143. unsigned int num_triangles, ofs_triangles, ofs_adjacency;
  144. unsigned int num_joints, ofs_joints;
  145. unsigned int num_poses, ofs_poses;
  146. unsigned int num_anims, ofs_anims;
  147. unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
  148. unsigned int num_comment, ofs_comment;
  149. unsigned int num_extensions, ofs_extensions;
  150. } IQMHeader;
  151. typedef struct IQMMesh {
  152. unsigned int name;
  153. unsigned int material;
  154. unsigned int first_vertex, num_vertexes;
  155. unsigned int first_triangle, num_triangles;
  156. } IQMMesh;
  157. typedef struct IQMTriangle {
  158. unsigned int vertex[3];
  159. } IQMTriangle;
  160. typedef struct IQMAdjacency { // adjacency unused by default
  161. unsigned int triangle[3];
  162. } IQMAdjacency;
  163. typedef struct IQMJoint {
  164. unsigned int name;
  165. int parent;
  166. float translate[3], rotate[4], scale[3];
  167. } IQMJoint;
  168. typedef struct IQMPose {
  169. int parent;
  170. unsigned int mask;
  171. float channeloffset[10];
  172. float channelscale[10];
  173. } IQMPose;
  174. typedef struct IQMAnim {
  175. unsigned int name;
  176. unsigned int first_frame, num_frames;
  177. float framerate;
  178. unsigned int flags;
  179. } IQMAnim;
  180. typedef struct IQMVertexArray {
  181. unsigned int type;
  182. unsigned int flags;
  183. unsigned int format;
  184. unsigned int size;
  185. unsigned int offset;
  186. } IQMVertexArray;
  187. typedef struct IQMBounds { // bounds unused by default
  188. float bbmin[3], bbmax[3];
  189. float xyradius, radius;
  190. } IQMBounds;
  191. typedef enum {
  192. IQM_POSITION = 0,
  193. IQM_TEXCOORD = 1,
  194. IQM_NORMAL = 2,
  195. IQM_TANGENT = 3, // tangents unused by default
  196. IQM_BLENDINDEXES = 4,
  197. IQM_BLENDWEIGHTS = 5,
  198. IQM_COLOR = 6, // vertex colors unused by default
  199. IQM_CUSTOM = 0x10 // custom vertex values unused by default
  200. } IQMVertexType;
  201. //----------------------------------------------------------------------------------
  202. // Global Variables Definition
  203. //----------------------------------------------------------------------------------
  204. //----------------------------------------------------------------------------------
  205. // Module specific Functions Declaration
  206. //----------------------------------------------------------------------------------
  207. void rlLoadAnimatedMesh(AnimatedMesh *amesh, bool dynamic);
  208. void rlUnloadAnimatedMesh(AnimatedMesh *amesh);
  209. void rlUpdateAnimatedMesh(AnimatedMesh *amesh);
  210. void rlDrawAnimatedMesh(AnimatedMesh amesh, Material material, Matrix transform);
  211. static AnimatedModel LoadIQM(const char *filename);
  212. //----------------------------------------------------------------------------------
  213. // Module Functions Definition
  214. //----------------------------------------------------------------------------------
  215. void rlLoadAnimatedMesh(AnimatedMesh *amesh, bool dynamic)
  216. {
  217. amesh->vaoId = 0; // Vertex Array Object
  218. amesh->vboId[0] = 0; // Vertex positions VBO << these are the animated vertices in animVertices
  219. amesh->vboId[1] = 0; // Vertex texcoords VBO
  220. amesh->vboId[2] = 0; // Vertex normals VBO << these are the animated normals in animNormals
  221. amesh->vboId[3] = 0; // Vertex colors VBO
  222. amesh->vboId[4] = 0; // Vertex tangents VBO UNUSED
  223. amesh->vboId[5] = 0; // Vertex texcoords2 VBO UNUSED
  224. amesh->vboId[6] = 0; // Vertex indices VBO
  225. #if defined(GRAPHICS_API_OPENGL_11)
  226. TraceLog(LOG_WARNING, "OGL 11");
  227. #endif
  228. #if defined(GRAPHICS_API_OPENGL_21)
  229. TraceLog(LOG_WARNING, "OGL 21");
  230. #endif
  231. #if defined(GRAPHICS_API_OPENGL_33)
  232. TraceLog(LOG_WARNING, "OGL 33");
  233. #endif
  234. #if defined(GRAPHICS_API_OPENGL_ES2)
  235. TraceLog(LOG_WARNING, "OGL ES2");
  236. #endif
  237. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  238. int drawHint = GL_STATIC_DRAW;
  239. if (dynamic) drawHint = GL_DYNAMIC_DRAW;
  240. //if (vaoSupported)
  241. {
  242. // Initialize Quads VAO (Buffer A)
  243. glGenVertexArrays(1, &amesh->vaoId);
  244. glBindVertexArray(amesh->vaoId);
  245. }
  246. // NOTE: Attributes must be uploaded considering default locations points
  247. // Enable vertex attributes: position (shader-location = 0)
  248. glGenBuffers(1, &amesh->vboId[0]);
  249. glBindBuffer(GL_ARRAY_BUFFER, amesh->vboId[0]);
  250. glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*amesh->vertexCount, amesh->animVertices, drawHint);
  251. glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);
  252. glEnableVertexAttribArray(0);
  253. // Enable vertex attributes: texcoords (shader-location = 1)
  254. glGenBuffers(1, &amesh->vboId[1]);
  255. glBindBuffer(GL_ARRAY_BUFFER, amesh->vboId[1]);
  256. glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*amesh->vertexCount, amesh->texcoords, drawHint);
  257. glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0);
  258. glEnableVertexAttribArray(1);
  259. // Enable vertex attributes: normals (shader-location = 2)
  260. if (amesh->animNormals != NULL)
  261. {
  262. glGenBuffers(1, &amesh->vboId[2]);
  263. glBindBuffer(GL_ARRAY_BUFFER, amesh->vboId[2]);
  264. glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*amesh->vertexCount, amesh->animNormals, drawHint);
  265. glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0);
  266. glEnableVertexAttribArray(2);
  267. }
  268. else
  269. {
  270. // Default color vertex attribute set to WHITE
  271. glVertexAttrib3f(2, 1.0f, 1.0f, 1.0f);
  272. glDisableVertexAttribArray(2);
  273. }
  274. // colors UNUSED
  275. /*
  276. // Default color vertex attribute (shader-location = 3)
  277. if (mesh->colors != NULL)
  278. {
  279. glGenBuffers(1, &amesh->vboId[3]);
  280. glBindBuffer(GL_ARRAY_BUFFER, amesh->vboId[3]);
  281. glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh->vertexCount, mesh->colors, drawHint);
  282. glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
  283. glEnableVertexAttribArray(3);
  284. }
  285. else
  286. {
  287. // Default color vertex attribute set to WHITE
  288. glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
  289. glDisableVertexAttribArray(3);
  290. }
  291. */
  292. // colors to default
  293. glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f);
  294. glDisableVertexAttribArray(3);
  295. // tangents UNUSED
  296. /*
  297. // Default tangent vertex attribute (shader-location = 4)
  298. if (mesh->tangents != NULL)
  299. {
  300. glGenBuffers(1, &mesh->vboId[4]);
  301. glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[4]);
  302. glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*mesh->vertexCount, mesh->tangents, drawHint);
  303. glVertexAttribPointer(4, 4, GL_FLOAT, 0, 0, 0);
  304. glEnableVertexAttribArray(4);
  305. }
  306. else
  307. {
  308. // Default tangents vertex attribute
  309. glVertexAttrib4f(4, 0.0f, 0.0f, 0.0f, 0.0f);
  310. glDisableVertexAttribArray(4);
  311. }
  312. */
  313. // tangents to default
  314. glVertexAttrib4f(4, 0.0f, 0.0f, 0.0f, 0.0f);
  315. glDisableVertexAttribArray(4);
  316. // texcoords2 UNUSED
  317. /*
  318. // Default texcoord2 vertex attribute (shader-location = 5)
  319. if (mesh->texcoords2 != NULL)
  320. {
  321. glGenBuffers(1, &mesh->vboId[5]);
  322. glBindBuffer(GL_ARRAY_BUFFER, mesh->vboId[5]);
  323. glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords2, drawHint);
  324. glVertexAttribPointer(5, 2, GL_FLOAT, 0, 0, 0);
  325. glEnableVertexAttribArray(5);
  326. }
  327. else
  328. {
  329. // Default texcoord2 vertex attribute
  330. glVertexAttrib2f(5, 0.0f, 0.0f);
  331. glDisableVertexAttribArray(5);
  332. }
  333. */
  334. // texcoords2 to default
  335. glVertexAttrib2f(5, 0.0f, 0.0f);
  336. glDisableVertexAttribArray(5);
  337. if (amesh->triangles != NULL)
  338. {
  339. glGenBuffers(1, &amesh->vboId[6]);
  340. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, amesh->vboId[6]);
  341. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*amesh->triangleCount*3, amesh->triangles, GL_STATIC_DRAW);
  342. }
  343. if (amesh->vaoId > 0) TraceLog(LOG_INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", amesh->vaoId);
  344. else TraceLog(LOG_WARNING, "Mesh could not be uploaded to VRAM (GPU)");
  345. #endif
  346. }
  347. // Unload mesh data from CPU and GPU
  348. void rlUnloadAnimatedMesh(AnimatedMesh *amesh)
  349. {
  350. if (amesh->vertices != NULL) free(amesh->vertices);
  351. if (amesh->animVertices != NULL) free(amesh->animVertices);
  352. if (amesh->texcoords != NULL) free(amesh->texcoords);
  353. if (amesh->normals != NULL) free(amesh->normals);
  354. if (amesh->animNormals != NULL) free(amesh->animNormals);
  355. // if (mesh->colors != NULL) free(mesh->colors);
  356. // if (mesh->tangents != NULL) free(mesh->tangents);
  357. // if (mesh->texcoords2 != NULL) free(mesh->texcoords2);
  358. if (amesh->triangles != NULL) free(amesh->triangles);
  359. if (amesh->weightId != NULL) free(amesh->weightId);
  360. if (amesh->weightBias != NULL) free(amesh->weightBias);
  361. rlDeleteBuffers(amesh->vboId[0]); // vertex
  362. rlDeleteBuffers(amesh->vboId[1]); // texcoords
  363. rlDeleteBuffers(amesh->vboId[2]); // normals
  364. rlDeleteBuffers(amesh->vboId[3]); // colors
  365. rlDeleteBuffers(amesh->vboId[4]); // tangents
  366. rlDeleteBuffers(amesh->vboId[5]); // texcoords2
  367. rlDeleteBuffers(amesh->vboId[6]); // indices
  368. rlDeleteVertexArrays(amesh->vaoId);
  369. }
  370. // Update vertex and normal data into GPU
  371. void rlUpdateAnimatedMesh(AnimatedMesh *amesh)
  372. {
  373. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  374. // Activate mesh VAO
  375. glBindVertexArray(amesh->vaoId);
  376. // Update positions data
  377. glBindBuffer(GL_ARRAY_BUFFER, amesh->vboId[0]);
  378. glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*amesh->vertexCount, amesh->animVertices);
  379. // Update normals data
  380. glBindBuffer(GL_ARRAY_BUFFER, amesh->vboId[2]);
  381. glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*amesh->vertexCount, amesh->animNormals);
  382. // Unbind the current VAO
  383. glBindVertexArray(0);
  384. //mesh.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
  385. // Now we can modify vertices
  386. //glUnmapBuffer(GL_ARRAY_BUFFER);
  387. #endif
  388. }
  389. // Draw a 3d mesh with material and transform
  390. void rlDrawAnimatedMesh(AnimatedMesh amesh, Material material, Matrix transform)
  391. {
  392. #if defined(GRAPHICS_API_OPENGL_11)
  393. /*
  394. glEnable(GL_TEXTURE_2D);
  395. glBindTexture(GL_TEXTURE_2D, material.maps[MAP_DIFFUSE].texture.id);
  396. // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model
  397. glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array
  398. glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array
  399. //if (amesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array
  400. //if (amesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array
  401. glVertexPointer(3, GL_FLOAT, 0, amesh.animVertices); // Pointer to vertex coords array
  402. glTexCoordPointer(2, GL_FLOAT, 0, amesh.texcoords); // Pointer to texture coords array
  403. if (amesh.animNormals != NULL) glNormalPointer(GL_FLOAT, 0, amesh.animNormals); // Pointer to normals array
  404. //if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array
  405. rlPushMatrix();
  406. rlMultMatrixf(MatrixToFloat(transform));
  407. rlColor4ub(material.maps[MAP_DIFFUSE].color.r, material.maps[MAP_DIFFUSE].color.g, material.maps[MAP_DIFFUSE].color.b, material.maps[MAP_DIFFUSE].color.a);
  408. if (amesh.triangles != NULL) glDrawElements(GL_TRIANGLES, amesh.triangleCount*3, GL_UNSIGNED_SHORT, amesh.triangles);
  409. else glDrawArrays(GL_TRIANGLES, 0, amesh.vertexCount);
  410. rlPopMatrix();
  411. glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array
  412. glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array
  413. if (amesh.animNormals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array
  414. //if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array
  415. glDisable(GL_TEXTURE_2D);
  416. glBindTexture(GL_TEXTURE_2D, 0);
  417. */
  418. #endif
  419. #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
  420. // Bind shader program
  421. glUseProgram(material.shader.id);
  422. // Matrices and other values required by shader
  423. //-----------------------------------------------------
  424. // Calculate and send to shader model matrix (used by PBR shader)
  425. if (material.shader.locs[LOC_MATRIX_MODEL] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform);
  426. // Upload to shader material.colDiffuse
  427. if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1)
  428. glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255.0f,
  429. (float)material.maps[MAP_DIFFUSE].color.g/255.0f,
  430. (float)material.maps[MAP_DIFFUSE].color.b/255.0f,
  431. (float)material.maps[MAP_DIFFUSE].color.a/255.0f);
  432. // Upload to shader material.colSpecular (if available)
  433. if (material.shader.locs[LOC_COLOR_SPECULAR] != -1)
  434. glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255.0f,
  435. (float)material.maps[MAP_SPECULAR].color.g/255.0f,
  436. (float)material.maps[MAP_SPECULAR].color.b/255.0f,
  437. (float)material.maps[MAP_SPECULAR].color.a/255.0f);
  438. if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], GetMatrixModelview());
  439. if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection);
  440. // At this point the modelview matrix just contains the view matrix (camera)
  441. // That's because BeginMode3D() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
  442. Matrix matView = GetMatrixModelview(); // View matrix (camera)
  443. Matrix matProjection = projection; // Projection matrix (perspective)
  444. // Calculate model-view matrix combining matModel and matView
  445. Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates
  446. //-----------------------------------------------------
  447. // Bind active texture maps (if available)
  448. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  449. {
  450. if (material.maps[i].texture.id > 0)
  451. {
  452. glActiveTexture(GL_TEXTURE0 + i);
  453. if ((i == MAP_IRRADIANCE) || (i == MAP_PREFILTER) || (i == MAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].texture.id);
  454. else glBindTexture(GL_TEXTURE_2D, material.maps[i].texture.id);
  455. glUniform1i(material.shader.locs[LOC_MAP_DIFFUSE + i], i);
  456. }
  457. }
  458. glBindVertexArray(amesh.vaoId);
  459. /*
  460. // Bind vertex array objects (or VBOs)
  461. if (vaoSupported) glBindVertexArray(amesh.vaoId);
  462. else
  463. {
  464. // TODO: Simplify VBO binding into a for loop
  465. // Bind mesh VBO data: vertex position (shader-location = 0)
  466. glBindBuffer(GL_ARRAY_BUFFER, amesh.vboId[0]);
  467. glVertexAttribPointer(material.shader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
  468. glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_POSITION]);
  469. // Bind mesh VBO data: vertex texcoords (shader-location = 1)
  470. glBindBuffer(GL_ARRAY_BUFFER, amesh.vboId[1]);
  471. glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
  472. glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TEXCOORD01]);
  473. // Bind mesh VBO data: vertex normals (shader-location = 2, if available)
  474. if (material.shader.locs[LOC_VERTEX_NORMAL] != -1)
  475. {
  476. glBindBuffer(GL_ARRAY_BUFFER, amesh.vboId[2]);
  477. glVertexAttribPointer(material.shader.locs[LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0);
  478. glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_NORMAL]);
  479. }
  480. // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
  481. if (material.shader.locs[LOC_VERTEX_COLOR] != -1)
  482. {
  483. if (amesh.vboId[3] != 0)
  484. {
  485. glBindBuffer(GL_ARRAY_BUFFER, amesh.vboId[3]);
  486. glVertexAttribPointer(material.shader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
  487. glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_COLOR]);
  488. }
  489. else
  490. {
  491. // Set default value for unused attribute
  492. // NOTE: Required when using default shader and no VAO support
  493. glVertexAttrib4f(material.shader.locs[LOC_VERTEX_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
  494. glDisableVertexAttribArray(material.shader.locs[LOC_VERTEX_COLOR]);
  495. }
  496. }
  497. // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
  498. if (material.shader.locs[LOC_VERTEX_TANGENT] != -1)
  499. {
  500. glBindBuffer(GL_ARRAY_BUFFER, amesh.vboId[4]);
  501. glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TANGENT], 4, GL_FLOAT, 0, 0, 0);
  502. glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TANGENT]);
  503. }
  504. // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
  505. if (material.shader.locs[LOC_VERTEX_TEXCOORD02] != -1)
  506. {
  507. glBindBuffer(GL_ARRAY_BUFFER, amesh.vboId[5]);
  508. glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TEXCOORD02], 2, GL_FLOAT, 0, 0, 0);
  509. glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TEXCOORD02]);
  510. }
  511. if (amesh.triangles != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, amesh.vboId[6]);
  512. }
  513. */
  514. int eyesCount = 1;
  515. #if defined(SUPPORT_VR_SIMULATOR)
  516. if (vrStereoRender) eyesCount = 2;
  517. #endif
  518. for (int eye = 0; eye < eyesCount; eye++)
  519. {
  520. if (eyesCount == 1) modelview = matModelView;
  521. #if defined(SUPPORT_VR_SIMULATOR)
  522. else SetStereoView(eye, matProjection, matModelView);
  523. #endif
  524. // Calculate model-view-projection matrix (MVP)
  525. Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates
  526. // Send combined model-view-projection matrix to shader
  527. glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP));
  528. // Draw call!
  529. if (amesh.triangles != NULL) glDrawElements(GL_TRIANGLES, amesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw
  530. else glDrawArrays(GL_TRIANGLES, 0, amesh.vertexCount);
  531. }
  532. // Unbind all binded texture maps
  533. for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
  534. {
  535. glActiveTexture(GL_TEXTURE0 + i); // Set shader active texture
  536. if ((i == MAP_IRRADIANCE) || (i == MAP_PREFILTER) || (i == MAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  537. else glBindTexture(GL_TEXTURE_2D, 0); // Unbind current active texture
  538. }
  539. glBindVertexArray(0);
  540. /*
  541. // Unind vertex array objects (or VBOs)
  542. if (vaoSupported) glBindVertexArray(0);
  543. else
  544. {
  545. glBindBuffer(GL_ARRAY_BUFFER, 0);
  546. if (amesh.triangles != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  547. }
  548. */
  549. // Unbind shader program
  550. glUseProgram(0);
  551. // Restore projection/modelview matrices
  552. // NOTE: In stereo rendering matrices are being modified to fit every eye
  553. projection = matProjection;
  554. modelview = matView;
  555. #endif
  556. }
  557. #ifdef __cplusplus
  558. extern "C" { // Prevents name mangling of functions
  559. #endif
  560. // Load .iqm file and initialize animated model
  561. AnimatedModel LoadAnimatedModel(const char *filename)
  562. {
  563. AnimatedModel out = LoadIQM(filename);
  564. for (int i = 0; i < out.meshCount; i++) rlLoadAnimatedMesh(&out.mesh[i], false);
  565. out.transform = MatrixIdentity();
  566. out.meshMaterialId = malloc(sizeof(int)*out.meshCount);
  567. out.materials = NULL;
  568. out.materialCount = 0;
  569. for (int i = 0; i < out.meshCount; i++) out.meshMaterialId[i] = -1;
  570. return out;
  571. }
  572. // Add a texture to an animated model
  573. AnimatedModel AnimatedModelAddTexture(AnimatedModel model, const char *filename)
  574. {
  575. Texture2D texture = LoadTexture(filename);
  576. model.materials = realloc(model.materials, sizeof(Material)*(model.materialCount + 1));
  577. model.materials[model.materialCount] = LoadMaterialDefault();
  578. model.materials[model.materialCount].maps[MAP_DIFFUSE].texture = texture;
  579. model.materialCount++;
  580. return model;
  581. }
  582. // Set the material for a mesh
  583. AnimatedModel SetMeshMaterial(AnimatedModel model, int meshid, int textureid)
  584. {
  585. if (meshid > model.meshCount)
  586. {
  587. TraceLog(LOG_WARNING, "MeshId greater than meshCount\n");
  588. return model;
  589. }
  590. if (textureid > model.materialCount)
  591. {
  592. TraceLog(LOG_WARNING,"textureid greater than materialCount\n");
  593. return model;
  594. }
  595. model.meshMaterialId[meshid] = textureid;
  596. return model;
  597. }
  598. // Load animations from a .iqm file
  599. Animation LoadAnimationFromIQM(const char *filename)
  600. {
  601. Animation animation = { 0 };
  602. FILE *iqmFile;
  603. IQMHeader iqm;
  604. iqmFile = fopen(filename,"rb");
  605. if (!iqmFile)
  606. {
  607. TraceLog(LOG_ERROR, "[%s] Unable to open file", filename);
  608. return animation;
  609. }
  610. // header
  611. fread(&iqm, sizeof(IQMHeader), 1, iqmFile);
  612. if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC)))
  613. {
  614. TraceLog(LOG_ERROR, "Magic Number \"%s\"does not match.", iqm.magic);
  615. fclose(iqmFile);
  616. return animation;
  617. }
  618. if (iqm.version != IQM_VERSION)
  619. {
  620. TraceLog(LOG_ERROR, "IQM version %i is incorrect.", iqm.version);
  621. fclose(iqmFile);
  622. return animation;
  623. }
  624. // header
  625. if (iqm.num_anims > 1) TraceLog(LOG_WARNING, "More than 1 animation in file, only the first one will get loaded");
  626. // joints
  627. IQMPose *poses;
  628. poses = malloc(sizeof(IQMPose)*iqm.num_poses);
  629. fseek(iqmFile, iqm.ofs_poses, SEEK_SET);
  630. fread(poses, sizeof(IQMPose)*iqm.num_poses, 1, iqmFile);
  631. animation.jointCount = iqm.num_poses;
  632. animation.joints = malloc(sizeof(Joint)*iqm.num_poses);
  633. for (int j = 0; j < iqm.num_poses; j++)
  634. {
  635. strcpy(animation.joints[j].name, ANIMJOINTNAME);
  636. animation.joints[j].parent = poses[j].parent;
  637. }
  638. // animations
  639. IQMAnim anim = {0};
  640. fseek(iqmFile, iqm.ofs_anims, SEEK_SET);
  641. fread(&anim, sizeof(IQMAnim), 1, iqmFile);
  642. animation.frameCount = anim.num_frames;
  643. animation.framerate = anim.framerate;
  644. // frameposes
  645. unsigned short *framedata = malloc(sizeof(unsigned short)*iqm.num_frames*iqm.num_framechannels);
  646. fseek(iqmFile, iqm.ofs_frames, SEEK_SET);
  647. fread(framedata, sizeof(unsigned short)*iqm.num_frames*iqm.num_framechannels, 1, iqmFile);
  648. animation.framepose = malloc(sizeof(Pose*)*anim.num_frames);
  649. for (int j = 0; j < anim.num_frames; j++) animation.framepose[j] = malloc(sizeof(Pose)*iqm.num_poses);
  650. int dcounter = anim.first_frame*iqm.num_framechannels;
  651. for (int frame = 0; frame < anim.num_frames; frame++)
  652. {
  653. for (int i = 0; i < iqm.num_poses; i++)
  654. {
  655. animation.framepose[frame][i].translation.x = poses[i].channeloffset[0];
  656. if (poses[i].mask & 0x01)
  657. {
  658. animation.framepose[frame][i].translation.x += framedata[dcounter]*poses[i].channelscale[0];
  659. dcounter++;
  660. }
  661. animation.framepose[frame][i].translation.y = poses[i].channeloffset[1];
  662. if (poses[i].mask & 0x02)
  663. {
  664. animation.framepose[frame][i].translation.y += framedata[dcounter]*poses[i].channelscale[1];
  665. dcounter++;
  666. }
  667. animation.framepose[frame][i].translation.z = poses[i].channeloffset[2];
  668. if (poses[i].mask & 0x04)
  669. {
  670. animation.framepose[frame][i].translation.z += framedata[dcounter]*poses[i].channelscale[2];
  671. dcounter++;
  672. }
  673. animation.framepose[frame][i].rotation.x = poses[i].channeloffset[3];
  674. if (poses[i].mask & 0x08)
  675. {
  676. animation.framepose[frame][i].rotation.x += framedata[dcounter]*poses[i].channelscale[3];
  677. dcounter++;
  678. }
  679. animation.framepose[frame][i].rotation.y = poses[i].channeloffset[4];
  680. if (poses[i].mask & 0x10)
  681. {
  682. animation.framepose[frame][i].rotation.y += framedata[dcounter]*poses[i].channelscale[4];
  683. dcounter++;
  684. }
  685. animation.framepose[frame][i].rotation.z = poses[i].channeloffset[5];
  686. if (poses[i].mask & 0x20)
  687. {
  688. animation.framepose[frame][i].rotation.z += framedata[dcounter]*poses[i].channelscale[5];
  689. dcounter++;
  690. }
  691. animation.framepose[frame][i].rotation.w = poses[i].channeloffset[6];
  692. if (poses[i].mask & 0x40)
  693. {
  694. animation.framepose[frame][i].rotation.w += framedata[dcounter]*poses[i].channelscale[6];
  695. dcounter++;
  696. }
  697. animation.framepose[frame][i].scale.x = poses[i].channeloffset[7];
  698. if (poses[i].mask & 0x80)
  699. {
  700. animation.framepose[frame][i].scale.x += framedata[dcounter]*poses[i].channelscale[7];
  701. dcounter++;
  702. }
  703. animation.framepose[frame][i].scale.y = poses[i].channeloffset[8];
  704. if (poses[i].mask & 0x100)
  705. {
  706. animation.framepose[frame][i].scale.y += framedata[dcounter]*poses[i].channelscale[8];
  707. dcounter++;
  708. }
  709. animation.framepose[frame][i].scale.z = poses[i].channeloffset[9];
  710. if (poses[i].mask & 0x200)
  711. {
  712. animation.framepose[frame][i].scale.z += framedata[dcounter]*poses[i].channelscale[9];
  713. dcounter++;
  714. }
  715. animation.framepose[frame][i].rotation = QuaternionNormalize(animation.framepose[frame][i].rotation);
  716. }
  717. }
  718. // Build frameposes
  719. for (int frame = 0; frame < anim.num_frames; frame++)
  720. {
  721. for (int i = 0; i < animation.jointCount; i++)
  722. {
  723. if (animation.joints[i].parent >= 0)
  724. {
  725. animation.framepose[frame][i].rotation = QuaternionMultiply(animation.framepose[frame][animation.joints[i].parent].rotation, animation.framepose[frame][i].rotation);
  726. animation.framepose[frame][i].translation = Vector3RotateByQuaternion(animation.framepose[frame][i].translation, animation.framepose[frame][animation.joints[i].parent].rotation);
  727. animation.framepose[frame][i].translation = Vector3Add(animation.framepose[frame][i].translation, animation.framepose[frame][animation.joints[i].parent].translation);
  728. animation.framepose[frame][i].scale = Vector3MultiplyV(animation.framepose[frame][i].scale, animation.framepose[frame][animation.joints[i].parent].scale);
  729. }
  730. }
  731. }
  732. free(framedata);
  733. free(poses);
  734. fclose(iqmFile);
  735. return animation;
  736. }
  737. // Unload animated model
  738. void UnloadAnimatedModel(AnimatedModel model)
  739. {
  740. free(model.materials);
  741. free(model.meshMaterialId);
  742. free(model.joints);
  743. free(model.basepose);
  744. for (int i = 0; i < model.meshCount; i++) rlUnloadAnimatedMesh(&model.mesh[i]);
  745. free(model.mesh);
  746. }
  747. // Unload animation
  748. void UnloadAnimation(Animation anim)
  749. {
  750. free(anim.joints);
  751. free(anim.framepose);
  752. for (int i = 0; i < anim.frameCount; i++) free(anim.framepose[i]);
  753. }
  754. // Check if skeletons match, only parents and jointCount are checked
  755. bool CheckSkeletonsMatch(AnimatedModel model, Animation anim)
  756. {
  757. if (model.jointCount != anim.jointCount) return 0;
  758. for (int i = 0; i < model.jointCount; i++)
  759. {
  760. if (model.joints[i].parent != anim.joints[i].parent) return 0;
  761. }
  762. return 1;
  763. }
  764. // Calculate the animated vertex positions and normals based on an animation at a given frame
  765. void AnimateModel(AnimatedModel model, Animation anim, int frame)
  766. {
  767. if (frame >= anim.frameCount) frame = frame%anim.frameCount;
  768. for (int m = 0; m < model.meshCount; m++)
  769. {
  770. Vector3 outv = {0};
  771. Vector3 outn = {0};
  772. Vector3 baset = {0};
  773. Quaternion baser = {0};
  774. Vector3 bases = {0};
  775. Vector3 outt = {0};
  776. Quaternion outr = {0};
  777. Vector3 outs = {0};
  778. int vcounter = 0;
  779. int wcounter = 0;
  780. int weightId = 0;
  781. for (int i = 0; i < model.mesh[m].vertexCount; i++)
  782. {
  783. weightId = model.mesh[m].weightId[wcounter];
  784. baset = model.basepose[weightId].translation;
  785. baser = model.basepose[weightId].rotation;
  786. bases = model.basepose[weightId].scale;
  787. outt = anim.framepose[frame][weightId].translation;
  788. outr = anim.framepose[frame][weightId].rotation;
  789. outs = anim.framepose[frame][weightId].scale;
  790. // vertices
  791. outv = (Vector3){model.mesh[m].vertices[vcounter],model.mesh[m].vertices[vcounter + 1],model.mesh[m].vertices[vcounter + 2]};
  792. outv = Vector3MultiplyV(outv,outs);
  793. outv = Vector3Subtract(outv,baset);
  794. outv = Vector3RotateByQuaternion(outv,QuaternionMultiply(outr,QuaternionInvert(baser)));
  795. outv = Vector3Add(outv,outt);
  796. model.mesh[m].animVertices[vcounter] = outv.x;
  797. model.mesh[m].animVertices[vcounter + 1] = outv.y;
  798. model.mesh[m].animVertices[vcounter + 2] = outv.z;
  799. // normals
  800. outn = (Vector3){model.mesh[m].normals[vcounter],model.mesh[m].normals[vcounter + 1],model.mesh[m].normals[vcounter + 2]};
  801. outn = Vector3RotateByQuaternion(outn,QuaternionMultiply(outr,QuaternionInvert(baser)));
  802. model.mesh[m].animNormals[vcounter] = outn.x;
  803. model.mesh[m].animNormals[vcounter + 1] = outn.y;
  804. model.mesh[m].animNormals[vcounter + 2] = outn.z;
  805. vcounter += 3;
  806. wcounter += 4;
  807. }
  808. }
  809. }
  810. // Draw an animated model
  811. void DrawAnimatedModel(AnimatedModel model,Vector3 position,float scale,Color tint)
  812. {
  813. Vector3 vScale = { scale, scale, scale };
  814. Vector3 rotationAxis = { 0.0f,0.0f,0.0f };
  815. DrawAnimatedModelEx(model, position, rotationAxis, 0.0f, vScale, tint);
  816. }
  817. // Draw an animated model with extended parameters
  818. void DrawAnimatedModelEx(AnimatedModel model,Vector3 position,Vector3 rotationAxis,float rotationAngle, Vector3 scale,Color tint)
  819. {
  820. if (model.materialCount == 0)
  821. {
  822. TraceLog(LOG_WARNING,"No materials set, can't draw animated mesh\n");
  823. return;
  824. }
  825. Matrix matScale = MatrixScale(scale.x,scale.y,scale.z);
  826. Matrix matRotation = MatrixRotate(rotationAxis,rotationAngle*DEG2RAD);
  827. Matrix matTranslation = MatrixTranslate(position.x,position.y,position.z);
  828. Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale,matRotation),matTranslation);
  829. model.transform = MatrixMultiply(model.transform,matTransform);
  830. for (int i = 0; i < model.meshCount; i++)
  831. {
  832. rlUpdateAnimatedMesh(&model.mesh[i]);
  833. rlDrawAnimatedMesh(model.mesh[i],model.materials[model.meshMaterialId[i]],MatrixIdentity());
  834. }
  835. }
  836. // Load animated model meshes from IQM file
  837. static AnimatedModel LoadIQM(const char *filename)
  838. {
  839. AnimatedModel model = { 0 };
  840. FILE *iqmFile;
  841. IQMHeader iqm;
  842. IQMMesh *imesh;
  843. IQMTriangle *tri;
  844. IQMVertexArray *va;
  845. IQMJoint *ijoint;
  846. float *vertex;
  847. float *normal;
  848. float *text;
  849. char *blendi;
  850. unsigned char *blendw;
  851. iqmFile = fopen(filename, "rb");
  852. if (!iqmFile)
  853. {
  854. TraceLog(LOG_ERROR, "[%s] Unable to open file", filename);
  855. return model;
  856. }
  857. // header
  858. fread(&iqm,sizeof(IQMHeader), 1, iqmFile);
  859. if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC)))
  860. {
  861. TraceLog(LOG_ERROR, "Magic Number \"%s\"does not match.", iqm.magic);
  862. fclose(iqmFile);
  863. return model;
  864. }
  865. if(iqm.version != IQM_VERSION)
  866. {
  867. TraceLog(LOG_ERROR, "IQM version %i is incorrect.", iqm.version);
  868. fclose(iqmFile);
  869. return model;
  870. }
  871. // meshes
  872. imesh = malloc(sizeof(IQMMesh)*iqm.num_meshes);
  873. fseek(iqmFile, iqm.ofs_meshes, SEEK_SET);
  874. fread(imesh, sizeof(IQMMesh)*iqm.num_meshes, 1, iqmFile);
  875. model.meshCount = iqm.num_meshes;
  876. model.mesh = malloc(sizeof(AnimatedMesh)*iqm.num_meshes);
  877. for (int i = 0; i < iqm.num_meshes; i++)
  878. {
  879. fseek(iqmFile,iqm.ofs_text+imesh[i].name,SEEK_SET);
  880. fread(model.mesh[i].name, sizeof(char)*MESH_NAME_LENGTH, 1, iqmFile);
  881. model.mesh[i].vertexCount = imesh[i].num_vertexes;
  882. model.mesh[i].vertices = malloc(sizeof(float)*imesh[i].num_vertexes*3);
  883. model.mesh[i].normals = malloc(sizeof(float)*imesh[i].num_vertexes*3);
  884. model.mesh[i].texcoords = malloc(sizeof(float)*imesh[i].num_vertexes*2);
  885. model.mesh[i].weightId = malloc(sizeof(int)*imesh[i].num_vertexes*4);
  886. model.mesh[i].weightBias = malloc(sizeof(float)*imesh[i].num_vertexes*4);
  887. model.mesh[i].triangleCount = imesh[i].num_triangles;
  888. model.mesh[i].triangles = malloc(sizeof(unsigned short)*imesh[i].num_triangles*3);
  889. model.mesh[i].animVertices = malloc(sizeof(float)*imesh[i].num_vertexes*3);
  890. model.mesh[i].animNormals = malloc(sizeof(float)*imesh[i].num_vertexes*3);
  891. }
  892. // tris
  893. tri = malloc(sizeof(IQMTriangle)*iqm.num_triangles);
  894. fseek(iqmFile, iqm.ofs_triangles, SEEK_SET);
  895. fread(tri, sizeof(IQMTriangle)*iqm.num_triangles, 1, iqmFile);
  896. for (int m = 0; m < iqm.num_meshes; m++)
  897. {
  898. int tcounter = 0;
  899. for (int i=imesh[m].first_triangle; i < imesh[m].first_triangle+imesh[m].num_triangles; i++)
  900. {
  901. // IQM triangles are stored counter clockwise, but raylib sets opengl to clockwise drawing, so we swap them around
  902. model.mesh[m].triangles[tcounter+2] = tri[i].vertex[0] - imesh[m].first_vertex;
  903. model.mesh[m].triangles[tcounter+1] = tri[i].vertex[1] - imesh[m].first_vertex;
  904. model.mesh[m].triangles[tcounter] = tri[i].vertex[2] - imesh[m].first_vertex;
  905. tcounter += 3;
  906. }
  907. }
  908. // vertarrays
  909. va = malloc(sizeof(IQMVertexArray)*iqm.num_vertexarrays);
  910. fseek(iqmFile, iqm.ofs_vertexarrays, SEEK_SET);
  911. fread(va, sizeof(IQMVertexArray)*iqm.num_vertexarrays, 1, iqmFile);
  912. for (int i = 0; i < iqm.num_vertexarrays; i++)
  913. {
  914. switch (va[i].type)
  915. {
  916. case IQM_POSITION:
  917. {
  918. vertex = malloc(sizeof(float)*iqm.num_vertexes*3);
  919. fseek(iqmFile, va[i].offset, SEEK_SET);
  920. fread(vertex, sizeof(float)*iqm.num_vertexes*3, 1, iqmFile);
  921. for (int m = 0; m < iqm.num_meshes; m++)
  922. {
  923. int vcounter = 0;
  924. for (int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)
  925. {
  926. model.mesh[m].vertices[vcounter] = vertex[i];
  927. model.mesh[m].animVertices[vcounter] = vertex[i];
  928. vcounter++;
  929. }
  930. }
  931. } break;
  932. case IQM_NORMAL:
  933. {
  934. normal = malloc(sizeof(float)*iqm.num_vertexes*3);
  935. fseek(iqmFile, va[i].offset, SEEK_SET);
  936. fread(normal, sizeof(float)*iqm.num_vertexes*3, 1, iqmFile);
  937. for (int m = 0; m < iqm.num_meshes; m++)
  938. {
  939. int vcounter = 0;
  940. for (int i = imesh[m].first_vertex*3; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*3; i++)
  941. {
  942. model.mesh[m].normals[vcounter] = normal[i];
  943. model.mesh[m].animNormals[vcounter] = normal[i];
  944. vcounter++;
  945. }
  946. }
  947. } break;
  948. case IQM_TEXCOORD:
  949. {
  950. text = malloc(sizeof(float)*iqm.num_vertexes*2);
  951. fseek(iqmFile, va[i].offset, SEEK_SET);
  952. fread(text, sizeof(float)*iqm.num_vertexes*2, 1, iqmFile);
  953. for (int m = 0; m < iqm.num_meshes; m++)
  954. {
  955. int vcounter = 0;
  956. for (int i = imesh[m].first_vertex*2; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*2; i++)
  957. {
  958. model.mesh[m].texcoords[vcounter] = text[i];
  959. vcounter++;
  960. }
  961. }
  962. } break;
  963. case IQM_BLENDINDEXES:
  964. {
  965. blendi = malloc(sizeof(char)*iqm.num_vertexes*4);
  966. fseek(iqmFile, va[i].offset, SEEK_SET);
  967. fread(blendi, sizeof(char)*iqm.num_vertexes*4, 1, iqmFile);
  968. for (int m = 0; m < iqm.num_meshes; m++)
  969. {
  970. int vcounter = 0;
  971. for (int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
  972. {
  973. model.mesh[m].weightId[vcounter] = blendi[i];
  974. vcounter++;
  975. }
  976. }
  977. } break;
  978. case IQM_BLENDWEIGHTS:
  979. {
  980. blendw = malloc(sizeof(unsigned char)*iqm.num_vertexes*4);
  981. fseek(iqmFile,va[i].offset,SEEK_SET);
  982. fread(blendw,sizeof(unsigned char)*iqm.num_vertexes*4,1,iqmFile);
  983. for (int m = 0; m < iqm.num_meshes; m++)
  984. {
  985. int vcounter = 0;
  986. for (int i = imesh[m].first_vertex*4; i < (imesh[m].first_vertex + imesh[m].num_vertexes)*4; i++)
  987. {
  988. model.mesh[m].weightBias[vcounter] = blendw[i]/255.0f;
  989. vcounter++;
  990. }
  991. }
  992. } break;
  993. }
  994. }
  995. // joints, include base poses
  996. ijoint = malloc(sizeof(IQMJoint)*iqm.num_joints);
  997. fseek(iqmFile, iqm.ofs_joints, SEEK_SET);
  998. fread(ijoint, sizeof(IQMJoint)*iqm.num_joints, 1, iqmFile);
  999. model.jointCount = iqm.num_joints;
  1000. model.joints = malloc(sizeof(Joint)*iqm.num_joints);
  1001. model.basepose = malloc(sizeof(Pose)*iqm.num_joints);
  1002. for (int i = 0; i < iqm.num_joints; i++)
  1003. {
  1004. // joints
  1005. model.joints[i].parent = ijoint[i].parent;
  1006. fseek(iqmFile, iqm.ofs_text + ijoint[i].name, SEEK_SET);
  1007. fread(model.joints[i].name,sizeof(char)*JOINT_NAME_LENGTH, 1, iqmFile);
  1008. // basepose
  1009. model.basepose[i].translation.x = ijoint[i].translate[0];
  1010. model.basepose[i].translation.y = ijoint[i].translate[1];
  1011. model.basepose[i].translation.z = ijoint[i].translate[2];
  1012. model.basepose[i].rotation.x = ijoint[i].rotate[0];
  1013. model.basepose[i].rotation.y = ijoint[i].rotate[1];
  1014. model.basepose[i].rotation.z = ijoint[i].rotate[2];
  1015. model.basepose[i].rotation.w = ijoint[i].rotate[3];
  1016. model.basepose[i].scale.x = ijoint[i].scale[0];
  1017. model.basepose[i].scale.y = ijoint[i].scale[1];
  1018. model.basepose[i].scale.z = ijoint[i].scale[2];
  1019. }
  1020. // build base pose
  1021. for (int i = 0; i < model.jointCount; i++)
  1022. {
  1023. if (model.joints[i].parent >= 0)
  1024. {
  1025. model.basepose[i].rotation = QuaternionMultiply(model.basepose[model.joints[i].parent].rotation, model.basepose[i].rotation);
  1026. model.basepose[i].translation = Vector3RotateByQuaternion(model.basepose[i].translation, model.basepose[model.joints[i].parent].rotation);
  1027. model.basepose[i].translation = Vector3Add(model.basepose[i].translation, model.basepose[model.joints[i].parent].translation);
  1028. model.basepose[i].scale = Vector3MultiplyV(model.basepose[i].scale, model.basepose[model.joints[i].parent].scale);
  1029. }
  1030. }
  1031. fclose(iqmFile);
  1032. free(imesh);
  1033. free(tri);
  1034. free(va);
  1035. free(vertex);
  1036. free(normal);
  1037. free(text);
  1038. free(blendi);
  1039. free(blendw);
  1040. free(ijoint);
  1041. return model;
  1042. }
  1043. #endif