mirror of https://github.com/bjornbytes/lovr.git
Use internal scene graph for models;
Allows for loading of more complicated models and multiple materials for a single model. Also fixes bugs with Mesh draw ranges. Model:getAABB is temporarily removed.
This commit is contained in:
parent
7b20ad9650
commit
f5e8535726
|
@ -23,19 +23,9 @@ int l_lovrModelSetTexture(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrModelGetAABB(lua_State* L) {
|
||||
Model* model = luax_checktype(L, 1, Model);
|
||||
float* aabb = lovrModelGetAABB(model);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
lua_pushnumber(L, aabb[i]);
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrModel[] = {
|
||||
{ "draw", l_lovrModelDraw },
|
||||
{ "getTexture", l_lovrModelGetTexture },
|
||||
{ "setTexture", l_lovrModelSetTexture },
|
||||
{ "getAABB", l_lovrModelGetAABB },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -119,8 +119,11 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
|
|||
lovrMeshUnmap(mesh);
|
||||
}
|
||||
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(MATRIX_MODEL, transform);
|
||||
if (transform) {
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(MATRIX_MODEL, transform);
|
||||
}
|
||||
|
||||
lovrGraphicsBindTexture(mesh->texture);
|
||||
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
|
||||
lovrGraphicsPrepare();
|
||||
|
@ -129,11 +132,15 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) {
|
|||
size_t start = mesh->rangeStart;
|
||||
size_t count = mesh->rangeCount;
|
||||
if (mesh->map.length > 0) {
|
||||
glDrawElements(mesh->drawMode, mesh->map.length, GL_UNSIGNED_INT, (GLvoid*) start);
|
||||
count = mesh->isRangeEnabled ? mesh->rangeCount : mesh->map.length;
|
||||
glDrawElements(mesh->drawMode, count, GL_UNSIGNED_INT, (GLvoid*) (start * sizeof(unsigned int)));
|
||||
} else {
|
||||
glDrawArrays(mesh->drawMode, start, count);
|
||||
}
|
||||
lovrGraphicsPop();
|
||||
|
||||
if (transform) {
|
||||
lovrGraphicsPop();
|
||||
}
|
||||
}
|
||||
|
||||
MeshFormat lovrMeshGetVertexFormat(Mesh* mesh) {
|
||||
|
@ -224,7 +231,9 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count) {
|
|||
}
|
||||
|
||||
int lovrMeshSetDrawRange(Mesh* mesh, int start, int count) {
|
||||
if (start < 0 || count < 0 || (size_t) start + count > mesh->count) {
|
||||
size_t limit = mesh->map.length > 0 ? mesh->map.length : mesh->count;
|
||||
|
||||
if (start < 0 || count < 0 || (size_t) start + count > limit) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,66 +3,24 @@
|
|||
#include "math/mat4.h"
|
||||
#include "math/vec3.h"
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
|
||||
static void visitNode(Model* model, ModelData* modelData, ModelNode* node, mat4 transform, vec_float_t* vertices, vec_uint_t* indices) {
|
||||
float newTransform[16];
|
||||
static void renderNode(Model* model, int nodeIndex) {
|
||||
ModelNode* node = &model->modelData->nodes[nodeIndex];
|
||||
|
||||
if (transform) {
|
||||
mat4_set(newTransform, transform);
|
||||
} else {
|
||||
mat4_identity(newTransform);
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(MATRIX_MODEL, node->transform);
|
||||
|
||||
for (int i = 0; i < node->primitives.length; i++) {
|
||||
ModelPrimitive* primitive = &model->modelData->primitives[node->primitives.data[i]];
|
||||
lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount);
|
||||
lovrMeshDraw(model->mesh, NULL);
|
||||
}
|
||||
|
||||
mat4_multiply(newTransform, node->transform);
|
||||
|
||||
int indexOffset = vertices->length / 3;
|
||||
|
||||
// Meshes
|
||||
for (int m = 0; m < node->meshes.length; m++) {
|
||||
ModelMesh* mesh = modelData->meshes.data[node->meshes.data[m]];
|
||||
|
||||
// Transformed vertices
|
||||
for (int v = 0; v < mesh->vertices.length; v++) {
|
||||
ModelVertex vertex = mesh->vertices.data[v];
|
||||
|
||||
float vec[3] = { vertex.x, vertex.y, vertex.z };
|
||||
mat4_transform(newTransform, vec);
|
||||
vec_pusharr(vertices, vec, 3);
|
||||
|
||||
model->aabb[0] = MIN(model->aabb[0], vec[0]);
|
||||
model->aabb[1] = MAX(model->aabb[1], vec[0]);
|
||||
model->aabb[2] = MIN(model->aabb[2], vec[1]);
|
||||
model->aabb[3] = MAX(model->aabb[3], vec[1]);
|
||||
model->aabb[4] = MIN(model->aabb[4], vec[2]);
|
||||
model->aabb[5] = MAX(model->aabb[5], vec[2]);
|
||||
|
||||
if (modelData->hasNormals) {
|
||||
ModelVertex normal = mesh->normals.data[v];
|
||||
vec_push(vertices, normal.x);
|
||||
vec_push(vertices, normal.y);
|
||||
vec_push(vertices, normal.z);
|
||||
}
|
||||
|
||||
if (modelData->hasTexCoords) {
|
||||
ModelVertex texCoord = mesh->texCoords.data[v];
|
||||
vec_push(vertices, texCoord.x);
|
||||
vec_push(vertices, texCoord.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Face vertex indices
|
||||
for (int f = 0; f < mesh->faces.length; f++) {
|
||||
ModelFace face = mesh->faces.data[f];
|
||||
vec_push(indices, face.indices[0] + indexOffset);
|
||||
vec_push(indices, face.indices[1] + indexOffset);
|
||||
vec_push(indices, face.indices[2] + indexOffset);
|
||||
}
|
||||
for (int i = 0; i < node->children.length; i++) {
|
||||
renderNode(model, node->children.data[i]);
|
||||
}
|
||||
|
||||
for (int c = 0; c < node->children.length; c++) {
|
||||
visitNode(model, modelData, node->children.data[c], newTransform, vertices, indices);
|
||||
}
|
||||
lovrGraphicsPop();
|
||||
}
|
||||
|
||||
Model* lovrModelCreate(ModelData* modelData) {
|
||||
|
@ -70,51 +28,33 @@ Model* lovrModelCreate(ModelData* modelData) {
|
|||
if (!model) return NULL;
|
||||
|
||||
model->modelData = modelData;
|
||||
model->aabb[0] = FLT_MAX;
|
||||
model->aabb[1] = FLT_MIN;
|
||||
model->aabb[2] = FLT_MAX;
|
||||
model->aabb[3] = FLT_MIN;
|
||||
model->aabb[4] = FLT_MAX;
|
||||
model->aabb[5] = FLT_MIN;
|
||||
|
||||
vec_float_t vertices;
|
||||
vec_init(&vertices);
|
||||
|
||||
vec_uint_t indices;
|
||||
vec_init(&indices);
|
||||
|
||||
visitNode(model, modelData, modelData->root, NULL, &vertices, &indices);
|
||||
|
||||
MeshFormat format;
|
||||
vec_init(&format);
|
||||
|
||||
int components = 3;
|
||||
MeshAttribute position = { .name = "lovrPosition", .type = MESH_FLOAT, .count = 3 };
|
||||
vec_push(&format, position);
|
||||
MeshAttribute attribute = { .name = "lovrPosition", .type = MESH_FLOAT, .count = 3 };
|
||||
vec_push(&format, attribute);
|
||||
|
||||
if (modelData->hasNormals) {
|
||||
MeshAttribute normal = { .name = "lovrNormal", .type = MESH_FLOAT, .count = 3 };
|
||||
vec_push(&format, normal);
|
||||
components += 3;
|
||||
MeshAttribute attribute = { .name = "lovrNormal", .type = MESH_FLOAT, .count = 3 };
|
||||
vec_push(&format, attribute);
|
||||
}
|
||||
|
||||
if (modelData->hasTexCoords) {
|
||||
MeshAttribute texCoord = { .name = "lovrTexCoord", .type = MESH_FLOAT, .count = 2 };
|
||||
vec_push(&format, texCoord);
|
||||
components += 2;
|
||||
if (modelData->hasUVs) {
|
||||
MeshAttribute attribute = { .name = "lovrTexCoord", .type = MESH_FLOAT, .count = 2 };
|
||||
vec_push(&format, attribute);
|
||||
}
|
||||
|
||||
model->mesh = lovrMeshCreate(vertices.length / components, &format, MESH_TRIANGLES, MESH_STATIC);
|
||||
void* data = lovrMeshMap(model->mesh, 0, vertices.length / components, 0, 1);
|
||||
memcpy(data, vertices.data, vertices.length * sizeof(float));
|
||||
model->mesh = lovrMeshCreate(modelData->vertexCount, &format, MESH_TRIANGLES, MESH_STATIC);
|
||||
void* data = lovrMeshMap(model->mesh, 0, modelData->vertexCount, 0, 1);
|
||||
memcpy(data, modelData->vertices, modelData->vertexCount * modelData->vertexSize * sizeof(float));
|
||||
lovrMeshUnmap(model->mesh);
|
||||
lovrMeshSetVertexMap(model->mesh, indices.data, indices.length);
|
||||
lovrMeshSetVertexMap(model->mesh, modelData->indices, modelData->indexCount);
|
||||
lovrMeshSetRangeEnabled(model->mesh, 1);
|
||||
|
||||
model->texture = NULL;
|
||||
|
||||
vec_deinit(&format);
|
||||
vec_deinit(&vertices);
|
||||
vec_deinit(&indices);
|
||||
return model;
|
||||
}
|
||||
|
||||
|
@ -129,7 +69,14 @@ void lovrModelDestroy(const Ref* ref) {
|
|||
}
|
||||
|
||||
void lovrModelDraw(Model* model, mat4 transform) {
|
||||
lovrMeshDraw(model->mesh, transform);
|
||||
if (model->modelData->nodeCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(MATRIX_MODEL, transform);
|
||||
renderNode(model, 0);
|
||||
lovrGraphicsPop();
|
||||
}
|
||||
|
||||
Texture* lovrModelGetTexture(Model* model) {
|
||||
|
@ -148,7 +95,3 @@ void lovrModelSetTexture(Model* model, Texture* texture) {
|
|||
lovrRetain(&model->texture->ref);
|
||||
}
|
||||
}
|
||||
|
||||
float* lovrModelGetAABB(Model* model) {
|
||||
return model->aabb;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ typedef struct {
|
|||
ModelData* modelData;
|
||||
Mesh* mesh;
|
||||
Texture* texture;
|
||||
float aabb[6];
|
||||
} Model;
|
||||
|
||||
Model* lovrModelCreate(ModelData* modelData);
|
||||
|
@ -20,4 +19,3 @@ void lovrModelDestroy(const Ref* ref);
|
|||
void lovrModelDraw(Model* model, mat4 transform);
|
||||
Texture* lovrModelGetTexture(Model* model);
|
||||
void lovrModelSetTexture(Model* model, Texture* texture);
|
||||
float* lovrModelGetAABB(Model* model);
|
||||
|
|
|
@ -600,53 +600,49 @@ ModelData* lovrHeadsetControllerNewModelData(Controller* controller) {
|
|||
ModelData* modelData = malloc(sizeof(ModelData));
|
||||
if (!modelData) return NULL;
|
||||
|
||||
ModelMesh* mesh = malloc(sizeof(ModelMesh));
|
||||
vec_init(&modelData->meshes);
|
||||
vec_push(&modelData->meshes, mesh);
|
||||
modelData->indexCount = vrModel->unTriangleCount;
|
||||
modelData->indices = malloc(modelData->indexCount * sizeof(unsigned int));
|
||||
memcpy(modelData->indices, vrModel->rIndexData, modelData->indexCount * sizeof(unsigned int));
|
||||
|
||||
vec_init(&mesh->faces);
|
||||
for (uint32_t i = 0; i < vrModel->unTriangleCount; i++) {
|
||||
ModelFace face;
|
||||
face.indices[0] = vrModel->rIndexData[3 * i + 0];
|
||||
face.indices[1] = vrModel->rIndexData[3 * i + 1];
|
||||
face.indices[2] = vrModel->rIndexData[3 * i + 2];
|
||||
vec_push(&mesh->faces, face);
|
||||
}
|
||||
modelData->vertexCount = vrModel->unVertexCount;
|
||||
modelData->vertexSize = 8;
|
||||
modelData->vertices = malloc(modelData->vertexCount * modelData->vertexSize * sizeof(float));
|
||||
|
||||
vec_init(&mesh->vertices);
|
||||
vec_init(&mesh->normals);
|
||||
vec_init(&mesh->texCoords);
|
||||
int vertex = 0;
|
||||
for (size_t i = 0; i < vrModel->unVertexCount; i++) {
|
||||
float* position = vrModel->rVertexData[i].vPosition.v;
|
||||
float* normal = vrModel->rVertexData[i].vNormal.v;
|
||||
float* texCoords = vrModel->rVertexData[i].rfTextureCoord;
|
||||
ModelVertex v;
|
||||
|
||||
v.x = position[0];
|
||||
v.y = position[1];
|
||||
v.z = position[2];
|
||||
vec_push(&mesh->vertices, v);
|
||||
modelData->vertices[vertex++] = position[0];
|
||||
modelData->vertices[vertex++] = position[1];
|
||||
modelData->vertices[vertex++] = position[2];
|
||||
|
||||
v.x = normal[0];
|
||||
v.y = normal[1];
|
||||
v.z = normal[2];
|
||||
vec_push(&mesh->normals, v);
|
||||
modelData->vertices[vertex++] = normal[0];
|
||||
modelData->vertices[vertex++] = normal[1];
|
||||
modelData->vertices[vertex++] = normal[2];
|
||||
|
||||
v.x = texCoords[0];
|
||||
v.y = texCoords[1];
|
||||
v.z = 0.f;
|
||||
vec_push(&mesh->texCoords, v);
|
||||
modelData->vertices[vertex++] = texCoords[0];
|
||||
modelData->vertices[vertex++] = texCoords[1];
|
||||
}
|
||||
|
||||
ModelNode* root = malloc(sizeof(ModelNode));
|
||||
vec_init(&root->meshes);
|
||||
vec_push(&root->meshes, 0);
|
||||
vec_init(&root->children);
|
||||
mat4_identity(root->transform);
|
||||
modelData->nodeCount = 1;
|
||||
modelData->primitiveCount = 1;
|
||||
|
||||
modelData->nodes = malloc(1 * sizeof(ModelNode));
|
||||
modelData->primitives = malloc(1 * sizeof(ModelPrimitive));
|
||||
|
||||
ModelNode* root = &modelData->nodes[0];
|
||||
root->parent = -1;
|
||||
mat4_identity(root->transform);
|
||||
vec_init(&root->children);
|
||||
vec_init(&root->primitives);
|
||||
vec_push(&root->primitives, 0);
|
||||
modelData->primitives[0].drawStart = 0;
|
||||
modelData->primitives[0].drawCount = modelData->vertexCount;
|
||||
|
||||
modelData->root = root;
|
||||
modelData->hasNormals = 1;
|
||||
modelData->hasTexCoords = 1;
|
||||
modelData->hasUVs = 1;
|
||||
|
||||
return modelData;
|
||||
}
|
||||
|
|
|
@ -2,29 +2,41 @@
|
|||
#include "math/mat4.h"
|
||||
#include <stdlib.h>
|
||||
#include <assimp/cimport.h>
|
||||
#include <assimp/config.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/mesh.h>
|
||||
#include <assimp/matrix4x4.h>
|
||||
#include <assimp/vector3.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
static void assimpNodeTraversal(ModelNode* node, struct aiNode* assimpNode) {
|
||||
static void assimpSumChildren(struct aiNode* assimpNode, int* totalChildren) {
|
||||
(*totalChildren)++;
|
||||
for (unsigned int i = 0; i < assimpNode->mNumChildren; i++) {
|
||||
assimpSumChildren(assimpNode->mChildren[i], totalChildren);
|
||||
}
|
||||
}
|
||||
|
||||
static void assimpNodeTraversal(ModelData* modelData, struct aiNode* assimpNode, int* nodeId) {
|
||||
int currentIndex = *nodeId;
|
||||
ModelNode* node = &modelData->nodes[currentIndex];
|
||||
|
||||
// Transform
|
||||
struct aiMatrix4x4 m = assimpNode->mTransformation;
|
||||
aiTransposeMatrix4(&m);
|
||||
mat4_set(node->transform, (float*) &m);
|
||||
|
||||
// Meshes
|
||||
vec_init(&node->meshes);
|
||||
vec_pusharr(&node->meshes, assimpNode->mMeshes, assimpNode->mNumMeshes);
|
||||
// Primitives
|
||||
vec_init(&node->primitives);
|
||||
vec_pusharr(&node->primitives, assimpNode->mMeshes, assimpNode->mNumMeshes);
|
||||
|
||||
// Children
|
||||
vec_init(&node->children);
|
||||
for (unsigned int n = 0; n < assimpNode->mNumChildren; n++) {
|
||||
ModelNode* child = malloc(sizeof(ModelNode));
|
||||
assimpNodeTraversal(child, assimpNode->mChildren[n]);
|
||||
vec_push(&node->children, child);
|
||||
(*nodeId)++;
|
||||
vec_push(&node->children, *nodeId);
|
||||
ModelNode* child = &modelData->nodes[*nodeId];
|
||||
child->parent = currentIndex;
|
||||
assimpNodeTraversal(modelData, assimpNode->mChildren[n], nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,104 +44,104 @@ ModelData* lovrModelDataCreate(Blob* blob) {
|
|||
ModelData* modelData = malloc(sizeof(ModelData));
|
||||
if (!modelData) return NULL;
|
||||
|
||||
modelData->hasNormals = 0;
|
||||
modelData->hasTexCoords = 0;
|
||||
|
||||
struct aiPropertyStore* propertyStore = aiCreatePropertyStore();
|
||||
aiSetImportPropertyInteger(propertyStore, AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_POINT | aiPrimitiveType_LINE);
|
||||
unsigned int flags = aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_OptimizeGraph | aiProcess_FlipUVs;
|
||||
const struct aiScene* scene = aiImportFileFromMemory(blob->data, blob->size, flags, NULL);
|
||||
const struct aiScene* scene = aiImportFileFromMemoryWithProperties(blob->data, blob->size, flags, NULL, propertyStore);
|
||||
aiReleasePropertyStore(propertyStore);
|
||||
|
||||
modelData->nodeCount = 0;
|
||||
modelData->vertexCount = 0;
|
||||
modelData->indexCount = 0;
|
||||
modelData->hasNormals = 0;
|
||||
modelData->hasUVs = 0;
|
||||
|
||||
// Meshes
|
||||
vec_init(&modelData->meshes);
|
||||
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
|
||||
struct aiMesh* assimpMesh = scene->mMeshes[m];
|
||||
ModelMesh* mesh = malloc(sizeof(ModelMesh));
|
||||
vec_push(&modelData->meshes, mesh);
|
||||
modelData->vertexCount += assimpMesh->mNumVertices;
|
||||
modelData->indexCount += assimpMesh->mNumFaces * 3;
|
||||
modelData->hasNormals |= assimpMesh->mNormals != NULL;
|
||||
modelData->hasUVs |= assimpMesh->mTextureCoords[0] != NULL;
|
||||
}
|
||||
|
||||
// Faces
|
||||
vec_init(&mesh->faces);
|
||||
// Allocate
|
||||
modelData->primitiveCount = scene->mNumMeshes;
|
||||
modelData->primitives = malloc(modelData->primitiveCount * sizeof(ModelPrimitive));
|
||||
modelData->vertexSize = 3 + (modelData->hasNormals ? 3 : 0) + (modelData->hasUVs ? 2 : 0);
|
||||
modelData->vertices = malloc(modelData->vertexSize * modelData->vertexCount * sizeof(float));
|
||||
modelData->indices = malloc(modelData->indexCount * sizeof(uint32_t));
|
||||
|
||||
// Load
|
||||
int vertex = 0;
|
||||
int index = 0;
|
||||
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
|
||||
struct aiMesh* assimpMesh = scene->mMeshes[m];
|
||||
modelData->primitives[m].drawStart = index;
|
||||
modelData->primitives[m].drawCount = 0;
|
||||
|
||||
// Indices
|
||||
for (unsigned int f = 0; f < assimpMesh->mNumFaces; f++) {
|
||||
struct aiFace assimpFace = assimpMesh->mFaces[f];
|
||||
lovrAssert(assimpFace.mNumIndices == 3, "Only triangular faces are supported");
|
||||
|
||||
// Skip lines and points, polygons are triangulated
|
||||
if (assimpFace.mNumIndices != 3) {
|
||||
continue;
|
||||
}
|
||||
modelData->primitives[m].drawCount += assimpFace.mNumIndices;
|
||||
|
||||
ModelFace face;
|
||||
for (unsigned int i = 0; i < assimpFace.mNumIndices; i++) {
|
||||
face.indices[i] = assimpFace.mIndices[i];
|
||||
modelData->indices[index++] = (vertex / modelData->vertexSize) + assimpFace.mIndices[i];
|
||||
}
|
||||
vec_push(&mesh->faces, face);
|
||||
}
|
||||
|
||||
// Vertices
|
||||
vec_init(&mesh->vertices);
|
||||
for (unsigned int v = 0; v < assimpMesh->mNumVertices; v++) {
|
||||
ModelVertex vertex;
|
||||
vertex.x = assimpMesh->mVertices[v].x;
|
||||
vertex.y = assimpMesh->mVertices[v].y;
|
||||
vertex.z = assimpMesh->mVertices[v].z;
|
||||
vec_push(&mesh->vertices, vertex);
|
||||
}
|
||||
modelData->vertices[vertex++] = assimpMesh->mVertices[v].x;
|
||||
modelData->vertices[vertex++] = assimpMesh->mVertices[v].y;
|
||||
modelData->vertices[vertex++] = assimpMesh->mVertices[v].z;
|
||||
|
||||
// Normals
|
||||
lovrAssert(assimpMesh->mNormals, "Model must have normals");
|
||||
if (modelData->hasNormals) {
|
||||
if (assimpMesh->mNormals) {
|
||||
modelData->vertices[vertex++] = assimpMesh->mNormals[v].x;
|
||||
modelData->vertices[vertex++] = assimpMesh->mNormals[v].y;
|
||||
modelData->vertices[vertex++] = assimpMesh->mNormals[v].z;
|
||||
} else {
|
||||
modelData->vertices[vertex++] = 0;
|
||||
modelData->vertices[vertex++] = 0;
|
||||
modelData->vertices[vertex++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
modelData->hasNormals = 1;
|
||||
vec_init(&mesh->normals);
|
||||
for (unsigned int n = 0; n < assimpMesh->mNumVertices; n++) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
if (modelData->hasUVs) {
|
||||
if (assimpMesh->mTextureCoords[0]) {
|
||||
modelData->vertices[vertex++] = assimpMesh->mTextureCoords[0][v].x;
|
||||
modelData->vertices[vertex++] = assimpMesh->mTextureCoords[0][v].y;
|
||||
} else {
|
||||
modelData->vertices[vertex++] = 0;
|
||||
modelData->vertices[vertex++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nodes
|
||||
modelData->root = malloc(sizeof(ModelNode));
|
||||
assimpNodeTraversal(modelData->root, scene->mRootNode);
|
||||
modelData->nodeCount = 0;
|
||||
assimpSumChildren(scene->mRootNode, &modelData->nodeCount);
|
||||
modelData->nodes = malloc(modelData->nodeCount * sizeof(ModelNode));
|
||||
modelData->nodes[0].parent = -1;
|
||||
int nodeIndex = 0;
|
||||
assimpNodeTraversal(modelData, scene->mRootNode, &nodeIndex);
|
||||
|
||||
aiReleaseImport(scene);
|
||||
return modelData;
|
||||
}
|
||||
|
||||
void lovrModelDataDestroy(ModelData* modelData) {
|
||||
for (int i = 0; i < modelData->meshes.length; i++) {
|
||||
ModelMesh* mesh = modelData->meshes.data[i];
|
||||
vec_deinit(&mesh->faces);
|
||||
vec_deinit(&mesh->vertices);
|
||||
vec_deinit(&mesh->normals);
|
||||
if (modelData->hasTexCoords) {
|
||||
vec_deinit(&mesh->texCoords);
|
||||
}
|
||||
free(mesh);
|
||||
for (int i = 0; i < modelData->nodeCount; i++) {
|
||||
vec_deinit(&modelData->nodes[i].children);
|
||||
vec_deinit(&modelData->nodes[i].primitives);
|
||||
}
|
||||
|
||||
vec_void_t nodes;
|
||||
vec_init(&nodes);
|
||||
vec_push(&nodes, modelData->root);
|
||||
while (nodes.length > 0) {
|
||||
ModelNode* node = vec_first(&nodes);
|
||||
vec_extend(&nodes, &node->children);
|
||||
vec_deinit(&node->meshes);
|
||||
vec_deinit(&node->children);
|
||||
vec_splice(&nodes, 0, 1);
|
||||
free(node);
|
||||
}
|
||||
|
||||
vec_deinit(&modelData->meshes);
|
||||
vec_deinit(&nodes);
|
||||
free(modelData->nodes);
|
||||
free(modelData->primitives);
|
||||
free(modelData->vertices);
|
||||
free(modelData->indices);
|
||||
free(modelData);
|
||||
}
|
||||
|
|
|
@ -5,39 +5,29 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} ModelVertex;
|
||||
int drawStart;
|
||||
int drawCount;
|
||||
} ModelPrimitive;
|
||||
|
||||
typedef vec_t(ModelVertex) vec_model_vertex_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int indices[3];
|
||||
} ModelFace;
|
||||
|
||||
typedef vec_t(ModelFace) vec_model_face_t;
|
||||
|
||||
typedef struct {
|
||||
vec_model_face_t faces;
|
||||
vec_model_vertex_t vertices;
|
||||
vec_model_vertex_t normals;
|
||||
vec_model_vertex_t texCoords;
|
||||
} ModelMesh;
|
||||
|
||||
typedef vec_t(ModelMesh*) vec_model_mesh_t;
|
||||
|
||||
typedef struct {
|
||||
typedef struct ModelNode {
|
||||
float transform[16];
|
||||
vec_uint_t meshes;
|
||||
vec_void_t children;
|
||||
int parent;
|
||||
vec_uint_t children;
|
||||
vec_uint_t primitives;
|
||||
} ModelNode;
|
||||
|
||||
typedef struct {
|
||||
ModelNode* root;
|
||||
vec_model_mesh_t meshes;
|
||||
ModelNode* nodes;
|
||||
ModelPrimitive* primitives;
|
||||
float* vertices;
|
||||
uint32_t* indices;
|
||||
int nodeCount;
|
||||
int primitiveCount;
|
||||
int vertexCount;
|
||||
int vertexSize;
|
||||
int indexCount;
|
||||
int hasNormals;
|
||||
int hasTexCoords;
|
||||
int hasUVs;
|
||||
} ModelData;
|
||||
|
||||
ModelData* lovrModelDataCreate(Blob* blob);
|
||||
|
|
Loading…
Reference in New Issue