2016-11-19 09:28:01 +00:00
|
|
|
#include "graphics/model.h"
|
|
|
|
#include "graphics/graphics.h"
|
2017-01-21 03:55:54 +00:00
|
|
|
#include "math/mat4.h"
|
|
|
|
#include "math/vec3.h"
|
2016-10-04 04:54:27 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2016-10-31 20:54:32 +00:00
|
|
|
static void visitNode(ModelData* modelData, ModelNode* node, mat4 transform, vec_float_t* vertices, vec_uint_t* indices) {
|
2017-01-20 02:04:45 +00:00
|
|
|
float newTransform[16];
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2017-01-18 08:51:09 +00:00
|
|
|
if (transform) {
|
|
|
|
mat4_set(newTransform, transform);
|
2017-01-20 02:04:45 +00:00
|
|
|
} else {
|
|
|
|
mat4_identity(newTransform);
|
2016-10-31 20:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
2017-01-21 04:16:26 +00:00
|
|
|
float vec[3] = { vertex.x, vertex.y, vertex.z };
|
|
|
|
mat4_transform(newTransform, vec);
|
2017-01-18 08:51:09 +00:00
|
|
|
vec_pusharr(vertices, vec, 3);
|
2016-11-02 04:52:32 +00:00
|
|
|
|
|
|
|
if (modelData->hasNormals) {
|
|
|
|
ModelVertex normal = mesh->normals.data[v];
|
|
|
|
vec_push(vertices, normal.x);
|
|
|
|
vec_push(vertices, normal.y);
|
|
|
|
vec_push(vertices, normal.z);
|
|
|
|
}
|
2016-11-23 08:02:19 +00:00
|
|
|
|
|
|
|
if (modelData->hasTexCoords) {
|
|
|
|
ModelVertex texCoord = mesh->texCoords.data[v];
|
|
|
|
vec_push(vertices, texCoord.x);
|
|
|
|
vec_push(vertices, texCoord.y);
|
|
|
|
}
|
2016-10-31 20:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Face vertex indices
|
|
|
|
for (int f = 0; f < mesh->faces.length; f++) {
|
|
|
|
ModelFace face = mesh->faces.data[f];
|
2016-11-25 11:16:11 +00:00
|
|
|
vec_push(indices, face.indices[0] + indexOffset);
|
|
|
|
vec_push(indices, face.indices[1] + indexOffset);
|
|
|
|
vec_push(indices, face.indices[2] + indexOffset);
|
2016-10-31 20:54:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int c = 0; c < node->children.length; c++) {
|
|
|
|
visitNode(modelData, node->children.data[c], newTransform, vertices, indices);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 08:49:19 +00:00
|
|
|
Model* lovrModelCreate(ModelData* modelData) {
|
2016-11-19 07:41:23 +00:00
|
|
|
Model* model = lovrAlloc(sizeof(Model), lovrModelDestroy);
|
2016-11-08 22:44:03 +00:00
|
|
|
if (!model) return NULL;
|
|
|
|
|
2016-11-25 08:49:19 +00:00
|
|
|
model->modelData = modelData;
|
2016-10-31 20:54:32 +00:00
|
|
|
|
|
|
|
vec_float_t vertices;
|
|
|
|
vec_init(&vertices);
|
|
|
|
|
|
|
|
vec_uint_t indices;
|
|
|
|
vec_init(&indices);
|
|
|
|
|
2016-11-25 08:49:19 +00:00
|
|
|
visitNode(modelData, modelData->root, NULL, &vertices, &indices);
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2017-03-11 22:13:49 +00:00
|
|
|
MeshFormat format;
|
2016-10-31 20:54:32 +00:00
|
|
|
vec_init(&format);
|
2016-11-02 04:52:32 +00:00
|
|
|
|
2016-11-23 08:02:19 +00:00
|
|
|
int components = 3;
|
2017-03-11 22:13:49 +00:00
|
|
|
MeshAttribute position = { .name = "lovrPosition", .type = MESH_FLOAT, .count = 3 };
|
2016-10-31 20:54:32 +00:00
|
|
|
vec_push(&format, position);
|
|
|
|
|
2016-11-25 08:49:19 +00:00
|
|
|
if (modelData->hasNormals) {
|
2017-03-11 22:13:49 +00:00
|
|
|
MeshAttribute normal = { .name = "lovrNormal", .type = MESH_FLOAT, .count = 3 };
|
2016-11-02 04:52:32 +00:00
|
|
|
vec_push(&format, normal);
|
2016-11-23 08:02:19 +00:00
|
|
|
components += 3;
|
2016-11-02 04:52:32 +00:00
|
|
|
}
|
|
|
|
|
2016-11-25 08:49:19 +00:00
|
|
|
if (modelData->hasTexCoords) {
|
2017-03-11 22:13:49 +00:00
|
|
|
MeshAttribute texCoord = { .name = "lovrTexCoord", .type = MESH_FLOAT, .count = 2 };
|
2016-11-25 11:14:48 +00:00
|
|
|
vec_push(&format, texCoord);
|
2016-11-23 08:02:19 +00:00
|
|
|
components += 2;
|
|
|
|
}
|
2016-11-02 04:52:32 +00:00
|
|
|
|
2017-03-11 22:13:49 +00:00
|
|
|
model->mesh = lovrMeshCreate(vertices.length / components, &format, MESH_TRIANGLES, MESH_STATIC);
|
2017-03-12 01:27:18 +00:00
|
|
|
void* data = lovrMeshMap(model->mesh, 0, vertices.length / components);
|
|
|
|
memcpy(data, vertices.data, vertices.length * sizeof(float));
|
2017-03-11 22:13:49 +00:00
|
|
|
lovrMeshSetVertexMap(model->mesh, indices.data, indices.length);
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2016-11-08 22:51:58 +00:00
|
|
|
model->texture = NULL;
|
|
|
|
|
2016-11-18 10:03:50 +00:00
|
|
|
vec_deinit(&format);
|
2016-10-31 20:54:32 +00:00
|
|
|
vec_deinit(&vertices);
|
|
|
|
vec_deinit(&indices);
|
2016-10-04 04:54:27 +00:00
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
2016-11-19 07:41:23 +00:00
|
|
|
void lovrModelDestroy(const Ref* ref) {
|
|
|
|
Model* model = containerof(ref, Model);
|
2016-11-23 08:02:19 +00:00
|
|
|
if (model->texture) {
|
|
|
|
lovrRelease(&model->texture->ref);
|
|
|
|
}
|
2016-11-26 07:15:04 +00:00
|
|
|
lovrModelDataDestroy(model->modelData);
|
2017-03-11 22:13:49 +00:00
|
|
|
lovrRelease(&model->mesh->ref);
|
2016-10-04 04:54:27 +00:00
|
|
|
free(model);
|
|
|
|
}
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2017-01-20 03:11:42 +00:00
|
|
|
void lovrModelDraw(Model* model, mat4 transform) {
|
2017-03-11 22:13:49 +00:00
|
|
|
lovrMeshDraw(model->mesh, transform);
|
2016-10-31 20:54:32 +00:00
|
|
|
}
|
2016-11-08 22:51:58 +00:00
|
|
|
|
|
|
|
Texture* lovrModelGetTexture(Model* model) {
|
|
|
|
return model->texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
void lovrModelSetTexture(Model* model, Texture* texture) {
|
2016-11-23 08:02:19 +00:00
|
|
|
if (model->texture) {
|
|
|
|
lovrRelease(&model->texture->ref);
|
|
|
|
}
|
|
|
|
|
2016-11-08 22:51:58 +00:00
|
|
|
model->texture = texture;
|
2017-03-11 22:13:49 +00:00
|
|
|
lovrMeshSetTexture(model->mesh, model->texture);
|
2016-11-23 08:02:19 +00:00
|
|
|
|
|
|
|
if (model->texture) {
|
|
|
|
lovrRetain(&model->texture->ref);
|
|
|
|
}
|
2016-11-08 22:51:58 +00:00
|
|
|
}
|