aboutsummaryrefslogtreecommitdiff
path: root/src/models.c
diff options
context:
space:
mode:
authorraysan5 <raysan5@gmail.com>2014-04-19 16:36:49 +0200
committerraysan5 <raysan5@gmail.com>2014-04-19 16:36:49 +0200
commitf06a15ac8b3fe92d101ae795225fbf56fa670dba (patch)
treecdfba90ee24fd078a15c89d8753ee3e11d8e229b /src/models.c
parent650a8f7f159d3ce2addb1b0fdb31c3f460005391 (diff)
downloadraylib-f06a15ac8b3fe92d101ae795225fbf56fa670dba.tar.gz
raylib-f06a15ac8b3fe92d101ae795225fbf56fa670dba.zip
raylib 1.1
View CHANGELOG for a detailed list of changes
Diffstat (limited to 'src/models.c')
-rw-r--r--src/models.c647
1 files changed, 343 insertions, 304 deletions
diff --git a/src/models.c b/src/models.c
index 84ef43fa..5eb5d107 100644
--- a/src/models.c
+++ b/src/models.c
@@ -25,9 +25,9 @@
#include "raylib.h"
-#include <GL/gl.h> // OpenGL functions
#include <stdio.h> // Standard input/output functions, used to read model files data
#include <stdlib.h> // Declares malloc() and free() for memory management
+#include <string.h> // Required for strcmp()
#include <math.h> // Used for sin, cos, tan
#include "raymath.h" // Required for data type Matrix and Matrix functions
@@ -52,6 +52,7 @@
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static float GetHeightValue(Color pixel);
+static VertexData LoadOBJ(const char *fileName);
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -67,9 +68,9 @@ void DrawCube(Vector3 position, float width, float height, float lenght, Color c
rlPushMatrix();
- // NOTE: Be careful! Function order matters (scale, translate, rotate)
- //rlScalef(2.0f, 2.0f, 2.0f);
+ // NOTE: Be careful! Function order matters (rotate -> scale -> translate)
//rlTranslatef(0.0f, 0.0f, 0.0f);
+ //rlScalef(2.0f, 2.0f, 2.0f);
//rlRotatef(45, 0, 1, 0);
rlBegin(RL_TRIANGLES);
@@ -215,9 +216,9 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei
float y = position.y;
float z = position.z;
- rlEnableTexture(texture.glId);
+ rlEnableTexture(texture.id);
- rlPushMatrix();
+ //rlPushMatrix();
// NOTE: Be careful! Function order matters (scale, translate, rotate)
//rlScalef(2.0f, 2.0f, 2.0f);
//rlTranslatef(2.0f, 0.0f, 0.0f);
@@ -262,7 +263,7 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Right Of The Texture and Quad
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad
rlEnd();
- rlPopMatrix();
+ //rlPopMatrix();
rlDisableTexture();
}
@@ -278,13 +279,13 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
{
rlPushMatrix();
rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
- //rlRotatef(rotation, 0, 1, 0);
rlScalef(radius, radius, radius);
+ //rlRotatef(rotation, 0, 1, 0);
rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a);
- for(int i = 0; i < 2 * rings + 1; i ++)
+ for(int i = 0; i < 2 * rings + 1; i++)
{
for(int j = 0; j < slices; j++)
{
@@ -317,14 +318,14 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color)
{
rlPushMatrix();
- rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
- //rlRotatef(rotation, 0, 1, 0);
+ //rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
rlScalef(radius, radius, radius);
+ //rlRotatef(rotation, 0, 1, 0);
rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a);
- for(int i = 0; i < 2 * rings + 1; i ++)
+ for(int i = 0; i < 2 * rings + 1; i++)
{
for(int j = 0; j < slices; j++)
{
@@ -447,12 +448,12 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color)
// NOTE: Plane is always created on XZ ground and then rotated
rlPushMatrix();
rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
+ rlScalef(size.x, 1.0f, size.y);
// TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions...
rlRotatef(rotation.x, 1, 0, 0);
rlRotatef(rotation.y, 0, 1, 0);
rlRotatef(rotation.z, 0, 0, 1);
- rlScalef(size.x, 1.0f, size.y);
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
@@ -568,14 +569,13 @@ void DrawGizmo(Vector3 position)
rlPopMatrix();
}
-void DrawGizmoEx(Vector3 position, Vector3 rot, float scale, bool orbits)
-{
- static float rotation = 0;
+void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale)
+{
// NOTE: RGB = XYZ
rlPushMatrix();
rlTranslatef(position.x, position.y, position.z);
- rlRotatef(rotation, 0, 1, 0);
rlScalef(scale, scale, scale);
+ rlRotatef(rotation.y, 0, 1, 0);
rlBegin(RL_LINES);
// X Axis
@@ -612,279 +612,53 @@ void DrawGizmoEx(Vector3 position, Vector3 rot, float scale, bool orbits)
rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x - .1, position.y, position.z - .9);
// Extra
- if(orbits)
+ int n = 3;
+
+ // X Axis
+ for (int i=0; i < 360; i += 6)
{
- int n = 3;
-
- // X Axis
- for (int i=0; i < 360; i += 6)
- {
- rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n);
- rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n);
- }
-
- // Y Axis
- for (int i=0; i < 360; i += 6)
- {
- rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, 0, position.y + cos(DEG2RAD*i) * scale/n);
- rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, 0, position.y + cos(DEG2RAD*(i+6)) * scale/n);
- }
-
- // Z Axis
- for (int i=0; i < 360; i += 6)
- {
- rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n, 0);
- rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n, 0);
- }
+ rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n);
+ rlColor4ub(200, 0, 0, 255); rlVertex3f(0, position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n);
+ }
+
+ // Y Axis
+ for (int i=0; i < 360; i += 6)
+ {
+ rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, 0, position.y + cos(DEG2RAD*i) * scale/n);
+ rlColor4ub(0, 200, 0, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, 0, position.y + cos(DEG2RAD*(i+6)) * scale/n);
+ }
+
+ // Z Axis
+ for (int i=0; i < 360; i += 6)
+ {
+ rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + sin(DEG2RAD*i) * scale/n, position.y + cos(DEG2RAD*i) * scale/n, 0);
+ rlColor4ub(0, 0, 200, 255); rlVertex3f(position.x + sin(DEG2RAD*(i+6)) * scale/n, position.y + cos(DEG2RAD*(i+6)) * scale/n, 0);
}
rlEnd();
rlPopMatrix();
-
- rotation += 0.1f;
}
-// Load a 3d model (.OBJ)
-// TODO: Add comments explaining this function process
+// Load a 3d model
Model LoadModel(const char *fileName)
{
VertexData vData;
- char dataType;
- char comments[200];
-
- int numVertex = 0;
- int numNormals = 0;
- int numTexCoords = 0;
- int numTriangles = 0;
-
- FILE* objFile;
-
- objFile = fopen(fileName, "rt");
-
- while(!feof(objFile))
- {
- fscanf(objFile, "%c", &dataType);
-
- switch(dataType)
- {
- case '#': // It's a comment
- {
- fgets(comments, 200, objFile);
- } break;
- case 'v':
- {
- fscanf(objFile, "%c", &dataType);
-
- if (dataType == 't') // Read texCoord
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'v')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numTexCoords);
- }
-
- fgets(comments, 200, objFile);
- }
- else if (dataType == 'n') // Read normals
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'v')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numNormals);
- }
-
- fgets(comments, 200, objFile);
- }
- else // Read vertex
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'v')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numVertex);
- }
-
- fgets(comments, 200, objFile);
- }
- } break;
- case 'f':
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'f')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numTriangles);
- }
-
- fgets(comments, 200, objFile);
-
- } break;
- default: break;
- }
- }
-
- Vector3 midVertices[numVertex];
- Vector3 midNormals[numNormals];
- Vector2 midTexCoords[numTexCoords];
-
- vData.numVertices = numTriangles*3;
-
- vData.vertices = (float *)malloc(vData.numVertices * 3 * sizeof(float));
- vData.texcoords = (float *)malloc(vData.numVertices * 2 * sizeof(float));
- vData.normals = (float *)malloc(vData.numVertices * 3 * sizeof(float));
-
- int countVertex = 0;
- int countNormals = 0;
- int countTexCoords = 0;
-
- int vCounter = 0; // Used to count vertices float by float
- int tcCounter = 0; // Used to count texcoords float by float
- int nCounter = 0; // Used to count normals float by float
-
- rewind(objFile);
-
- while(!feof(objFile))
- {
- fscanf(objFile, "%c", &dataType);
-
- switch(dataType)
- {
- case '#':
- {
- fgets(comments, 200, objFile);
- } break;
- case 'v':
- {
- fscanf(objFile, "%c", &dataType);
-
- if (dataType == 't') // Read texCoord
- {
- float useless = 0;
-
- fscanf(objFile, "%f %f %f", &midTexCoords[countTexCoords].x, &midTexCoords[countTexCoords].y, &useless);
- countTexCoords++;
-
- fscanf(objFile, "%c", &dataType);
- }
- else if (dataType == 'n') // Read normals
- {
- fscanf(objFile, "%f %f %f", &midNormals[countNormals].x, &midNormals[countNormals].y, &midNormals[countNormals].z );
- countNormals++;
-
- fscanf(objFile, "%c", &dataType);
- }
- else // Read vertex
- {
- fscanf(objFile, "%f %f %f", &midVertices[countVertex].x, &midVertices[countVertex].y, &midVertices[countVertex].z );
- countVertex++;
-
- fscanf(objFile, "%c", &dataType);
- }
- } break;
- case 'f':
- {
- // At this point all vertex data (v, vt, vn) have been gathered on midVertices, midTexCoords, midNormals
- // Now we can organize that data into our VertexData struct
-
- int vNum, vtNum, vnNum;
- fscanf(objFile, "%c", &dataType);
- fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
-
- vData.vertices[vCounter] = midVertices[vNum-1].x;
- vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
- vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
- vCounter += 3;
-
- vData.normals[nCounter] = midNormals[vnNum-1].x;
- vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
- vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
- nCounter += 3;
-
- vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
- vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
- tcCounter += 2;
-
- fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
-
- vData.vertices[vCounter] = midVertices[vNum-1].x;
- vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
- vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
- vCounter += 3;
-
- vData.normals[nCounter] = midNormals[vnNum-1].x;
- vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
- vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
- nCounter += 3;
-
- vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
- vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
- tcCounter += 2;
-
- fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
-
- vData.vertices[vCounter] = midVertices[vNum-1].x;
- vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
- vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
- vCounter += 3;
-
- vData.normals[nCounter] = midNormals[vnNum-1].x;
- vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
- vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
- nCounter += 3;
-
- vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
- vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
- tcCounter += 2;
- } break;
- default: break;
- }
- }
-
- fclose(objFile);
-
- // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
+ if (strcmp(GetExtension(fileName),"obj") == 0) vData = LoadOBJ(fileName);
+ else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName);
Model model;
-#ifdef USE_OPENGL_11
- model.data = vData; // model data is vertex data
-#else
- model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO
+ model.mesh = vData; // Model mesh is vertex data
+ model.textureId = 0;
+#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
+ model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO
+ model.textureId = 1; // Default whiteTexture
+
// Now that vertex data is uploaded to GPU, we can free arrays
- free(vData.vertices);
- free(vData.texcoords);
- free(vData.normals);
+ //free(vData.vertices);
+ //free(vData.texcoords);
+ //free(vData.normals);
#endif
return model;
@@ -902,11 +676,11 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
// TODO: Consider resolution when generating model data?
int numTriangles = (mapX-1)*(mapZ-1)*2; // One quad every four pixels
- vData.numVertices = numTriangles*3;
+ vData.vertexCount = numTriangles*3;
- vData.vertices = (float *)malloc(vData.numVertices * 3 * sizeof(float));
- vData.normals = (float *)malloc(vData.numVertices * 3 * sizeof(float));
- vData.texcoords = (float *)malloc(vData.numVertices * 2 * sizeof(float));
+ vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
int vCounter = 0; // Used to count vertices float by float
int tcCounter = 0; // Used to count texcoords float by float
@@ -973,7 +747,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
// Fill normals array with data
//--------------------------------------------------------------
- // TODO: Review normals calculation
+ // NOTE: Current Model implementation doe not use normals!
for (int i = 0; i < 18; i += 3)
{
vData.normals[nCounter + i] = 0.0f;
@@ -981,6 +755,8 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
vData.normals[nCounter + i + 2] = 0.0f;
}
+ // TODO: Calculate normals in an efficient way
+
nCounter += 18; // 6 vertex, 18 floats
trisCounter += 2;
@@ -991,15 +767,17 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
Model model;
-#ifdef USE_OPENGL_11
- model.data = vData; // model data is vertex data
-#else
+ model.mesh = vData; // Model mesh is vertex data
+ model.textureId = 0;
+
+#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO
+ model.textureId = 1; // Default whiteTexture
// Now that vertex data is uploaded to GPU, we can free arrays
- free(vData.vertices);
- free(vData.texcoords);
- free(vData.normals);
+ //free(vData.vertices);
+ //free(vData.texcoords);
+ //free(vData.normals);
#endif
return model;
@@ -1008,37 +786,43 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
// Unload 3d model from memory
void UnloadModel(Model model)
{
-#ifdef USE_OPENGL_11
- free(model.data.vertices);
- free(model.data.texcoords);
- free(model.data.normals);
-#endif
+ free(model.mesh.vertices);
+ free(model.mesh.texcoords);
+ free(model.mesh.normals);
#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
rlDeleteVertexArrays(model.vaoId);
#endif
}
-// Draw a model
-void DrawModel(Model model, Vector3 position, float scale, Color color)
+void SetModelTexture(Model *model, Texture2D texture)
{
- rlglDrawModel(model, position, scale, false);
+ if (texture.id <= 0) model->textureId = 1; // Default white texture (use mesh color)
+ else model->textureId = texture.id;
}
-// Draw a textured model
-void DrawModelEx(Model model, Texture2D texture, Vector3 position, float scale, Color tint)
+// Draw a model (with texture if set)
+void DrawModel(Model model, Vector3 position, float scale, Color tint)
{
- rlEnableTexture(texture.glId);
-
- DrawModel(model, position, scale, tint);
-
- rlDisableTexture();
+ Vector3 vScale = { scale, scale, scale };
+ Vector3 rotation = { 0, 0, 0 };
+
+ rlglDrawModel(model, position, rotation, vScale, tint, false);
}
-// Draw a model wires
+// Draw a model with extended parameters
+void DrawModelEx(Model model, Vector3 position, Vector3 rotation, Vector3 scale, Color tint)
+{
+ rlglDrawModel(model, position, rotation, scale, tint, false);
+}
+
+// Draw a model wires (with texture if set)
void DrawModelWires(Model model, Vector3 position, float scale, Color color)
{
- rlglDrawModel(model, position, scale, true);
+ Vector3 vScale = { scale, scale, scale };
+ Vector3 rotation = { 0, 0, 0 };
+
+ rlglDrawModel(model, position, rotation, vScale, color, true);
}
// Draw a billboard
@@ -1070,7 +854,7 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size,
Vector3 c = VectorAdd(center, p2);
Vector3 d = VectorSubtract(center, p1);
- rlEnableTexture(texture.glId);
+ rlEnableTexture(texture.id);
rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
@@ -1113,7 +897,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec
Vector3 c = VectorAdd(center, p2);
Vector3 d = VectorSubtract(center, p1);
- rlEnableTexture(texture.glId);
+ rlEnableTexture(texture.id);
rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
@@ -1142,4 +926,259 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec
static float GetHeightValue(Color pixel)
{
return (((float)pixel.r + (float)pixel.g + (float)pixel.b)/3);
+}
+
+// Load OBJ mesh data
+static VertexData LoadOBJ(const char *fileName)
+{
+ VertexData vData;
+
+ char dataType;
+ char comments[200];
+
+ int numVertex = 0;
+ int numNormals = 0;
+ int numTexCoords = 0;
+ int numTriangles = 0;
+
+ FILE* objFile;
+
+ objFile = fopen(fileName, "rt");
+
+ // First pass over all file to get numVertex, numNormals, numTexCoords, numTriangles
+ // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition)
+ while(!feof(objFile))
+ {
+ fscanf(objFile, "%c", &dataType);
+
+ switch(dataType)
+ {
+ case '#': // It's a comment
+ {
+ fgets(comments, 200, objFile);
+ } break;
+ case 'o': // New object
+ {
+ // TODO: Read multiple objects, we need to know numMeshes + verticesPerMesh
+
+ // NOTE: One OBJ file can contain multible meshes defined, one after every 'o'
+
+ } break;
+ case 'v':
+ {
+ fscanf(objFile, "%c", &dataType);
+
+ if (dataType == 't') // Read texCoord
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+
+ while (dataType == 'v')
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+ }
+
+ if (dataType == '#')
+ {
+ fscanf(objFile, "%i", &numTexCoords);
+ }
+
+ fgets(comments, 200, objFile);
+ }
+ else if (dataType == 'n') // Read normals
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+
+ while (dataType == 'v')
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+ }
+
+ if (dataType == '#')
+ {
+ fscanf(objFile, "%i", &numNormals);
+ }
+
+ fgets(comments, 200, objFile);
+ }
+ else // Read vertex
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+
+ while (dataType == 'v')
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+ }
+
+ if (dataType == '#')
+ {
+ fscanf(objFile, "%i", &numVertex);
+ }
+
+ fgets(comments, 200, objFile);
+ }
+ } break;
+ case 'f':
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+
+ while (dataType == 'f')
+ {
+ fgets(comments, 200, objFile);
+ fscanf(objFile, "%c", &dataType);
+ }
+
+ if (dataType == '#')
+ {
+ fscanf(objFile, "%i", &numTriangles);
+ }
+
+ fgets(comments, 200, objFile);
+
+ } break;
+ default: break;
+ }
+ }
+
+ // Once we know the number of vertices to store, we create required arrays
+ Vector3 *midVertices = (Vector3 *)malloc(numVertex*sizeof(Vector3));
+ Vector3 *midNormals = (Vector3 *)malloc(numNormals*sizeof(Vector3));
+ Vector2 *midTexCoords = (Vector2 *)malloc(numTexCoords*sizeof(Vector2));
+
+ vData.vertexCount = numTriangles*3;
+
+ // Additional arrays to store vertex data as floats
+ vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
+ vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.colors = (float *)malloc(vData.vertexCount * 4 * sizeof(float));
+
+ int countVertex = 0;
+ int countNormals = 0;
+ int countTexCoords = 0;
+
+ int vCounter = 0; // Used to count vertices float by float
+ int tcCounter = 0; // Used to count texcoords float by float
+ int nCounter = 0; // Used to count normals float by float
+
+ rewind(objFile); // Return to the beginning of the file, to read again
+
+ // Reading again file to get vertex data
+ while(!feof(objFile))
+ {
+ fscanf(objFile, "%c", &dataType);
+
+ switch(dataType)
+ {
+ case '#':
+ {
+ fgets(comments, 200, objFile);
+ } break;
+ case 'v':
+ {
+ fscanf(objFile, "%c", &dataType);
+
+ if (dataType == 't') // Read texCoord
+ {
+ float useless = 0;
+
+ fscanf(objFile, "%f %f %f", &midTexCoords[countTexCoords].x, &midTexCoords[countTexCoords].y, &useless);
+ countTexCoords++;
+
+ fscanf(objFile, "%c", &dataType);
+ }
+ else if (dataType == 'n') // Read normals
+ {
+ fscanf(objFile, "%f %f %f", &midNormals[countNormals].x, &midNormals[countNormals].y, &midNormals[countNormals].z );
+ countNormals++;
+
+ fscanf(objFile, "%c", &dataType);
+ }
+ else // Read vertex
+ {
+ fscanf(objFile, "%f %f %f", &midVertices[countVertex].x, &midVertices[countVertex].y, &midVertices[countVertex].z );
+ countVertex++;
+
+ fscanf(objFile, "%c", &dataType);
+ }
+ } break;
+ case 'f':
+ {
+ // At this point all vertex data (v, vt, vn) have been gathered on midVertices, midTexCoords, midNormals
+ // Now we can organize that data into our VertexData struct
+
+ int vNum, vtNum, vnNum;
+ fscanf(objFile, "%c", &dataType);
+ fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
+
+ vData.vertices[vCounter] = midVertices[vNum-1].x;
+ vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
+ vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
+ vCounter += 3;
+
+ vData.normals[nCounter] = midNormals[vnNum-1].x;
+ vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
+ vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
+ nCounter += 3;
+
+ vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
+ vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
+ tcCounter += 2;
+
+ fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
+
+ vData.vertices[vCounter] = midVertices[vNum-1].x;
+ vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
+ vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
+ vCounter += 3;
+
+ vData.normals[nCounter] = midNormals[vnNum-1].x;
+ vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
+ vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
+ nCounter += 3;
+
+ vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
+ vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
+ tcCounter += 2;
+
+ fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
+
+ vData.vertices[vCounter] = midVertices[vNum-1].x;
+ vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
+ vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
+ vCounter += 3;
+
+ vData.normals[nCounter] = midNormals[vnNum-1].x;
+ vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
+ vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
+ nCounter += 3;
+
+ vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
+ vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
+ tcCounter += 2;
+ } break;
+ default: break;
+ }
+ }
+
+ fclose(objFile);
+
+ // NOTE: We set all vertex colors to white
+ for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 1.0f;
+
+ // Now we can free temp mid* arrays
+ free(midVertices);
+ free(midNormals);
+ free(midTexCoords);
+
+ // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
+ TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName);
+
+ return vData;
} \ No newline at end of file