mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
WIP matrix & rotation lua APIs
This commit is contained in:
parent
a87ce1bad7
commit
513532a93c
15 changed files with 1509 additions and 5 deletions
239
src/script/lua_api/l_rotation.cpp
Normal file
239
src/script/lua_api/l_rotation.cpp
Normal file
|
@ -0,0 +1,239 @@
|
|||
// Luanti
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
// Copyright (C) 2025 Lars Müller
|
||||
|
||||
#include "lua_api/l_rotation.h"
|
||||
#include "common/c_packer.h"
|
||||
#include "lua_api/l_internal.h"
|
||||
|
||||
#include "common/c_converter.h"
|
||||
#include "irr_v3d.h"
|
||||
#include "quaternion.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <lauxlib.h>
|
||||
#include <lua.h>
|
||||
|
||||
core::quaternion &LuaRotation::check(lua_State *L, int index)
|
||||
{
|
||||
return static_cast<LuaRotation *>(luaL_checkudata(L, index, className))->quaternion;
|
||||
}
|
||||
|
||||
void LuaRotation::create(lua_State *L, const core::quaternion &quaternion)
|
||||
{
|
||||
auto *rot = static_cast<LuaRotation *>(lua_newuserdata(L, sizeof(LuaRotation)));
|
||||
rot->quaternion = quaternion;
|
||||
luaL_getmetatable(L, LuaRotation::className);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
int LuaRotation::l_identity(lua_State *L)
|
||||
{
|
||||
create(L, core::quaternion());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_quaternion(lua_State *L)
|
||||
{
|
||||
// TODO be more strict.
|
||||
f64 x = luaL_checknumber(L, 1);
|
||||
f64 y = luaL_checknumber(L, 2);
|
||||
f64 z = luaL_checknumber(L, 3);
|
||||
f64 w = luaL_checknumber(L, 4);
|
||||
// Note: Converted to f32
|
||||
core::quaternion q(x, y, z, w);
|
||||
q.normalize();
|
||||
create(L, q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_axis_angle(lua_State *L)
|
||||
{
|
||||
v3f axis = readParam<v3f>(L, 1);
|
||||
f64 angle = luaL_checknumber(L, 2);
|
||||
core::quaternion quaternion;
|
||||
// Note: Axis converted to f32
|
||||
axis.normalize();
|
||||
quaternion.fromAngleAxis(angle, axis);
|
||||
create(L, quaternion);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<float v3f::* C>
|
||||
int LuaRotation::l_fixed_axis_angle(lua_State *L)
|
||||
{
|
||||
f64 angle = luaL_checknumber(L, 1);
|
||||
// Note: Angle converted to f32
|
||||
v3f axis;
|
||||
axis.*C = 1.0f;
|
||||
create(L, core::quaternion().fromAngleAxis(angle, axis));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_euler_angles(lua_State *L)
|
||||
{
|
||||
v3f euler = readParam<v3f>(L, 1);
|
||||
core::quaternion quaternion;
|
||||
// Note: Euler angles converted to f32
|
||||
quaternion.set(euler.X, euler.Y, euler.Z);
|
||||
create(L, quaternion);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_to_quaternion(lua_State *L)
|
||||
{
|
||||
const auto &q = check(L, 1);
|
||||
lua_pushnumber(L, q.X);
|
||||
lua_pushnumber(L, q.Y);
|
||||
lua_pushnumber(L, q.Z);
|
||||
lua_pushnumber(L, q.W);
|
||||
return 4;
|
||||
}
|
||||
|
||||
int LuaRotation::l_to_axis_angle(lua_State *L)
|
||||
{
|
||||
const auto q = check(L, 1);
|
||||
core::vector3df axis;
|
||||
f32 angle;
|
||||
q.toAngleAxis(angle, axis);
|
||||
push_v3f(L, axis);
|
||||
lua_pushnumber(L, angle);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int LuaRotation::l_to_euler_angles(lua_State *L)
|
||||
{
|
||||
const auto &q = check(L, 1);
|
||||
core::vector3df euler;
|
||||
q.toEuler(euler);
|
||||
lua_pushnumber(L, euler.X);
|
||||
lua_pushnumber(L, euler.Y);
|
||||
lua_pushnumber(L, euler.Z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Math
|
||||
|
||||
int LuaRotation::l_apply(lua_State *L)
|
||||
{
|
||||
const auto &q = check(L, 1);
|
||||
v3f vec = readParam<v3f>(L, 2);
|
||||
push_v3f(L, q * vec);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_compose(lua_State *L)
|
||||
{
|
||||
int n_args = lua_gettop(L);
|
||||
if (n_args == 0)
|
||||
return LuaRotation::l_identity(L);
|
||||
auto product = check(L, 1);
|
||||
for (int i = 2; i <= n_args; ++i) {
|
||||
product *= check(L, i);
|
||||
}
|
||||
create(L, product);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_invert(lua_State *L)
|
||||
{
|
||||
create(L, check(L, 1).makeInverse());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_slerp(lua_State *L)
|
||||
{
|
||||
const auto &from = check(L, 1);
|
||||
const auto &to = check(L, 2);
|
||||
f32 time = readParam<Finite<f32>>(L, 3).value;
|
||||
core::quaternion result;
|
||||
result.slerp(from, to, time);
|
||||
create(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaRotation::l_angle_to(lua_State *L)
|
||||
{
|
||||
const auto &from = check(L, 1);
|
||||
const auto &to = check(L, 2);
|
||||
f32 angle = from.angleTo(to);
|
||||
lua_pushnumber(L, angle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Serialization
|
||||
|
||||
int LuaRotation::mt_tostring(lua_State *L)
|
||||
{
|
||||
const auto &q = check(L, 1);
|
||||
lua_pushfstring(L, "(%f\t%f\t%f\t%f)", q.X, q.Y, q.Z, q.W);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *LuaRotation::packIn(lua_State *L, int idx)
|
||||
{
|
||||
return new core::quaternion(check(L, idx));
|
||||
}
|
||||
|
||||
void LuaRotation::packOut(lua_State *L, void *ptr)
|
||||
{
|
||||
auto *quat = static_cast<core::quaternion *>(ptr);
|
||||
if (L)
|
||||
create(L, *quat);
|
||||
delete quat;
|
||||
}
|
||||
|
||||
void LuaRotation::Register(lua_State *L)
|
||||
{
|
||||
static const luaL_Reg metamethods[] = {
|
||||
{"__tostring", mt_tostring},
|
||||
{0, 0}
|
||||
};
|
||||
registerClass<LuaRotation>(L, methods, metamethods);
|
||||
|
||||
lua_createtable(L, 0, 0);
|
||||
int Matrix4 = lua_gettop(L);
|
||||
|
||||
#define SET_CONSTRUCTOR(name, method) \
|
||||
lua_pushcfunction(L, method); \
|
||||
lua_setfield(L, Matrix4, name); \
|
||||
|
||||
#define CONSTRUCTOR(name) SET_CONSTRUCTOR(#name, l_##name)
|
||||
|
||||
CONSTRUCTOR(identity)
|
||||
CONSTRUCTOR(quaternion)
|
||||
CONSTRUCTOR(axis_angle)
|
||||
CONSTRUCTOR(euler_angles)
|
||||
CONSTRUCTOR(compose)
|
||||
|
||||
#undef CONSTRUCTOR
|
||||
|
||||
SET_CONSTRUCTOR("x", l_fixed_axis_angle<&v3f::X>)
|
||||
SET_CONSTRUCTOR("y", l_fixed_axis_angle<&v3f::Y>)
|
||||
SET_CONSTRUCTOR("z", l_fixed_axis_angle<&v3f::Z>)
|
||||
|
||||
#undef SET_CONSTRUCTOR
|
||||
|
||||
lua_setglobal(L, className);
|
||||
|
||||
script_register_packer(L, className, packIn, packOut);
|
||||
}
|
||||
|
||||
const char LuaRotation::className[] = "Rotation";
|
||||
|
||||
#define METHOD(name) luamethod(LuaRotation, name)
|
||||
const luaL_Reg LuaRotation::methods[] = {
|
||||
METHOD(to_quaternion),
|
||||
METHOD(to_axis_angle),
|
||||
METHOD(to_euler_angles),
|
||||
METHOD(apply),
|
||||
METHOD(compose),
|
||||
METHOD(invert),
|
||||
METHOD(slerp),
|
||||
METHOD(angle_to),
|
||||
{0,0}
|
||||
};
|
||||
#undef METHOD
|
Loading…
Add table
Add a link
Reference in a new issue