2016-11-19 09:28:01 +00:00
|
|
|
#include "graphics/model.h"
|
|
|
|
#include "graphics/graphics.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) {
|
|
|
|
mat4 newTransform;
|
|
|
|
|
|
|
|
if (!transform) {
|
|
|
|
newTransform = mat4_init();
|
|
|
|
} else {
|
|
|
|
newTransform = mat4_copy(transform);
|
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
|
2016-11-02 04:52:32 +00:00
|
|
|
float transformedVertex[4] = {
|
2016-10-31 20:54:32 +00:00
|
|
|
vertex.x,
|
|
|
|
vertex.y,
|
|
|
|
vertex.z,
|
|
|
|
1.f
|
|
|
|
};
|
|
|
|
|
2016-11-02 04:52:32 +00:00
|
|
|
mat4_multiplyVector(newTransform, transformedVertex);
|
|
|
|
vec_pusharr(vertices, transformedVertex, 3);
|
|
|
|
|
|
|
|
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-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];
|
|
|
|
|
|
|
|
for (int v = 0; v < face.indices.length; v++) {
|
|
|
|
vec_push(indices, face.indices.data[v] + indexOffset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int c = 0; c < node->children.length; c++) {
|
|
|
|
visitNode(modelData, node->children.data[c], newTransform, vertices, indices);
|
|
|
|
}
|
2016-11-18 10:03:50 +00:00
|
|
|
|
|
|
|
mat4_deinit(newTransform);
|
2016-10-31 20:54:32 +00:00
|
|
|
}
|
|
|
|
|
2016-11-05 22:56:58 +00:00
|
|
|
Model* lovrModelCreate(void* data, int size) {
|
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-05 22:56:58 +00:00
|
|
|
model->modelData = lovrModelDataCreate(data, size);
|
2016-11-08 22:44:03 +00:00
|
|
|
if (!model->modelData) return NULL;
|
2016-10-31 20:54:32 +00:00
|
|
|
|
|
|
|
vec_float_t vertices;
|
|
|
|
vec_init(&vertices);
|
|
|
|
|
|
|
|
vec_uint_t indices;
|
|
|
|
vec_init(&indices);
|
|
|
|
|
|
|
|
visitNode(model->modelData, model->modelData->root, NULL, &vertices, &indices);
|
|
|
|
|
|
|
|
BufferFormat format;
|
|
|
|
vec_init(&format);
|
2016-11-02 04:52:32 +00:00
|
|
|
|
|
|
|
BufferAttribute position = { .name = "position", .type = BUFFER_FLOAT, .size = 3 };
|
2016-10-31 20:54:32 +00:00
|
|
|
vec_push(&format, position);
|
|
|
|
|
2016-11-02 04:52:32 +00:00
|
|
|
if (model->modelData->hasNormals) {
|
|
|
|
BufferAttribute normal = { .name = "normal", .type = BUFFER_FLOAT, .size = 3 };
|
|
|
|
vec_push(&format, normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
int components = model->modelData->hasNormals ? 6 : 3;
|
|
|
|
|
|
|
|
model->buffer = lovrBufferCreate(vertices.length / components, &format, BUFFER_TRIANGLES, BUFFER_STATIC);
|
2016-11-13 07:18:53 +00:00
|
|
|
lovrBufferSetVertices(model->buffer, (void*) vertices.data, vertices.length * sizeof(float));
|
2016-10-31 20:54:32 +00:00
|
|
|
lovrBufferSetVertexMap(model->buffer, indices.data, indices.length);
|
|
|
|
|
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);
|
|
|
|
lovrRelease(&model->modelData->ref);
|
|
|
|
lovrRelease(&model->buffer->ref);
|
2016-10-04 04:54:27 +00:00
|
|
|
free(model);
|
|
|
|
}
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2016-11-02 03:56:29 +00:00
|
|
|
void lovrModelDraw(Model* model, float x, float y, float z, float size, float angle, float ax, float ay, float az) {
|
|
|
|
lovrGraphicsPush();
|
|
|
|
lovrGraphicsTransform(x, y, z, size, size, size, angle, ax, ay, az);
|
2016-10-31 20:54:32 +00:00
|
|
|
lovrBufferDraw(model->buffer);
|
2016-11-02 03:56:29 +00:00
|
|
|
lovrGraphicsPop();
|
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) {
|
|
|
|
model->texture = texture;
|
|
|
|
}
|