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

102 lines
3 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>
static void renderNode(Model* model, int nodeIndex) {
ModelNode* node = &model->modelData->nodes[nodeIndex];
2017-10-21 22:20:16 +00:00
Material* currentMaterial = lovrGraphicsGetMaterial();
int useMaterials = currentMaterial->isDefault;
2016-10-31 20:54:32 +00:00
lovrGraphicsPush();
lovrGraphicsMatrixTransform(MATRIX_MODEL, node->transform);
2016-10-31 20:54:32 +00:00
for (int i = 0; i < node->primitives.length; i++) {
ModelPrimitive* primitive = &model->modelData->primitives[node->primitives.data[i]];
2017-10-21 22:20:16 +00:00
if (useMaterials) {
lovrGraphicsSetMaterial(model->materials[primitive->material]);
}
lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount);
lovrMeshDraw(model->mesh, NULL);
2016-10-31 20:54:32 +00:00
}
for (int i = 0; i < node->children.length; i++) {
renderNode(model, node->children.data[i]);
2016-10-31 20:54:32 +00:00
}
lovrGraphicsPop();
2017-10-21 22:20:16 +00:00
if (useMaterials) {
lovrGraphicsSetMaterial(currentMaterial);
}
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
model->modelData = modelData;
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
MeshAttribute attribute = { .name = "lovrPosition", .type = MESH_FLOAT, .count = 3 };
vec_push(&format, attribute);
2016-10-31 20:54:32 +00:00
2016-11-25 08:49:19 +00:00
if (modelData->hasNormals) {
MeshAttribute attribute = { .name = "lovrNormal", .type = MESH_FLOAT, .count = 3 };
vec_push(&format, attribute);
2016-11-02 04:52:32 +00:00
}
if (modelData->hasUVs) {
MeshAttribute attribute = { .name = "lovrTexCoord", .type = MESH_FLOAT, .count = 2 };
vec_push(&format, attribute);
2016-11-23 08:02:19 +00:00
}
2016-11-02 04:52:32 +00:00
2017-10-24 02:24:23 +00:00
if (modelData->hasVertexColors) {
MeshAttribute attribute = { .name = "lovrVertexColor", .type = MESH_BYTE, .count = 4 };
vec_push(&format, attribute);
}
model->mesh = lovrMeshCreate(modelData->vertexCount, &format, MESH_TRIANGLES, MESH_STATIC);
void* data = lovrMeshMap(model->mesh, 0, modelData->vertexCount, 0, 1);
2017-10-24 02:24:23 +00:00
memcpy(data, modelData->vertices, modelData->vertexCount * modelData->stride);
2017-04-09 20:40:20 +00:00
lovrMeshUnmap(model->mesh);
lovrMeshSetVertexMap(model->mesh, modelData->indices, modelData->indexCount);
lovrMeshSetRangeEnabled(model->mesh, 1);
2016-10-31 20:54:32 +00:00
2017-10-21 22:20:16 +00:00
model->materials = malloc(modelData->materialCount * sizeof(Material*));
for (int i = 0; i < modelData->materialCount; i++) {
model->materials[i] = lovrMaterialCreate(&modelData->materials[i], 0);
}
2016-11-18 10:03:50 +00:00
vec_deinit(&format);
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);
2017-10-21 22:20:16 +00:00
for (int i = 0; i < model->modelData->materialCount; i++) {
lovrRelease(&model->materials[i]->ref);
}
free(model->materials);
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) {
if (model->modelData->nodeCount == 0) {
return;
}
lovrGraphicsPush();
lovrGraphicsMatrixTransform(MATRIX_MODEL, transform);
renderNode(model, 0);
lovrGraphicsPop();
2016-10-31 20:54:32 +00:00
}
2016-11-08 22:51:58 +00:00
2017-10-15 17:26:33 +00:00
Mesh* lovrModelGetMesh(Model* model) {
return model->mesh;
}