2017-12-10 20:40:37 +00:00
|
|
|
#include "api.h"
|
2019-04-05 11:58:29 +00:00
|
|
|
#include "graphics/material.h"
|
2017-03-11 11:08:07 +00:00
|
|
|
#include "graphics/model.h"
|
2019-05-24 22:14:09 +00:00
|
|
|
#include "data/modelData.h"
|
2019-07-12 03:00:36 +00:00
|
|
|
#include "core/maf.h"
|
2016-10-31 20:54:32 +00:00
|
|
|
|
2019-09-20 02:21:31 +00:00
|
|
|
static uint32_t luax_checkanimation(lua_State* L, int index, Model* model) {
|
|
|
|
switch (lua_type(L, index)) {
|
|
|
|
case LUA_TSTRING: {
|
2019-09-07 22:07:07 +00:00
|
|
|
size_t length;
|
|
|
|
const char* name = lua_tolstring(L, index, &length);
|
2019-09-20 02:21:31 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2020-01-23 19:18:04 +00:00
|
|
|
uint64_t animationIndex = map_get(&modelData->animationMap, hash64(name, length));
|
|
|
|
lovrAssert(animationIndex != MAP_NIL, "Model has no animation named '%s'", name);
|
|
|
|
return (uint32_t) animationIndex;
|
2019-09-20 02:21:31 +00:00
|
|
|
}
|
|
|
|
case LUA_TNUMBER: return lua_tointeger(L, index) - 1;
|
|
|
|
default: return luaL_typerror(L, index, "number or string");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrModelDraw(lua_State* L) {
|
2016-11-19 08:57:18 +00:00
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
2017-01-20 03:11:42 +00:00
|
|
|
float transform[16];
|
2019-01-31 00:13:44 +00:00
|
|
|
int index = luax_readmat4(L, 2, transform, 1);
|
2018-12-12 06:16:40 +00:00
|
|
|
int instances = luaL_optinteger(L, index, 1);
|
2017-11-26 03:45:44 +00:00
|
|
|
lovrModelDraw(model, transform, instances);
|
2016-10-31 20:54:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2016-11-08 22:51:58 +00:00
|
|
|
|
2019-05-24 22:14:09 +00:00
|
|
|
static int l_lovrModelAnimate(lua_State* L) {
|
2019-01-13 19:08:06 +00:00
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
2019-09-20 02:21:31 +00:00
|
|
|
uint32_t animation = luax_checkanimation(L, 2, model);
|
2019-05-24 22:14:09 +00:00
|
|
|
float time = luaL_checknumber(L, 3);
|
|
|
|
float alpha = luax_optfloat(L, 4, 1.f);
|
|
|
|
lovrModelAnimate(model, animation, time, alpha);
|
2019-01-13 19:08:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-07-12 03:00:36 +00:00
|
|
|
static int l_lovrModelPose(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
|
|
|
|
uint32_t node;
|
|
|
|
switch (lua_type(L, 2)) {
|
|
|
|
case LUA_TNONE:
|
|
|
|
case LUA_TNIL:
|
|
|
|
lovrModelResetPose(model);
|
|
|
|
return 0;
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
node = lua_tointeger(L, 2) - 1;
|
|
|
|
break;
|
|
|
|
case LUA_TSTRING: {
|
2019-09-07 22:07:07 +00:00
|
|
|
size_t length;
|
|
|
|
const char* name = lua_tolstring(L, 2, &length);
|
2019-07-12 03:00:36 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2019-09-07 22:07:07 +00:00
|
|
|
uint64_t index = map_get(&modelData->nodeMap, hash64(name, length));
|
|
|
|
lovrAssert(index != MAP_NIL, "Model has no node named '%s'", name);
|
|
|
|
node = (uint32_t) index;
|
2019-07-12 03:00:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return luaL_typerror(L, 2, "nil, number, or string");
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = 3;
|
|
|
|
float position[4], rotation[4];
|
|
|
|
index = luax_readvec3(L, index, position, NULL);
|
|
|
|
index = luax_readquat(L, index, rotation, NULL);
|
|
|
|
float alpha = luax_optfloat(L, index, 1.f);
|
|
|
|
lovrModelPose(model, node, position, rotation, alpha);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrModelGetMaterial(lua_State* L) {
|
2019-02-14 07:55:47 +00:00
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
|
2019-08-09 23:10:46 +00:00
|
|
|
uint32_t material;
|
|
|
|
switch (lua_type(L, 2)) {
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
material = lua_tointeger(L, 2) - 1;
|
|
|
|
break;
|
|
|
|
case LUA_TSTRING: {
|
2019-09-07 22:07:07 +00:00
|
|
|
size_t length;
|
|
|
|
const char* name = lua_tolstring(L, 2, &length);
|
2019-08-09 23:10:46 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2019-09-07 22:07:07 +00:00
|
|
|
uint64_t index = map_get(&modelData->materialMap, hash64(name, length));
|
|
|
|
lovrAssert(index != MAP_NIL, "Model has no material named '%s'", name);
|
|
|
|
material = (uint32_t) index;
|
2019-08-09 23:10:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return luaL_typerror(L, 2, "nil, number, or string");
|
2019-02-14 07:55:47 +00:00
|
|
|
}
|
2019-08-09 23:10:46 +00:00
|
|
|
|
|
|
|
luax_pushtype(L, Material, lovrModelGetMaterial(model, material));
|
|
|
|
return 1;
|
2019-02-14 07:55:47 +00:00
|
|
|
}
|
|
|
|
|
2019-02-17 22:52:22 +00:00
|
|
|
static int l_lovrModelGetAABB(lua_State* L) {
|
2019-01-23 18:24:08 +00:00
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
float aabb[6];
|
|
|
|
lovrModelGetAABB(model, aabb);
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
lua_pushnumber(L, aabb[i]);
|
|
|
|
}
|
|
|
|
return 6;
|
|
|
|
}
|
|
|
|
|
2019-07-12 03:00:36 +00:00
|
|
|
static int l_lovrModelGetNodePose(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
uint32_t node;
|
|
|
|
switch (lua_type(L, 2)) {
|
|
|
|
case LUA_TNUMBER:
|
|
|
|
node = lua_tointeger(L, 2) - 1;
|
|
|
|
break;
|
|
|
|
case LUA_TSTRING: {
|
2019-09-07 22:07:07 +00:00
|
|
|
size_t length;
|
|
|
|
const char* name = lua_tolstring(L, 2, &length);
|
2019-07-12 03:00:36 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2019-09-07 22:07:07 +00:00
|
|
|
uint64_t index = map_get(&modelData->nodeMap, hash64(name, length));
|
|
|
|
lovrAssert(index != MAP_NIL, "Model has no node named '%s'", name);
|
|
|
|
node = (uint32_t) index;
|
2019-07-12 03:00:36 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return luaL_typerror(L, 2, "number or string");
|
|
|
|
}
|
|
|
|
|
|
|
|
float position[4], rotation[4], angle, ax, ay, az;
|
2020-02-17 02:31:02 +00:00
|
|
|
CoordinateSpace space = luax_checkenum(L, 3, CoordinateSpaces, "global", "CoordinateSpace");
|
2019-07-12 03:00:36 +00:00
|
|
|
lovrModelGetNodePose(model, node, position, rotation, space);
|
|
|
|
lua_pushnumber(L, position[0]);
|
|
|
|
lua_pushnumber(L, position[1]);
|
|
|
|
lua_pushnumber(L, position[2]);
|
|
|
|
quat_getAngleAxis(rotation, &angle, &ax, &ay, &az);
|
|
|
|
lua_pushnumber(L, angle);
|
|
|
|
lua_pushnumber(L, ax);
|
|
|
|
lua_pushnumber(L, ay);
|
|
|
|
lua_pushnumber(L, az);
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
|
2019-09-05 01:09:54 +00:00
|
|
|
static int l_lovrModelGetAnimationName(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
2019-09-07 22:07:07 +00:00
|
|
|
uint32_t index = luaL_checkinteger(L, 2);
|
2019-09-05 01:09:54 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2019-09-07 22:07:07 +00:00
|
|
|
lovrAssert(index > 0 && index <= modelData->animationCount, "Model has no animation at index %d", index);
|
|
|
|
lua_pushstring(L, modelData->animations[index - 1].name);
|
|
|
|
return 1;
|
2019-09-05 01:09:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrModelGetMaterialName(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
2019-09-07 22:07:07 +00:00
|
|
|
uint32_t index = luaL_checkinteger(L, 2);
|
2019-09-05 01:09:54 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2019-09-07 22:07:07 +00:00
|
|
|
lovrAssert(index > 0 && index <= modelData->materialCount, "Model has no material at index %d", index);
|
|
|
|
lua_pushstring(L, modelData->materials[index - 1].name);
|
|
|
|
return 1;
|
2019-09-05 01:09:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrModelGetNodeName(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
2019-09-07 22:07:07 +00:00
|
|
|
uint32_t index = luaL_checkinteger(L, 2);
|
2019-09-05 01:09:54 +00:00
|
|
|
ModelData* modelData = lovrModelGetModelData(model);
|
2019-09-07 22:07:07 +00:00
|
|
|
lovrAssert(index > 0 && index <= modelData->nodeCount, "Model has no node at index %d", index);
|
|
|
|
lua_pushstring(L, modelData->nodes[index - 1].name);
|
|
|
|
return 1;
|
2019-09-05 01:09:54 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 22:02:24 +00:00
|
|
|
static int l_lovrModelGetAnimationCount(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
lua_pushinteger(L, lovrModelGetModelData(model)->animationCount);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrModelGetMaterialCount(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
lua_pushinteger(L, lovrModelGetModelData(model)->materialCount);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int l_lovrModelGetNodeCount(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
lua_pushinteger(L, lovrModelGetModelData(model)->nodeCount);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-09-20 02:21:31 +00:00
|
|
|
static int l_lovrModelGetAnimationDuration(lua_State* L) {
|
|
|
|
Model* model = luax_checktype(L, 1, Model);
|
|
|
|
uint32_t animation = luax_checkanimation(L, 2, model);
|
|
|
|
lua_pushnumber(L, lovrModelGetModelData(model)->animations[animation].duration);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-03-11 11:08:07 +00:00
|
|
|
const luaL_Reg lovrModel[] = {
|
|
|
|
{ "draw", l_lovrModelDraw },
|
2019-05-24 22:14:09 +00:00
|
|
|
{ "animate", l_lovrModelAnimate },
|
2019-07-12 03:00:36 +00:00
|
|
|
{ "pose", l_lovrModelPose },
|
2019-02-14 07:55:47 +00:00
|
|
|
{ "getMaterial", l_lovrModelGetMaterial },
|
2019-01-23 18:24:08 +00:00
|
|
|
{ "getAABB", l_lovrModelGetAABB },
|
2019-07-12 03:00:36 +00:00
|
|
|
{ "getNodePose", l_lovrModelGetNodePose },
|
2019-09-05 01:09:54 +00:00
|
|
|
{ "getAnimationName", l_lovrModelGetAnimationName },
|
|
|
|
{ "getMaterialName", l_lovrModelGetMaterialName },
|
|
|
|
{ "getNodeName", l_lovrModelGetNodeName },
|
2019-08-27 22:02:24 +00:00
|
|
|
{ "getAnimationCount", l_lovrModelGetAnimationCount },
|
|
|
|
{ "getMaterialCount", l_lovrModelGetMaterialCount },
|
|
|
|
{ "getNodeCount", l_lovrModelGetNodeCount },
|
2019-09-20 02:21:31 +00:00
|
|
|
{ "getAnimationDuration", l_lovrModelGetAnimationDuration },
|
2017-03-11 11:08:07 +00:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|