lovr/src/api/l_graphics_model.c

428 lines
14 KiB
C

#include "api.h"
#include "graphics/graphics.h"
#include "data/modelData.h"
#include "core/maf.h"
#include "util.h"
// This adds about 2-3us of overhead, which sucks, but the reduction in complexity is large
static int luax_callmodeldata(lua_State* L, const char* method, int nrets) {
int nargs = lua_gettop(L);
Model* model = luax_checktype(L, 1, Model);
ModelData* data = lovrModelGetInfo(model)->data;
luax_pushtype(L, ModelData, data);
lua_pushstring(L, method);
lua_gettable(L, -2);
lua_insert(L, 1);
lua_replace(L, 2);
lua_call(L, nargs, nrets);
return nrets;
}
uint32_t luax_checkblendshape(lua_State* L, int index, Model* model) {
switch (lua_type(L, index)) {
case LUA_TSTRING: {
size_t length;
const char* name = lua_tolstring(L, index, &length);
ModelData* data = lovrModelGetInfo(model)->data;
uint64_t blendShapeIndex = map_get(&data->blendShapeMap, hash64(name, length));
lovrCheck(blendShapeIndex != MAP_NIL, "ModelData has no blend shape named '%s'", name);
return (uint32_t) blendShapeIndex;
}
case LUA_TNUMBER: {
uint32_t blendShape = luax_checku32(L, index) - 1;
ModelData* data = lovrModelGetInfo(model)->data;
lovrCheck(blendShape < data->blendShapeCount, "Invalid blend shape index '%d'", blendShape + 1);
return blendShape;
}
default: return luax_typeerror(L, index, "number or string"), ~0u;
}
}
static int l_lovrModelClone(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
Model* clone = lovrModelClone(model);
luax_pushtype(L, Model, clone);
lovrRelease(clone, lovrModelDestroy);
return 1;
}
static int l_lovrModelGetData(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
ModelData* data = lovrModelGetInfo(model)->data;
luax_pushtype(L, ModelData, data);
return 1;
}
static int l_lovrModelGetMetadata(lua_State* L) {
return luax_callmodeldata(L, "getMetadata", 1);
}
static int l_lovrModelGetRootNode(lua_State* L) {
return luax_callmodeldata(L, "getRootNode", 1);
}
static int l_lovrModelGetNodeCount(lua_State* L) {
return luax_callmodeldata(L, "getNodeCount", 1);
}
static int l_lovrModelGetNodeName(lua_State* L) {
return luax_callmodeldata(L, "getNodeName", 1);
}
static int l_lovrModelGetNodeParent(lua_State* L) {
return luax_callmodeldata(L, "getNodeParent", 1);
}
static int l_lovrModelGetNodeChildren(lua_State* L) {
return luax_callmodeldata(L, "getNodeChildren", 1);
}
static int l_lovrModelGetNodePosition(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
OriginType origin = luax_checkenum(L, 3, OriginType, "root");
float position[3], scale[3], rotation[4];
lovrModelGetNodeTransform(model, node, position, scale, rotation, origin);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
return 3;
}
static int l_lovrModelSetNodePosition(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
float position[3];
int index = luax_readvec3(L, 3, position, NULL);
float alpha = luax_optfloat(L, index, 1.f);
lovrModelSetNodeTransform(model, node, position, NULL, NULL, alpha);
return 0;
}
static int l_lovrModelGetNodeScale(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
OriginType origin = luax_checkenum(L, 3, OriginType, "root");
float position[3], scale[3], rotation[4];
lovrModelGetNodeTransform(model, node, position, scale, rotation, origin);
lua_pushnumber(L, scale[0]);
lua_pushnumber(L, scale[1]);
lua_pushnumber(L, scale[2]);
return 3;
}
static int l_lovrModelSetNodeScale(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
float scale[3];
int index = luax_readscale(L, 3, scale, 3, NULL);
float alpha = luax_optfloat(L, index, 1.f);
lovrModelSetNodeTransform(model, node, NULL, scale, NULL, alpha);
return 0;
}
static int l_lovrModelGetNodeOrientation(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
OriginType origin = luax_checkenum(L, 3, OriginType, "root");
float position[3], scale[3], rotation[4], angle, ax, ay, az;
lovrModelGetNodeTransform(model, node, position, scale, rotation, origin);
quat_getAngleAxis(rotation, &angle, &ax, &ay, &az);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 4;
}
static int l_lovrModelSetNodeOrientation(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
float rotation[4];
int index = luax_readquat(L, 3, rotation, NULL);
float alpha = luax_optfloat(L, index, 1.f);
lovrModelSetNodeTransform(model, node, NULL, NULL, rotation, alpha);
return 0;
}
static int l_lovrModelGetNodePose(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
OriginType origin = luax_checkenum(L, 3, OriginType, "root");
float position[3], scale[3], rotation[4], angle, ax, ay, az;
lovrModelGetNodeTransform(model, node, position, scale, rotation, origin);
quat_getAngleAxis(rotation, &angle, &ax, &ay, &az);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 7;
}
static int l_lovrModelSetNodePose(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
int index = 3;
float position[3], rotation[4];
index = luax_readvec3(L, index, position, NULL);
index = luax_readquat(L, index, rotation, NULL);
float alpha = luax_optfloat(L, index, 1.f);
lovrModelSetNodeTransform(model, node, position, NULL, rotation, alpha);
return 0;
}
static int l_lovrModelGetNodeTransform(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
OriginType origin = luax_checkenum(L, 3, OriginType, "root");
float position[3], scale[3], rotation[4], angle, ax, ay, az;
lovrModelGetNodeTransform(model, node, position, scale, rotation, origin);
quat_getAngleAxis(rotation, &angle, &ax, &ay, &az);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
lua_pushnumber(L, scale[0]);
lua_pushnumber(L, scale[1]);
lua_pushnumber(L, scale[2]);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 10;
}
static int l_lovrModelSetNodeTransform(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t node = luax_checknodeindex(L, 2, lovrModelGetInfo(model)->data);
int index = 3;
VectorType type;
float position[3], scale[3], rotation[4];
float* m = luax_tovector(L, index, &type);
if (m && type == V_MAT4) {
mat4_getPosition(m, position);
mat4_getScale(m, scale);
mat4_getOrientation(m, rotation);
index = 4;
} else {
index = luax_readvec3(L, index, position, NULL);
index = luax_readscale(L, index, scale, 3, NULL);
index = luax_readquat(L, index, rotation, NULL);
}
float alpha = luax_optfloat(L, index, 1.f);
lovrModelSetNodeTransform(model, node, position, scale, rotation, alpha);
return 0;
}
static int l_lovrModelResetNodeTransforms(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
lovrModelResetNodeTransforms(model);
return 0;
}
static int l_lovrModelGetAnimationCount(lua_State* L) {
return luax_callmodeldata(L, "getAnimationCount", 1);
}
static int l_lovrModelGetAnimationName(lua_State* L) {
return luax_callmodeldata(L, "getAnimationName", 1);
}
static int l_lovrModelGetAnimationDuration(lua_State* L) {
return luax_callmodeldata(L, "getAnimationDuration", 1);
}
static int l_lovrModelHasJoints(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
ModelData* data = lovrModelGetInfo(model)->data;
lua_pushboolean(L, data->skinCount > 0);
return 1;
}
static int l_lovrModelAnimate(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t animation = luax_checkanimationindex(L, 2, lovrModelGetInfo(model)->data);
float time = luax_checkfloat(L, 3);
float alpha = luax_optfloat(L, 4, 1.f);
lovrModelAnimate(model, animation, time, alpha);
return 0;
}
static int l_lovrModelGetBlendShapeCount(lua_State* L) {
return luax_callmodeldata(L, "getBlendShapeCount", 1);
}
static int l_lovrModelGetBlendShapeName(lua_State* L) {
return luax_callmodeldata(L, "getBlendShapeName", 1);
}
static int l_lovrModelGetBlendShapeWeight(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t blendShape = luax_checkblendshape(L, 2, model);
float weight = lovrModelGetBlendShapeWeight(model, blendShape);
lua_pushnumber(L, weight);
return 1;
}
static int l_lovrModelSetBlendShapeWeight(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t blendShape = luax_checkblendshape(L, 2, model);
float weight = luax_checkfloat(L, 3);
lovrModelSetBlendShapeWeight(model, blendShape, weight);
return 0;
}
static int l_lovrModelResetBlendShapes(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
lovrModelResetBlendShapes(model);
return 0;
}
static int l_lovrModelGetTriangles(lua_State* L) {
return luax_callmodeldata(L, "getTriangles", 2);
}
static int l_lovrModelGetTriangleCount(lua_State* L) {
return luax_callmodeldata(L, "getTriangleCount", 1);
}
static int l_lovrModelGetVertexCount(lua_State* L) {
return luax_callmodeldata(L, "getVertexCount", 1);
}
static int l_lovrModelGetWidth(lua_State* L) {
return luax_callmodeldata(L, "getWidth", 1);
}
static int l_lovrModelGetHeight(lua_State* L) {
return luax_callmodeldata(L, "getHeight", 1);
}
static int l_lovrModelGetDepth(lua_State* L) {
return luax_callmodeldata(L, "getDepth", 1);
}
static int l_lovrModelGetDimensions(lua_State* L) {
return luax_callmodeldata(L, "getDimensions", 3);
}
static int l_lovrModelGetCenter(lua_State* L) {
return luax_callmodeldata(L, "getCenter", 3);
}
static int l_lovrModelGetBoundingBox(lua_State* L) {
return luax_callmodeldata(L, "getBoundingBox", 6);
}
static int l_lovrModelGetBoundingSphere(lua_State* L) {
return luax_callmodeldata(L, "getBoundingSphere", 4);
}
static int l_lovrModelGetVertexBuffer(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
Buffer* buffer = lovrModelGetVertexBuffer(model);
luax_pushtype(L, Buffer, buffer);
return 1;
}
static int l_lovrModelGetIndexBuffer(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
Buffer* buffer = lovrModelGetIndexBuffer(model);
luax_pushtype(L, Buffer, buffer);
return 1;
}
static int l_lovrModelGetMeshCount(lua_State* L) {
return luax_callmodeldata(L, "getMeshCount", 1);
}
static int l_lovrModelGetMesh(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t index = luax_checku32(L, 2) - 1;
Mesh* mesh = lovrModelGetMesh(model, index);
luax_pushtype(L, Mesh, mesh);
return 1;
}
static int l_lovrModelGetTextureCount(lua_State* L) {
return luax_callmodeldata(L, "getImageCount", 1);
}
static int l_lovrModelGetTexture(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t index = luax_checku32(L, 2) - 1;
Texture* texture = lovrModelGetTexture(model, index);
luax_pushtype(L, Texture, texture);
return 1;
}
static int l_lovrModelGetMaterialCount(lua_State* L) {
return luax_callmodeldata(L, "getMaterialCount", 1);
}
static int l_lovrModelGetMaterialName(lua_State* L) {
return luax_callmodeldata(L, "getMaterialName", 1);
}
static int l_lovrModelGetMaterial(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t index = luax_checkmaterialindex(L, 2, lovrModelGetInfo(model)->data);
Material* material = lovrModelGetMaterial(model, index);
luax_pushtype(L, Material, material);
return 1;
}
const luaL_Reg lovrModel[] = {
{ "clone", l_lovrModelClone },
{ "getData", l_lovrModelGetData },
{ "getMetadata", l_lovrModelGetMetadata },
{ "getRootNode", l_lovrModelGetRootNode },
{ "getNodeCount", l_lovrModelGetNodeCount },
{ "getNodeName", l_lovrModelGetNodeName },
{ "getNodeParent", l_lovrModelGetNodeParent },
{ "getNodeChildren", l_lovrModelGetNodeChildren },
{ "getNodePosition", l_lovrModelGetNodePosition },
{ "setNodePosition", l_lovrModelSetNodePosition },
{ "getNodeOrientation", l_lovrModelGetNodeOrientation },
{ "setNodeOrientation", l_lovrModelSetNodeOrientation },
{ "getNodeScale", l_lovrModelGetNodeScale },
{ "setNodeScale", l_lovrModelSetNodeScale },
{ "getNodePose", l_lovrModelGetNodePose },
{ "setNodePose", l_lovrModelSetNodePose },
{ "getNodeTransform", l_lovrModelGetNodeTransform },
{ "setNodeTransform", l_lovrModelSetNodeTransform },
{ "resetNodeTransforms", l_lovrModelResetNodeTransforms },
{ "getAnimationCount", l_lovrModelGetAnimationCount },
{ "getAnimationName", l_lovrModelGetAnimationName },
{ "getAnimationDuration", l_lovrModelGetAnimationDuration },
{ "hasJoints", l_lovrModelHasJoints },
{ "animate", l_lovrModelAnimate },
{ "getBlendShapeCount", l_lovrModelGetBlendShapeCount },
{ "getBlendShapeName", l_lovrModelGetBlendShapeName },
{ "getBlendShapeWeight", l_lovrModelGetBlendShapeWeight },
{ "setBlendShapeWeight", l_lovrModelSetBlendShapeWeight },
{ "resetBlendShapes", l_lovrModelResetBlendShapes },
{ "getTriangles", l_lovrModelGetTriangles },
{ "getTriangleCount", l_lovrModelGetTriangleCount },
{ "getVertexCount", l_lovrModelGetVertexCount },
{ "getWidth", l_lovrModelGetWidth },
{ "getHeight", l_lovrModelGetHeight },
{ "getDepth", l_lovrModelGetDepth },
{ "getDimensions", l_lovrModelGetDimensions },
{ "getCenter", l_lovrModelGetCenter },
{ "getBoundingBox", l_lovrModelGetBoundingBox },
{ "getBoundingSphere", l_lovrModelGetBoundingSphere },
{ "getVertexBuffer", l_lovrModelGetVertexBuffer },
{ "getIndexBuffer", l_lovrModelGetIndexBuffer },
{ "getMeshCount", l_lovrModelGetMeshCount },
{ "getMesh", l_lovrModelGetMesh },
{ "getTextureCount", l_lovrModelGetTextureCount },
{ "getTexture", l_lovrModelGetTexture },
{ "getMaterialCount", l_lovrModelGetMaterialCount },
{ "getMaterialName", l_lovrModelGetMaterialName },
{ "getMaterial", l_lovrModelGetMaterial },
{ NULL, NULL }
};