1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-03 04:53:35 +00:00
lovr/src/graphics/model.c

136 lines
3.6 KiB
C
Raw Normal View History

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