Reviewed OBJ loading implementation -WIP-

One mesh files can be loaded correctly

MISSING:
 - Multimesh OBJ loading
 - Materials loading
This commit is contained in:
Ray 2019-04-01 12:17:29 +02:00
parent 0a492b5dea
commit e5edbb7104

View file

@ -635,7 +635,7 @@ Model LoadModel(const char *fileName)
TraceLog(LOG_WARNING, "[%s] No meshes can be loaded, default to cube mesh", fileName); TraceLog(LOG_WARNING, "[%s] No meshes can be loaded, default to cube mesh", fileName);
model.meshCount = 1; model.meshCount = 1;
model.meshes = (Mesh *)malloc(model.meshCount*sizeof(Mesh)); model.meshes = (Mesh *)calloc(model.meshCount, sizeof(Mesh));
model.meshes[0] = GenMeshCube(1.0f, 1.0f, 1.0f); model.meshes[0] = GenMeshCube(1.0f, 1.0f, 1.0f);
} }
@ -644,7 +644,7 @@ Model LoadModel(const char *fileName)
TraceLog(LOG_WARNING, "[%s] No materials can be loaded, default to white material", fileName); TraceLog(LOG_WARNING, "[%s] No materials can be loaded, default to white material", fileName);
model.materialCount = 1; model.materialCount = 1;
model.materials = (Material *)malloc(model.materialCount*sizeof(Material)); model.materials = (Material *)calloc(model.materialCount, sizeof(Material));
model.materials[0] = LoadMaterialDefault(); model.materials[0] = LoadMaterialDefault();
model.meshMaterial = (int *)calloc(model.meshCount, sizeof(int)); model.meshMaterial = (int *)calloc(model.meshCount, sizeof(int));
@ -1879,7 +1879,7 @@ void UnloadMaterial(Material material)
void DrawModel(Model model, Vector3 position, float scale, Color tint) void DrawModel(Model model, Vector3 position, float scale, Color tint)
{ {
Vector3 vScale = { scale, scale, scale }; Vector3 vScale = { scale, scale, scale };
Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; Vector3 rotationAxis = { 0.0f, 1.0f, 0.0f };
DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint); DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint);
} }
@ -1896,8 +1896,6 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota
Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
// Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform)
//Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates
model.transform = MatrixMultiply(model.transform, matTransform); model.transform = MatrixMultiply(model.transform, matTransform);
for (int i = 0; i < model.meshCount; i++) for (int i = 0; i < model.meshCount; i++)
@ -2126,25 +2124,25 @@ RayHitInfo GetCollisionRayModel(Ray ray, Model *model)
{ {
RayHitInfo result = { 0 }; RayHitInfo result = { 0 };
for (int i = 0; i < model->meshCount; i++) for (int m = 0; m < model->meshCount; m++)
{ {
// Check if meshhas vertex data on CPU for testing // Check if meshhas vertex data on CPU for testing
if (model->meshes[i].vertices != NULL) if (model->meshes[m].vertices != NULL)
{ {
// model->mesh.triangleCount may not be set, vertexCount is more reliable // model->mesh.triangleCount may not be set, vertexCount is more reliable
int triangleCount = model->meshes[i].vertexCount/3; int triangleCount = model->meshes[m].vertexCount/3;
// Test against all triangles in mesh // Test against all triangles in mesh
for (int i = 0; i < triangleCount; i++) for (int i = 0; i < triangleCount; i++)
{ {
Vector3 a, b, c; Vector3 a, b, c;
Vector3 *vertdata = (Vector3 *)model->meshes[i].vertices; Vector3 *vertdata = (Vector3 *)model->meshes[m].vertices;
if (model->meshes[i].indices) if (model->meshes[m].indices)
{ {
a = vertdata[model->meshes[i].indices[i*3 + 0]]; a = vertdata[model->meshes[m].indices[i*3 + 0]];
b = vertdata[model->meshes[i].indices[i*3 + 1]]; b = vertdata[model->meshes[m].indices[i*3 + 1]];
c = vertdata[model->meshes[i].indices[i*3 + 2]]; c = vertdata[model->meshes[m].indices[i*3 + 2]];
} }
else else
{ {
@ -2260,6 +2258,8 @@ BoundingBox MeshBoundingBox(Mesh mesh)
// Get min and max vertex to construct bounds (AABB) // Get min and max vertex to construct bounds (AABB)
Vector3 minVertex = { 0 }; Vector3 minVertex = { 0 };
Vector3 maxVertex = { 0 }; Vector3 maxVertex = { 0 };
printf("Mesh vertex count: %i\n", mesh.vertexCount);
if (mesh.vertices != NULL) if (mesh.vertices != NULL)
{ {
@ -2274,7 +2274,7 @@ BoundingBox MeshBoundingBox(Mesh mesh)
} }
// Create the bounding box // Create the bounding box
BoundingBox box; BoundingBox box = { 0 };
box.min = minVertex; box.min = minVertex;
box.max = maxVertex; box.max = maxVertex;
@ -2383,17 +2383,18 @@ void MeshBinormals(Mesh *mesh)
static Model LoadOBJ(const char *fileName) static Model LoadOBJ(const char *fileName)
{ {
Model model = { 0 }; Model model = { 0 };
model.transform = MatrixIdentity();
tinyobj_attrib_t attrib; tinyobj_attrib_t attrib;
tinyobj_shape_t *meshes = NULL; tinyobj_shape_t *meshes = NULL;
unsigned int meshCount = 0; unsigned int meshCount = 0;
tinyobj_material_t *materials = NULL; tinyobj_material_t *materials = NULL;
unsigned int materialCount = 0; unsigned int materialCount = 0;
int dataLength = 0; int dataLength = 0;
char *data = NULL; char *data = NULL;
// Load model data // Load model data
FILE *objFile = fopen(fileName, "rb"); FILE *objFile = fopen(fileName, "rb");
@ -2425,16 +2426,21 @@ static Model LoadOBJ(const char *fileName)
// Init model materials array // Init model materials array
model.materialCount = materialCount; model.materialCount = materialCount;
model.materials = (Material *)malloc(model.materialCount*sizeof(Material)); model.materials = (Material *)malloc(model.materialCount*sizeof(Material));
model.meshMaterial = (int *)calloc(model.meshCount, sizeof(int));
/*
// Multiple meshes data reference
// NOTE: They are provided as a faces offset
typedef struct {
char *name; // group name or object name
unsigned int face_offset;
unsigned int length;
} tinyobj_shape_t;
*/
// Init model meshes // Init model meshes
for (int m = 0; m < 1; m++) for (int m = 0; m < 1; m++)
{ {
printf("num_vertices: %i\n", attrib.num_vertices);
printf("num_normals: %i\n", attrib.num_normals);
printf("num_texcoords: %i\n", attrib.num_texcoords);
printf("num_faces: %i\n", attrib.num_faces);
printf("num_face_num_verts: %i\n", attrib.num_face_num_verts);
Mesh mesh = { 0 }; Mesh mesh = { 0 };
memset(&mesh, 0, sizeof(Mesh)); memset(&mesh, 0, sizeof(Mesh));
mesh.vertexCount = attrib.num_faces*3; mesh.vertexCount = attrib.num_faces*3;
@ -2443,98 +2449,43 @@ static Model LoadOBJ(const char *fileName)
mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float));
mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float));
int faceOffset = 0;
int vCount = 0; int vCount = 0;
int vtCount = 0; int vtCount = 0;
int vnCount = 0; int vnCount = 0;
/*
for (int i = 0; i < attrib.num_vertices*3; i++) printf("%2.2f, ", attrib.vertices[i]);
printf("\n");
for (int i = 0; i < attrib.num_texcoords*2; i++) printf("%2.2f, ", attrib.texcoords[i]);
printf("\n");
for (int i = 0; i < attrib.num_normals*3; i++) printf("%2.2f, ", attrib.normals[i]);
printf("\n");
tinyobj_vertex_index_t idx0 = attrib.faces[0];
tinyobj_vertex_index_t idx1 = attrib.faces[1];
tinyobj_vertex_index_t idx2 = attrib.faces[2];
for (int v = 0; v < 3; v++) { printf("%2.2f, ", attrib.vertices[idx0.v_idx*3 + v]); } printf("\n");
for (int v = 0; v < 3; v++) { printf("%2.2f, ", attrib.vertices[idx1.v_idx*3 + v]); } printf("\n");
for (int v = 0; v < 3; v++) { printf("%2.2f, ", attrib.vertices[idx2.v_idx*3 + v]); } printf("\n\n");
idx0 = attrib.faces[3 + 0];
idx1 = attrib.faces[3 + 1];
idx2 = attrib.faces[3 + 2];
for (int v = 0; v < 3; v++) { printf("%2.2f, ", attrib.vertices[idx0.v_idx*3 + v]); } printf("\n");
for (int v = 0; v < 3; v++) { printf("%2.2f, ", attrib.vertices[idx1.v_idx*3 + v]); } printf("\n");
for (int v = 0; v < 3; v++) { printf("%2.2f, ", attrib.vertices[idx2.v_idx*3 + v]); } printf("\n\n");
*/
for (int f = 0; f < attrib.num_faces; f++) for (int f = 0; f < attrib.num_faces; f++)
{ {
// Get indices for the face
tinyobj_vertex_index_t idx0 = attrib.faces[3*f + 0]; tinyobj_vertex_index_t idx0 = attrib.faces[3*f + 0];
tinyobj_vertex_index_t idx1 = attrib.faces[3*f + 1]; tinyobj_vertex_index_t idx1 = attrib.faces[3*f + 1];
tinyobj_vertex_index_t idx2 = attrib.faces[3*f + 2]; tinyobj_vertex_index_t idx2 = attrib.faces[3*f + 2];
// printf("Face index: v %i/%i/%i . vt %i/%i/%i . vn %i/%i/%i\n", // TraceLog(LOG_DEBUG, "Face %i index: v %i/%i/%i . vt %i/%i/%i . vn %i/%i/%i\n", f, idx0.v_idx, idx1.v_idx, idx2.v_idx, idx0.vt_idx, idx1.vt_idx, idx2.vt_idx, idx0.vn_idx, idx1.vn_idx, idx2.vn_idx);
// idx0.v_idx, idx1.v_idx, idx2.v_idx,
// idx0.vt_idx, idx1.vt_idx, idx2.vt_idx,
// idx0.vn_idx, idx1.vn_idx, idx2.vn_idx);
// Fill vertices buffer (float) using vertex index of the face
for (int v = 0; v < 3; v++) { mesh.vertices[vCount + v] = attrib.vertices[idx0.v_idx*3 + v]; } vCount +=3; for (int v = 0; v < 3; v++) { mesh.vertices[vCount + v] = attrib.vertices[idx0.v_idx*3 + v]; } vCount +=3;
for (int v = 0; v < 3; v++) { mesh.vertices[vCount + v] = attrib.vertices[idx1.v_idx*3 + v]; } vCount +=3; for (int v = 0; v < 3; v++) { mesh.vertices[vCount + v] = attrib.vertices[idx1.v_idx*3 + v]; } vCount +=3;
for (int v = 0; v < 3; v++) { mesh.vertices[vCount + v] = attrib.vertices[idx2.v_idx*3 + v]; } vCount +=3; for (int v = 0; v < 3; v++) { mesh.vertices[vCount + v] = attrib.vertices[idx2.v_idx*3 + v]; } vCount +=3;
for (int v = 0; v < 2; v++) { mesh.texcoords[vtCount + v] = attrib.texcoords[idx0.vt_idx*2 + v]; } vtCount += 2; // Fill texcoords buffer (float) using vertex index of the face
for (int v = 0; v < 2; v++) { mesh.texcoords[vtCount + v] = attrib.texcoords[idx1.vt_idx*2 + v]; } vtCount += 2; // NOTE: Y-coordinate must be flipped upside-down
for (int v = 0; v < 2; v++) { mesh.texcoords[vtCount + v] = attrib.texcoords[idx2.vt_idx*2 + v]; } vtCount += 2; mesh.texcoords[vtCount + 0] = attrib.texcoords[idx0.vt_idx*2 + 0];
mesh.texcoords[vtCount + 1] = 1.0f - attrib.texcoords[idx0.vt_idx*2 + 1]; vtCount += 2;
mesh.texcoords[vtCount + 0] = attrib.texcoords[idx1.vt_idx*2 + 0];
mesh.texcoords[vtCount + 1] = 1.0f - attrib.texcoords[idx1.vt_idx*2 + 1]; vtCount += 2;
mesh.texcoords[vtCount + 0] = attrib.texcoords[idx2.vt_idx*2 + 0];
mesh.texcoords[vtCount + 1] = 1.0f - attrib.texcoords[idx2.vt_idx*2 + 1]; vtCount += 2;
// Fill normals buffer (float) using vertex index of the face
for (int v = 0; v < 3; v++) { mesh.normals[vnCount + v] = attrib.normals[idx0.vn_idx*3 + v]; } vnCount +=3; for (int v = 0; v < 3; v++) { mesh.normals[vnCount + v] = attrib.normals[idx0.vn_idx*3 + v]; } vnCount +=3;
for (int v = 0; v < 3; v++) { mesh.normals[vnCount + v] = attrib.normals[idx1.vn_idx*3 + v]; } vnCount +=3; for (int v = 0; v < 3; v++) { mesh.normals[vnCount + v] = attrib.normals[idx1.vn_idx*3 + v]; } vnCount +=3;
for (int v = 0; v < 3; v++) { mesh.normals[vnCount + v] = attrib.normals[idx2.vn_idx*3 + v]; } vnCount +=3; for (int v = 0; v < 3; v++) { mesh.normals[vnCount + v] = attrib.normals[idx2.vn_idx*3 + v]; } vnCount +=3;
} }
printf("vCount: %i\n", vCount);
printf("vtCount: %i\n", vtCount);
printf("vnCount: %i\n", vnCount);
model.meshes[m] = mesh; // Assign mesh data to model model.meshes[m] = mesh; // Assign mesh data to model
rlLoadMesh(&model.meshes[m], false); // Upload vertex data to GPU (static mesh) rlLoadMesh(&model.meshes[m], false); // Upload vertex data to GPU (static mesh)
} }
/*
// Data reference to process
typedef struct {
char *name; // group name or object name
unsigned int face_offset;
unsigned int length;
} tinyobj_shape_t;
typedef struct { int v_idx, vt_idx, vn_idx; } tinyobj_vertex_index_t;
typedef struct {
unsigned int num_vertices;
unsigned int num_normals;
unsigned int num_texcoords;
unsigned int num_faces;
unsigned int num_face_num_verts;
int pad0;
float *vertices;
float *normals;
float *texcoords;
tinyobj_vertex_index_t *faces;
int *face_num_verts;
int *material_ids;
} tinyobj_attrib_t;
*/
// Init model materials // Init model materials
for (int m = 0; m < materialCount; m++) for (int m = 0; m < materialCount; m++)
{ {