2016-11-19 09:28:01 +00:00
|
|
|
#include "graphics/model.h"
|
|
|
|
#include "graphics/graphics.h"
|
2018-09-26 00:10:09 +00:00
|
|
|
#include "resources/shaders.h"
|
|
|
|
|
2019-01-13 16:41:18 +00:00
|
|
|
static void renderNode(Model* model, uint32_t nodeIndex, mat4 transform, int instances) {
|
2019-01-10 19:34:00 +00:00
|
|
|
ModelNode* node = &model->data->nodes[nodeIndex];
|
|
|
|
|
2019-01-13 16:41:18 +00:00
|
|
|
float globalTransform[16];
|
|
|
|
mat4_init(globalTransform, transform);
|
|
|
|
|
|
|
|
if (!model->animator || !lovrAnimatorEvaluate(model->animator, nodeIndex, globalTransform)) {
|
|
|
|
mat4_multiply(globalTransform, node->transform);
|
|
|
|
}
|
2019-01-10 19:34:00 +00:00
|
|
|
|
|
|
|
if (node->mesh >= 0) {
|
|
|
|
ModelMesh* modelMesh = &model->data->meshes[node->mesh];
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < modelMesh->primitiveCount; i++) {
|
|
|
|
uint32_t primitiveIndex = modelMesh->firstPrimitive + i;
|
|
|
|
ModelPrimitive* primitive = &model->data->primitives[primitiveIndex];
|
|
|
|
Mesh* mesh = model->meshes[primitiveIndex];
|
|
|
|
|
|
|
|
uint32_t rangeStart, rangeCount;
|
|
|
|
lovrMeshGetDrawRange(mesh, &rangeStart, &rangeCount);
|
|
|
|
|
|
|
|
lovrGraphicsBatch(&(BatchRequest) {
|
|
|
|
.type = BATCH_MESH,
|
|
|
|
.params.mesh = {
|
|
|
|
.object = mesh,
|
|
|
|
.mode = primitive->mode,
|
|
|
|
.rangeStart = rangeStart,
|
|
|
|
.rangeCount = rangeCount,
|
2019-01-13 16:41:18 +00:00
|
|
|
.instances = instances,
|
|
|
|
.pose = NULL
|
2019-01-10 19:34:00 +00:00
|
|
|
},
|
2019-01-13 16:41:18 +00:00
|
|
|
.transform = globalTransform
|
2019-01-10 19:34:00 +00:00
|
|
|
//.material = model->materials[modelMesh->material]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < node->childCount; i++) {
|
2019-01-13 16:41:18 +00:00
|
|
|
renderNode(model, node->children[i], globalTransform, instances);
|
2019-01-10 19:34:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-26 00:10:09 +00:00
|
|
|
Model* lovrModelInit(Model* model, ModelData* data) {
|
|
|
|
model->data = data;
|
|
|
|
lovrRetain(data);
|
|
|
|
|
|
|
|
if (data->viewCount > 0) {
|
|
|
|
model->buffers = calloc(data->viewCount, sizeof(Buffer*));
|
|
|
|
for (int i = 0; i < data->viewCount; i++) {
|
|
|
|
ModelView* view = &data->views[i];
|
|
|
|
ModelBlob* blob = &data->blobs[view->blob];
|
|
|
|
model->buffers[i] = lovrBufferCreate(view->length, (uint8_t*) blob->data + view->offset, BUFFER_GENERIC, USAGE_STATIC, false);
|
2017-10-21 22:20:16 +00:00
|
|
|
}
|
2017-11-21 02:19:39 +00:00
|
|
|
}
|
2017-11-21 02:17:06 +00:00
|
|
|
|
2018-09-26 00:10:09 +00:00
|
|
|
if (data->primitiveCount > 0) {
|
|
|
|
model->meshes = calloc(data->primitiveCount, sizeof(Mesh*));
|
|
|
|
for (int i = 0; i < data->primitiveCount; i++) {
|
|
|
|
ModelPrimitive* primitive = &data->primitives[i];
|
|
|
|
model->meshes[i] = lovrMeshCreateEmpty(primitive->mode);
|
|
|
|
|
|
|
|
bool setDrawRange = false;
|
|
|
|
for (int j = 0; j < MAX_DEFAULT_ATTRIBUTES; j++) {
|
|
|
|
if (primitive->attributes[j] >= 0) {
|
|
|
|
ModelAccessor* accessor = &data->accessors[primitive->attributes[j]];
|
|
|
|
|
|
|
|
lovrMeshAttachAttribute(model->meshes[i], lovrShaderAttributeNames[j], &(MeshAttribute) {
|
|
|
|
.buffer = model->buffers[accessor->view],
|
|
|
|
.offset = accessor->offset,
|
|
|
|
.stride = data->views[accessor->view].stride,
|
|
|
|
.type = accessor->type,
|
|
|
|
.components = accessor->components,
|
|
|
|
.enabled = true
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!setDrawRange && primitive->indices == -1) {
|
|
|
|
lovrMeshSetDrawRange(model->meshes[i], 0, accessor->count);
|
|
|
|
setDrawRange = true;
|
2018-09-01 13:27:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-26 00:10:09 +00:00
|
|
|
lovrMeshAttachAttribute(model->meshes[i], "lovrDrawID", &(MeshAttribute) {
|
|
|
|
.buffer = lovrGraphicsGetIdentityBuffer(),
|
|
|
|
.type = U8,
|
|
|
|
.components = 1,
|
|
|
|
.divisor = 1,
|
|
|
|
.integer = true,
|
|
|
|
.enabled = true
|
|
|
|
});
|
2018-01-04 16:49:39 +00:00
|
|
|
|
2018-09-26 00:10:09 +00:00
|
|
|
if (primitive->indices >= 0) {
|
|
|
|
ModelAccessor* accessor = &data->accessors[primitive->indices];
|
|
|
|
lovrMeshSetIndexBuffer(model->meshes[i], model->buffers[accessor->view], accessor->count, accessor->type == U16 ? 2 : 4);
|
2019-01-10 19:34:00 +00:00
|
|
|
lovrMeshSetDrawRange(model->meshes[i], 0, accessor->count);
|
2018-09-26 00:10:09 +00:00
|
|
|
}
|
2018-01-04 16:49:39 +00:00
|
|
|
}
|
2017-11-14 01:47:56 +00:00
|
|
|
}
|
|
|
|
|
2016-10-04 04:54:27 +00:00
|
|
|
return model;
|
|
|
|
}
|
|
|
|
|
2018-02-26 08:59:03 +00:00
|
|
|
void lovrModelDestroy(void* ref) {
|
|
|
|
Model* model = ref;
|
2018-09-26 00:10:09 +00:00
|
|
|
for (int i = 0; i < model->data->viewCount; i++) {
|
|
|
|
lovrRelease(model->buffers[i]);
|
2018-01-30 05:44:32 +00:00
|
|
|
}
|
2018-09-26 00:10:09 +00:00
|
|
|
for (int i = 0; i < model->data->primitiveCount; i++) {
|
|
|
|
lovrRelease(model->meshes[i]);
|
2017-11-26 03:02:28 +00:00
|
|
|
}
|
2018-09-26 00:10:09 +00:00
|
|
|
lovrRelease(model->data);
|
2016-10-04 04:54:27 +00:00
|
|
|
}
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2017-11-26 03:45:44 +00:00
|
|
|
void lovrModelDraw(Model* model, mat4 transform, int instances) {
|
2019-01-13 18:26:35 +00:00
|
|
|
renderNode(model, 0, transform, instances); // TODO use root
|
2017-11-02 02:27:58 +00:00
|
|
|
}
|