lovr/src/graphics/model.c

215 lines
7.0 KiB
C
Raw Normal View History

2016-11-19 09:28:01 +00:00
#include "graphics/model.h"
#include "graphics/graphics.h"
2018-07-04 20:51:35 +00:00
#include "graphics/shader.h"
#include "data/blob.h"
#include "data/textureData.h"
#include "data/vertexData.h"
2017-01-21 03:55:54 +00:00
#include "math/mat4.h"
2016-10-04 04:54:27 +00:00
#include <stdlib.h>
2018-07-04 20:51:35 +00:00
#include <string.h>
#include <stdio.h>
2016-10-04 04:54:27 +00:00
static void renderNode(Model* model, int nodeIndex, int instances) {
ModelNode* node = &model->modelData->nodes[nodeIndex];
2017-11-21 02:19:39 +00:00
if (node->primitives.length > 0) {
float globalInverse[16];
2017-11-21 05:16:16 +00:00
if (model->animator) {
mat4_set(globalInverse, model->nodeTransforms[nodeIndex]);
mat4_invert(globalInverse);
2017-11-21 02:19:39 +00:00
}
2016-10-31 20:54:32 +00:00
2017-11-21 02:19:39 +00:00
for (int i = 0; i < node->primitives.length; i++) {
ModelPrimitive* primitive = &model->modelData->primitives[node->primitives.data[i]];
if (model->animator) {
for (int i = 0; i < primitive->boneCount; i++) {
Bone* bone = &primitive->bones[i];
int nodeIndex = *(int*) map_get(&model->modelData->nodeMap, bone->name);
mat4 bonePose = model->pose[i];
mat4_identity(bonePose);
mat4_set(bonePose, globalInverse);
mat4_multiply(bonePose, model->nodeTransforms[nodeIndex]);
mat4_multiply(bonePose, bone->offset);
}
}
2018-01-30 05:44:32 +00:00
if (!model->material && model->materials) {
lovrMeshSetMaterial(model->mesh, model->materials[primitive->material]);
2017-11-21 02:19:39 +00:00
}
2017-11-21 02:19:39 +00:00
lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount);
2018-03-22 15:45:05 +00:00
lovrMeshSetPose(model->mesh, (float*) model->pose);
2018-08-31 13:03:35 +00:00
lovrGraphicsDraw(&(DrawCommand) {
2018-07-14 00:12:30 +00:00
.transform = model->nodeTransforms[nodeIndex],
.mesh = model->mesh,
2018-07-15 06:50:06 +00:00
.material = lovrMeshGetMaterial(model->mesh),
2018-07-14 00:12:30 +00:00
.instances = instances
});
2017-10-21 22:20:16 +00:00
}
2017-11-21 02:19:39 +00:00
}
for (int i = 0; i < node->children.length; i++) {
renderNode(model, node->children.data[i], instances);
2016-10-31 20:54:32 +00:00
}
}
2016-11-25 08:49:19 +00:00
Model* lovrModelCreate(ModelData* modelData) {
2018-07-25 02:14:29 +00:00
Model* model = lovrAlloc(Model, lovrModelDestroy);
2016-11-08 22:44:03 +00:00
if (!model) return NULL;
2018-02-26 08:59:03 +00:00
lovrRetain(modelData);
2016-11-25 08:49:19 +00:00
model->modelData = modelData;
2017-11-02 02:27:58 +00:00
model->aabbDirty = true;
2016-10-31 20:54:32 +00:00
model->mesh = lovrMeshCreate(modelData->vertexData->count, modelData->vertexData->format, MESH_TRIANGLES, USAGE_STATIC);
2018-06-04 02:00:31 +00:00
VertexPointer vertices = lovrMeshMapVertices(model->mesh, 0, modelData->vertexData->count, false, true);
memcpy(vertices.raw, modelData->vertexData->blob.data, modelData->vertexData->count * modelData->vertexData->format.stride);
2018-03-21 21:48:46 +00:00
IndexPointer indices = lovrMeshWriteIndices(model->mesh, modelData->indexCount, modelData->indexSize);
memcpy(indices.raw, modelData->indices.raw, modelData->indexCount * modelData->indexSize);
2016-10-31 20:54:32 +00:00
2018-01-30 05:44:32 +00:00
if (modelData->textures.length > 0) {
2018-03-21 22:00:28 +00:00
model->textures = calloc(modelData->textures.length, sizeof(Texture*));
2018-01-30 05:44:32 +00:00
for (int i = 0; i < modelData->textures.length; i++) {
if (modelData->textures.data[i]) {
model->textures[i] = lovrTextureCreate(TEXTURE_2D, (TextureData**) &modelData->textures.data[i], 1, i == 2, true, 0);
2018-01-30 05:44:32 +00:00
}
}
}
if (modelData->materialCount > 0) {
2018-03-21 22:00:28 +00:00
model->materials = calloc(modelData->materialCount, sizeof(Material*));
2018-01-30 05:44:32 +00:00
for (int i = 0; i < modelData->materialCount; i++) {
ModelMaterial* materialData = &modelData->materials[i];
2018-07-18 07:34:21 +00:00
Material* material = lovrMaterialCreate();
2018-02-12 03:16:40 +00:00
lovrMaterialSetScalar(material, SCALAR_METALNESS, materialData->metalness);
lovrMaterialSetScalar(material, SCALAR_ROUGHNESS, materialData->roughness);
2018-01-30 05:44:32 +00:00
lovrMaterialSetColor(material, COLOR_DIFFUSE, materialData->diffuseColor);
2018-02-12 03:16:40 +00:00
lovrMaterialSetColor(material, COLOR_EMISSIVE, materialData->emissiveColor);
2018-01-30 05:44:32 +00:00
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, model->textures[materialData->diffuseTexture]);
2018-02-12 03:16:40 +00:00
lovrMaterialSetTexture(material, TEXTURE_EMISSIVE, model->textures[materialData->emissiveTexture]);
lovrMaterialSetTexture(material, TEXTURE_METALNESS, model->textures[materialData->metalnessTexture]);
lovrMaterialSetTexture(material, TEXTURE_ROUGHNESS, model->textures[materialData->roughnessTexture]);
lovrMaterialSetTexture(material, TEXTURE_OCCLUSION, model->textures[materialData->occlusionTexture]);
lovrMaterialSetTexture(material, TEXTURE_NORMAL, model->textures[materialData->normalTexture]);
2018-01-30 05:44:32 +00:00
model->materials[i] = material;
}
2017-10-21 22:20:16 +00:00
}
for (int i = 0; i < MAX_BONES; i++) {
2017-11-21 02:42:29 +00:00
mat4_identity(model->pose[i]);
}
2017-11-21 02:50:06 +00:00
model->nodeTransforms = malloc(16 * modelData->nodeCount * sizeof(float));
2017-11-20 00:45:00 +00:00
for (int i = 0; i < modelData->nodeCount; i++) {
2018-01-04 16:49:39 +00:00
ModelNode* node = &model->modelData->nodes[i];
2017-11-21 02:50:06 +00:00
mat4 transform = model->nodeTransforms[i];
2018-01-04 16:49:39 +00:00
if (node->parent >= 0) {
mat4_set(transform, model->nodeTransforms[node->parent]);
mat4_multiply(transform, node->transform);
} else {
mat4_set(transform, node->transform);
}
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-01-30 05:44:32 +00:00
for (int i = 0; i < model->modelData->textures.length; i++) {
2018-02-26 08:59:03 +00:00
lovrRelease(model->textures[i]);
2018-01-30 05:44:32 +00:00
}
2017-10-21 22:20:16 +00:00
for (int i = 0; i < model->modelData->materialCount; i++) {
2018-02-26 08:59:03 +00:00
lovrRelease(model->materials[i]);
}
2018-02-26 08:59:03 +00:00
lovrRelease(model->animator);
lovrRelease(model->material);
2018-01-30 05:44:32 +00:00
free(model->textures);
2017-10-21 22:20:16 +00:00
free(model->materials);
2018-02-26 08:59:03 +00:00
lovrRelease(model->modelData);
lovrRelease(model->mesh);
2017-11-21 02:50:06 +00:00
free(model->nodeTransforms);
2016-10-04 04:54:27 +00:00
free(model);
}
2016-10-31 20:54:32 +00:00
void lovrModelDraw(Model* model, mat4 transform, int instances) {
if (model->modelData->nodeCount == 0) {
return;
}
if (model->animator) {
2017-11-20 00:45:00 +00:00
for (int i = 0; i < model->modelData->nodeCount; i++) {
ModelNode* node = &model->modelData->nodes[i];
2017-11-21 02:50:06 +00:00
float localTransform[16];
mat4_identity(localTransform);
if (!lovrAnimatorEvaluate(model->animator, node->name, localTransform)) {
mat4_set(localTransform, node->transform);
2017-11-20 00:45:00 +00:00
}
2017-11-21 02:50:06 +00:00
mat4 globalTransform = model->nodeTransforms[i];
2017-11-20 00:45:00 +00:00
if (node->parent >= 0) {
2017-11-21 02:50:06 +00:00
mat4_set(globalTransform, model->nodeTransforms[node->parent]);
mat4_multiply(globalTransform, localTransform);
2017-11-20 00:45:00 +00:00
} else {
2017-11-21 02:50:06 +00:00
mat4_set(globalTransform, localTransform);
2017-11-20 00:45:00 +00:00
}
}
}
if (model->material) {
lovrMeshSetMaterial(model->mesh, model->material);
}
lovrGraphicsPush();
2018-03-05 07:06:34 +00:00
lovrGraphicsMatrixTransform(transform);
renderNode(model, 0, instances);
lovrGraphicsPop();
2018-03-22 15:45:05 +00:00
lovrMeshSetPose(model->mesh, NULL);
2016-10-31 20:54:32 +00:00
}
2016-11-08 22:51:58 +00:00
2017-11-05 21:41:47 +00:00
Animator* lovrModelGetAnimator(Model* model) {
return model->animator;
}
void lovrModelSetAnimator(Model* model, Animator* animator) {
if (model->animator != animator) {
2018-02-26 08:59:03 +00:00
lovrRetain(animator);
lovrRelease(model->animator);
model->animator = animator;
}
2017-11-05 21:41:47 +00:00
}
2017-11-21 02:15:10 +00:00
int lovrModelGetAnimationCount(Model* model) {
return model->modelData->animationCount;
}
Material* lovrModelGetMaterial(Model* model) {
return model->material;
}
void lovrModelSetMaterial(Model* model, Material* material) {
if (model->material != material) {
2018-02-26 08:59:03 +00:00
lovrRetain(material);
lovrRelease(model->material);
model->material = material;
}
}
2017-10-15 17:26:33 +00:00
Mesh* lovrModelGetMesh(Model* model) {
return model->mesh;
}
2017-11-02 02:27:58 +00:00
const float* lovrModelGetAABB(Model* model) {
if (model->aabbDirty) {
lovrModelDataGetAABB(model->modelData, model->aabb);
model->aabbDirty = false;
}
return model->aabb;
}