diff --git a/src/api.h b/src/api.h index 131c1da0..022f75b3 100644 --- a/src/api.h +++ b/src/api.h @@ -46,6 +46,7 @@ extern const luaL_Reg lovrJoint[]; extern const luaL_Reg lovrMaterial[]; extern const luaL_Reg lovrMesh[]; extern const luaL_Reg lovrModel[]; +extern const luaL_Reg lovrModelData[]; extern const luaL_Reg lovrRandomGenerator[]; extern const luaL_Reg lovrRasterizer[]; extern const luaL_Reg lovrShader[]; diff --git a/src/api/data.c b/src/api/data.c index 97a22e4d..fcb2acdf 100644 --- a/src/api/data.c +++ b/src/api/data.c @@ -1,6 +1,7 @@ #include "api.h" #include "data/data.h" #include "data/audioStream.h" +#include "data/model.h" #include "data/rasterizer.h" #include "data/texture.h" @@ -8,6 +9,7 @@ int l_lovrDataInit(lua_State* L) { lua_newtable(L); luaL_register(L, NULL, lovrData); luax_registertype(L, "AudioStream", lovrAudioStream); + luax_registertype(L, "ModelData", lovrModelData); luax_registertype(L, "Rasterizer", lovrRasterizer); luax_registertype(L, "TextureData", lovrTextureData); return 1; @@ -23,6 +25,15 @@ int l_lovrDataNewAudioStream(lua_State* L) { return 1; } +int l_lovrDataNewModelData(lua_State* L) { + Blob* blob = luax_readblob(L, 1, "Model"); + ModelData* modelData = lovrModelDataCreate(blob); + luax_pushtype(L, ModelData, modelData); + lovrRelease(&blob->ref); + lovrRelease(&modelData->ref); + return 1; +} + int l_lovrDataNewTextureData(lua_State* L) { Blob* blob = luax_readblob(L, 1, "Texture"); TextureData* textureData = lovrTextureDataFromBlob(blob); @@ -56,6 +67,7 @@ int l_lovrDataNewRasterizer(lua_State* L) { const luaL_Reg lovrData[] = { { "newAudioStream", l_lovrDataNewAudioStream }, + { "newModelData", l_lovrDataNewModelData }, { "newRasterizer", l_lovrDataNewRasterizer }, { "newTextureData", l_lovrDataNewTextureData }, { NULL, NULL } diff --git a/src/api/graphics.c b/src/api/graphics.c index a0b666a6..5daabb79 100644 --- a/src/api/graphics.c +++ b/src/api/graphics.c @@ -956,8 +956,16 @@ int l_lovrGraphicsNewMesh(lua_State* L) { } int l_lovrGraphicsNewModel(lua_State* L) { - Blob* blob = luax_readblob(L, 1, "Model"); - ModelData* modelData = lovrModelDataCreate(blob); + ModelData* modelData; + void** type; + if ((type = luax_totype(L, 1, ModelData)) != NULL) { + modelData = *type; + } else { + Blob* blob = luax_readblob(L, 1, "Model"); + modelData = lovrModelDataCreate(blob); + lovrRelease(&blob->ref); + } + Model* model = lovrModelCreate(modelData); if (lua_gettop(L) >= 2) { @@ -979,7 +987,6 @@ int l_lovrGraphicsNewModel(lua_State* L) { luax_pushtype(L, Model, model); lovrRelease(&model->ref); - lovrRelease(&blob->ref); return 1; } diff --git a/src/api/types/modelData.c b/src/api/types/modelData.c new file mode 100644 index 00000000..a6281018 --- /dev/null +++ b/src/api/types/modelData.c @@ -0,0 +1,5 @@ +#include "api.h" + +const luaL_Reg lovrModelData[] = { + { NULL, NULL } +}; diff --git a/src/data/model.c b/src/data/model.c index 74f439b2..00d383bb 100644 --- a/src/data/model.c +++ b/src/data/model.c @@ -182,7 +182,7 @@ static void assimpFileClose(struct aiFileIO* io, struct aiFile* assimpFile) { } ModelData* lovrModelDataCreate(Blob* blob) { - ModelData* modelData = malloc(sizeof(ModelData)); + ModelData* modelData = lovrAlloc(sizeof(ModelData), lovrModelDataDestroy); if (!modelData) return NULL; struct aiFileIO assimpIO; @@ -447,7 +447,9 @@ ModelData* lovrModelDataCreate(Blob* blob) { return modelData; } -void lovrModelDataDestroy(ModelData* modelData) { +void lovrModelDataDestroy(const Ref* ref) { + ModelData* modelData = containerof(ref, ModelData); + for (int i = 0; i < modelData->nodeCount; i++) { vec_deinit(&modelData->nodes[i].children); vec_deinit(&modelData->nodes[i].primitives); diff --git a/src/data/model.h b/src/data/model.h index 48cd0860..9e724663 100644 --- a/src/data/model.h +++ b/src/data/model.h @@ -45,6 +45,7 @@ typedef struct ModelNode { } ModelNode; typedef struct { + Ref ref; ModelNode* nodes; map_int_t nodeMap; ModelPrimitive* primitives; @@ -67,5 +68,5 @@ typedef struct { } ModelData; ModelData* lovrModelDataCreate(Blob* blob); -void lovrModelDataDestroy(ModelData* modelData); +void lovrModelDataDestroy(const Ref* ref); void lovrModelDataGetAABB(ModelData* modelData, float aabb[6]); diff --git a/src/graphics/model.c b/src/graphics/model.c index 3d77b2c0..aae43998 100644 --- a/src/graphics/model.c +++ b/src/graphics/model.c @@ -53,6 +53,7 @@ Model* lovrModelCreate(ModelData* modelData) { Model* model = lovrAlloc(sizeof(Model), lovrModelDestroy); if (!model) return NULL; + lovrRetain(&modelData->ref); model->modelData = modelData; model->aabbDirty = true; model->animator = NULL; @@ -132,7 +133,7 @@ void lovrModelDestroy(const Ref* ref) { lovrRelease(&model->material->ref); } free(model->materials); - lovrModelDataDestroy(model->modelData); + lovrRelease(&model->modelData->ref); lovrRelease(&model->mesh->ref); free(model->nodeTransforms); free(model);