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

150 lines
4 KiB
C
Raw Normal View History

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-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-18 10:03:50 +00:00
mat4_deinit(newTransform);
2016-10-31 20:54:32 +00:00
}
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
lovrRetain(&modelData->ref);
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
BufferFormat format;
vec_init(&format);
2016-11-02 04:52:32 +00:00
2016-11-23 08:02:19 +00:00
int components = 3;
BufferAttribute position = { .name = "lovrPosition", .type = BUFFER_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) {
BufferAttribute normal = { .name = "lovrNormal", .type = BUFFER_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) {
2016-11-25 11:14:48 +00:00
BufferAttribute texCoord = { .name = "lovrTexCoord", .type = BUFFER_FLOAT, .count = 2 };
vec_push(&format, texCoord);
2016-11-23 08:02:19 +00:00
components += 2;
}
2016-11-02 04:52:32 +00:00
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);
2016-11-23 08:02:19 +00:00
if (model->texture) {
lovrRelease(&model->texture->ref);
}
2016-11-19 07:41:23 +00:00
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-11-25 11:15:13 +00:00
if (model->texture) {
lovrTextureBind(model->texture);
} else {
glBindTexture(GL_TEXTURE_2D, 0);
}
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) {
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;
2016-11-23 08:02:19 +00:00
lovrBufferSetTexture(model->buffer, model->texture);
if (model->texture) {
lovrRetain(&model->texture->ref);
}
2016-11-08 22:51:58 +00:00
}