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
|
|
|
}
|