lovr/src/loaders/model.c

163 lines
4.7 KiB
C
Raw Normal View History

2016-11-26 01:13:26 +00:00
#include "loaders/model.h"
2017-01-21 03:55:54 +00:00
#include "math/mat4.h"
2016-10-29 06:40:31 +00:00
#include <stdlib.h>
#include <assimp/scene.h>
2016-10-04 04:54:27 +00:00
#include <assimp/cimport.h>
#include <assimp/postprocess.h>
2016-10-29 22:18:10 +00:00
static void assimpNodeTraversal(ModelNode* node, struct aiNode* assimpNode) {
// Transform
struct aiMatrix4x4 m = assimpNode->mTransformation;
aiTransposeMatrix4(&m);
2017-01-20 02:04:45 +00:00
mat4_set(node->transform, (float*) &m);
2016-10-29 22:18:10 +00:00
// Meshes
vec_init(&node->meshes);
vec_pusharr(&node->meshes, assimpNode->mMeshes, assimpNode->mNumMeshes);
// Children
vec_init(&node->children);
2016-11-12 09:19:47 +00:00
for (unsigned int n = 0; n < assimpNode->mNumChildren; n++) {
2016-10-29 22:18:10 +00:00
ModelNode* child = malloc(sizeof(ModelNode));
assimpNodeTraversal(child, assimpNode->mChildren[n]);
vec_push(&node->children, child);
}
}
2016-10-04 04:54:27 +00:00
2016-11-26 07:15:04 +00:00
ModelData* lovrModelDataFromFile(void* data, int size) {
ModelData* modelData = malloc(sizeof(ModelData));
2016-11-08 22:44:03 +00:00
if (!modelData) return NULL;
2016-11-27 02:58:58 +00:00
modelData->hasNormals = 0;
modelData->hasTexCoords = 0;
2017-01-15 21:49:24 +00:00
unsigned int flags = aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_OptimizeGraph;
2016-11-23 08:02:19 +00:00
const struct aiScene* scene = aiImportFileFromMemory(data, size, flags, NULL);
2016-10-29 22:18:10 +00:00
// Meshes
vec_init(&modelData->meshes);
2016-11-12 09:19:47 +00:00
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
2016-10-29 22:18:10 +00:00
struct aiMesh* assimpMesh = scene->mMeshes[m];
ModelMesh* mesh = malloc(sizeof(ModelMesh));
2016-10-31 20:54:32 +00:00
vec_push(&modelData->meshes, mesh);
2016-10-29 22:18:10 +00:00
// Faces
vec_init(&mesh->faces);
2016-11-12 09:19:47 +00:00
for (unsigned int f = 0; f < assimpMesh->mNumFaces; f++) {
2016-10-29 22:18:10 +00:00
struct aiFace assimpFace = assimpMesh->mFaces[f];
2016-10-31 20:54:32 +00:00
// Skip lines and points, polygons are triangulated
if (assimpFace.mNumIndices != 3) {
continue;
}
2016-10-29 22:18:10 +00:00
ModelFace face;
2016-11-12 09:19:47 +00:00
for (unsigned int i = 0; i < assimpFace.mNumIndices; i++) {
2016-11-25 11:16:11 +00:00
face.indices[i] = assimpFace.mIndices[i];
2016-10-29 22:18:10 +00:00
}
vec_push(&mesh->faces, face);
}
// Vertices
vec_init(&mesh->vertices);
2016-11-12 09:19:47 +00:00
for (unsigned int v = 0; v < assimpMesh->mNumVertices; v++) {
2016-10-29 22:18:10 +00:00
ModelVertex vertex;
vertex.x = assimpMesh->mVertices[v].x;
vertex.y = assimpMesh->mVertices[v].y;
vertex.z = assimpMesh->mVertices[v].z;
2016-10-31 20:54:32 +00:00
vec_push(&mesh->vertices, vertex);
2016-10-09 04:52:58 +00:00
}
2016-11-02 04:52:32 +00:00
// Normals
if (!assimpMesh->mNormals) {
error("Model must have normals");
}
modelData->hasNormals = 1;
vec_init(&mesh->normals);
2016-11-12 09:19:47 +00:00
for (unsigned int n = 0; n < assimpMesh->mNumVertices; n++) {
2016-11-02 04:52:32 +00:00
ModelVertex normal;
normal.x = assimpMesh->mNormals[n].x;
normal.y = assimpMesh->mNormals[n].y;
normal.z = assimpMesh->mNormals[n].z;
vec_push(&mesh->normals, normal);
}
2016-11-23 08:02:19 +00:00
modelData->hasTexCoords = modelData->hasTexCoords || assimpMesh->mTextureCoords[0] != NULL;
if (assimpMesh->mTextureCoords[0]) {
vec_init(&mesh->texCoords);
for (unsigned int i = 0; i < assimpMesh->mNumVertices; i++) {
ModelVertex texCoord;
texCoord.x = assimpMesh->mTextureCoords[0][i].x;
texCoord.y = assimpMesh->mTextureCoords[0][i].y;
vec_push(&mesh->texCoords, texCoord);
}
}
2016-10-09 04:52:58 +00:00
}
2016-10-29 22:18:10 +00:00
// Nodes
modelData->root = malloc(sizeof(ModelNode));
assimpNodeTraversal(modelData->root, scene->mRootNode);
2016-10-09 04:52:58 +00:00
aiReleaseImport(scene);
2016-10-04 04:54:27 +00:00
return modelData;
}
2016-11-26 08:31:44 +00:00
ModelData* lovrModelDataFromOpenVRModel(OpenVRModel* vrModel) {
2016-11-26 07:15:04 +00:00
ModelData* modelData = malloc(sizeof(ModelData));
2016-11-25 11:18:53 +00:00
if (!modelData) return NULL;
2016-11-26 08:31:44 +00:00
RenderModel_t* renderModel = vrModel->model;
2016-11-25 11:18:53 +00:00
ModelMesh* mesh = malloc(sizeof(ModelMesh));
vec_init(&modelData->meshes);
vec_push(&modelData->meshes, mesh);
vec_init(&mesh->faces);
for (uint32_t i = 0; i < renderModel->unTriangleCount; i++) {
ModelFace face;
face.indices[0] = renderModel->rIndexData[3 * i + 0];
face.indices[1] = renderModel->rIndexData[3 * i + 1];
face.indices[2] = renderModel->rIndexData[3 * i + 2];
vec_push(&mesh->faces, face);
}
vec_init(&mesh->vertices);
vec_init(&mesh->normals);
vec_init(&mesh->texCoords);
for (size_t i = 0; i < renderModel->unVertexCount; i++) {
float* position = renderModel->rVertexData[i].vPosition.v;
float* normal = renderModel->rVertexData[i].vNormal.v;
ModelVertex v;
v.x = position[0];
v.y = position[1];
v.z = position[2];
vec_push(&mesh->vertices, v);
v.x = normal[0];
v.y = normal[1];
v.z = normal[2];
vec_push(&mesh->normals, v);
float* texCoords = renderModel->rVertexData[i].rfTextureCoord;
v.x = texCoords[0];
v.y = texCoords[1];
v.z = 0.f;
vec_push(&mesh->texCoords, v);
}
ModelNode* root = malloc(sizeof(ModelNode));
vec_init(&root->meshes);
vec_push(&root->meshes, 0);
vec_init(&root->children);
2017-01-25 05:49:51 +00:00
mat4_identity(root->transform);
2016-11-25 11:18:53 +00:00
modelData->root = root;
modelData->hasNormals = 1;
modelData->hasTexCoords = 1;
return modelData;
2016-11-25 09:12:36 +00:00
}