diff --git a/src/graphics/mesh.c b/src/graphics/mesh.c index e0f8e280..fa38710f 100644 --- a/src/graphics/mesh.c +++ b/src/graphics/mesh.c @@ -121,7 +121,6 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform) { } lovrGraphicsSetDefaultShader(SHADER_DEFAULT); - lovrGraphicsBindTexture(NULL, TEXTURE_2D, 0); lovrGraphicsPrepare(); lovrGraphicsBindVertexArray(mesh->vao); lovrMeshBindAttributes(mesh); diff --git a/src/graphics/model.c b/src/graphics/model.c index 495be5b0..08eefbd9 100644 --- a/src/graphics/model.c +++ b/src/graphics/model.c @@ -6,12 +6,17 @@ static void renderNode(Model* model, int nodeIndex) { ModelNode* node = &model->modelData->nodes[nodeIndex]; + Material* currentMaterial = lovrGraphicsGetMaterial(); + int useMaterials = currentMaterial->isDefault; lovrGraphicsPush(); lovrGraphicsMatrixTransform(MATRIX_MODEL, node->transform); for (int i = 0; i < node->primitives.length; i++) { ModelPrimitive* primitive = &model->modelData->primitives[node->primitives.data[i]]; + if (useMaterials) { + lovrGraphicsSetMaterial(model->materials[primitive->material]); + } lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount); lovrMeshDraw(model->mesh, NULL); } @@ -21,6 +26,9 @@ static void renderNode(Model* model, int nodeIndex) { } lovrGraphicsPop(); + if (useMaterials) { + lovrGraphicsSetMaterial(currentMaterial); + } } Model* lovrModelCreate(ModelData* modelData) { @@ -52,12 +60,21 @@ Model* lovrModelCreate(ModelData* modelData) { lovrMeshSetVertexMap(model->mesh, modelData->indices, modelData->indexCount); lovrMeshSetRangeEnabled(model->mesh, 1); + model->materials = malloc(modelData->materialCount * sizeof(Material*)); + for (int i = 0; i < modelData->materialCount; i++) { + model->materials[i] = lovrMaterialCreate(&modelData->materials[i], 0); + } + vec_deinit(&format); return model; } void lovrModelDestroy(const Ref* ref) { Model* model = containerof(ref, Model); + for (int i = 0; i < model->modelData->materialCount; i++) { + lovrRelease(&model->materials[i]->ref); + } + free(model->materials); lovrModelDataDestroy(model->modelData); lovrRelease(&model->mesh->ref); free(model); diff --git a/src/graphics/model.h b/src/graphics/model.h index 78b9943c..b21f3385 100644 --- a/src/graphics/model.h +++ b/src/graphics/model.h @@ -1,4 +1,5 @@ #include "loaders/model.h" +#include "graphics/material.h" #include "graphics/mesh.h" #include "graphics/texture.h" #include "math/math.h" @@ -11,6 +12,7 @@ typedef struct { Ref ref; ModelData* modelData; Mesh* mesh; + Material** materials; } Model; Model* lovrModelCreate(ModelData* modelData); diff --git a/src/loaders/model.c b/src/loaders/model.c index 767ed96a..654c648c 100644 --- a/src/loaders/model.c +++ b/src/loaders/model.c @@ -1,6 +1,7 @@ #include "loaders/model.h" #include "filesystem/filesystem.h" #include "math/mat4.h" +#include #include #include #include @@ -151,6 +152,7 @@ ModelData* lovrModelDataCreate(Blob* blob) { int index = 0; for (unsigned int m = 0; m < scene->mNumMeshes; m++) { struct aiMesh* assimpMesh = scene->mMeshes[m]; + modelData->primitives[m].material = assimpMesh->mMaterialIndex; modelData->primitives[m].drawStart = index; modelData->primitives[m].drawCount = 0; @@ -196,6 +198,46 @@ ModelData* lovrModelDataCreate(Blob* blob) { } } + // Materials + modelData->materialCount = scene->mNumMaterials; + modelData->materials = malloc(modelData->materialCount * sizeof(MaterialData)); + for (unsigned int m = 0; m < scene->mNumMaterials; m++) { + MaterialData* materialData = lovrMaterialDataCreateEmpty(); + struct aiMaterial* material = scene->mMaterials[m]; + struct aiColor4D color; + struct aiString str; + + if (aiGetMaterialColor(material, AI_MATKEY_COLOR_DIFFUSE, &color) == aiReturn_SUCCESS) { + materialData->colors[COLOR_DIFFUSE].r = color.r * 255; + materialData->colors[COLOR_DIFFUSE].g = color.g * 255; + materialData->colors[COLOR_DIFFUSE].b = color.b * 255; + materialData->colors[COLOR_DIFFUSE].a = color.a * 255; + } + + if (aiGetMaterialTexture(material, aiTextureType_DIFFUSE, 0, &str, NULL, NULL, NULL, NULL, NULL, NULL) == aiReturn_SUCCESS) { + char* path = str.data; + + if (strstr(path, "./") == path) { + path += 2; + } else if (path[0] == '/') { + lovrThrow("Absolute paths are not supported"); + } + + char fullpath[LOVR_PATH_MAX]; + char* dir = dirname((char*) blob->name); + snprintf(fullpath, LOVR_PATH_MAX, "%s/%s", dir, path); + + size_t size; + void* data = lovrFilesystemRead(fullpath, &size); + if (data) { + Blob* blob = lovrBlobCreate(data, size, path); + materialData->textures[TEXTURE_DIFFUSE] = lovrTextureDataFromBlob(blob); + } + } + + modelData->materials[m] = *materialData; + } + // Nodes modelData->nodeCount = 0; assimpSumChildren(scene->mRootNode, &modelData->nodeCount); @@ -209,13 +251,18 @@ ModelData* lovrModelDataCreate(Blob* blob) { } void lovrModelDataDestroy(ModelData* modelData) { -for (int i = 0; i < modelData->nodeCount; i++) { + for (int i = 0; i < modelData->nodeCount; i++) { vec_deinit(&modelData->nodes[i].children); vec_deinit(&modelData->nodes[i].primitives); } + for (int i = 0; i < modelData->materialCount; i++) { + lovrMaterialDataDestroy(&modelData->materials[i]); + } + free(modelData->nodes); free(modelData->primitives); + free(modelData->materials); free(modelData->vertices); free(modelData->indices); free(modelData); diff --git a/src/loaders/model.h b/src/loaders/model.h index 9b838ca1..b0f03567 100644 --- a/src/loaders/model.h +++ b/src/loaders/model.h @@ -1,10 +1,12 @@ #include "filesystem/blob.h" +#include "loaders/material.h" #include "util.h" #include "lib/vec/vec.h" #pragma once typedef struct { + int material; int drawStart; int drawCount; } ModelPrimitive; @@ -19,10 +21,12 @@ typedef struct ModelNode { typedef struct { ModelNode* nodes; ModelPrimitive* primitives; + MaterialData* materials; float* vertices; uint32_t* indices; int nodeCount; int primitiveCount; + int materialCount; int vertexCount; int vertexSize; int indexCount;