Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ Thumbs.db
.project
.cproject
builtins
_codeql_detected_source_root

/xmath/include/dmsdk/*
52 changes: 52 additions & 0 deletions xmath/api/xMath.script_api
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,55 @@
type: matrix4
- name: position
type: [vector3, vector4]

- name: quat_matrix4
type: function
desc: "Set the value of a quaternion from a matrix4."
parameters:
- name: q_in_place
type: quaternion
- name: m
type: matrix4

- name: matrix4_compose
type: function
desc: "Set the value of a matrix from translation, rotation and scale."
parameters:
- name: m_in_place
type: matrix4
- name: translation
type: [vector3, vector4]
- name: rotation
type: quaternion
- name: scale
type: vector3

- name: matrix4_scale
type: function
desc: "Set the value of a matrix from scale. Can take a vector3, a single number for uniform scale, or 3 numbers for x, y, z scale."
parameters:
- name: m_in_place
type: matrix4
- name: scale
type: [vector3, number]

- name: clamp
type: function
desc: "Clamp input value in range [min, max]. For numbers, pass (value, min, max) and returns the clamped number. For vectors, pass (v_in_place, value, min, max) to modify v_in_place. min and max can be numbers or matching vector types."
parameters:
- name: value_or_out
type: [number, vector3, vector4]
desc: "For numbers, the value to clamp. For vectors, the output vector to store the result."
- name: value_or_min
type: [number, vector3, vector4]
desc: "For numbers, the minimum value. For vectors, the value to clamp."
- name: min_or_max
type: [number, vector3, vector4]
desc: "For numbers, the maximum value. For vectors, the minimum value."
- name: max
type: [number, vector3, vector4]
desc: "For vectors only, the maximum value."
returns:
- name: result
type: number
desc: "For number inputs, returns the clamped number. For vector inputs, modifies v_in_place and returns nothing."
181 changes: 181 additions & 0 deletions xmath/src/xMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,182 @@ static int xMath_matrix_translation(lua_State* L)
return 0;
}

static int xMath_quat_matrix4(lua_State* L)
{
if (dmScript::IsQuat(L, 1))
{
Vectormath::Aos::Quat *out = dmScript::CheckQuat(L, 1);
Vectormath::Aos::Matrix4 *m = dmScript::CheckMatrix4(L, 2);
Vectormath::Aos::Matrix3 m3(m->getCol0().getXYZ(), m->getCol1().getXYZ(), m->getCol2().getXYZ());
*out = Vectormath::Aos::Quat(m3);
}

return 0;
}

static int xMath_matrix4_compose(lua_State* L)
{
if (dmScript::IsMatrix4(L, 1))
{
Vectormath::Aos::Matrix4 *out = dmScript::CheckMatrix4(L, 1);
Vectormath::Aos::Vector3 translation(0, 0, 0);
if (dmScript::IsVector3(L, 2))
{
translation = *dmScript::CheckVector3(L, 2);
}
else if (dmScript::IsVector4(L, 2))
{
translation = dmScript::CheckVector4(L, 2)->getXYZ();
}
Vectormath::Aos::Quat *rotation = dmScript::CheckQuat(L, 3);
Vectormath::Aos::Vector3 *scale = dmScript::CheckVector3(L, 4);

Vectormath::Aos::Matrix3 rotationMatrix = Vectormath::Aos::Matrix3(*rotation);
Vectormath::Aos::Matrix3 scaleMatrix = Vectormath::Aos::Matrix3::scale(*scale);
Vectormath::Aos::Matrix3 rs = rotationMatrix * scaleMatrix;

*out = Vectormath::Aos::Matrix4(rs, translation);
}

return 0;
}

static int xMath_matrix4_scale(lua_State* L)
{
if (dmScript::IsMatrix4(L, 1))
{
Vectormath::Aos::Matrix4 *out = dmScript::CheckMatrix4(L, 1);
int nargs = lua_gettop(L);

if (nargs == 2)
{
if (dmScript::IsVector3(L, 2))
{
Vectormath::Aos::Vector3 *scale = dmScript::CheckVector3(L, 2);
*out = Vectormath::Aos::Matrix4::scale(*scale);
}
else if (lua_isnumber(L, 2))
{
float s = (float) luaL_checknumber(L, 2);
*out = Vectormath::Aos::Matrix4::scale(Vectormath::Aos::Vector3(s, s, s));
}
}
else if (nargs == 4)
{
float x = (float) luaL_checknumber(L, 2);
float y = (float) luaL_checknumber(L, 3);
float z = (float) luaL_checknumber(L, 4);
*out = Vectormath::Aos::Matrix4::scale(Vectormath::Aos::Vector3(x, y, z));
}
}

return 0;
}

static inline float clamp_value(float value, float min_val, float max_val)
{
if (value < min_val) return min_val;
if (value > max_val) return max_val;
return value;
}

static int xMath_clamp(lua_State* L)
{
int nargs = lua_gettop(L);

if (nargs >= 3 && lua_isnumber(L, 1))
{
// clamp(value, min, max) for numbers - returns clamped number
float value = (float) luaL_checknumber(L, 1);
float min_val = (float) luaL_checknumber(L, 2);
float max_val = (float) luaL_checknumber(L, 3);
lua_pushnumber(L, clamp_value(value, min_val, max_val));
return 1;
}
else if (dmScript::IsVector3(L, 1))
{
// clamp(out, value, min, max) for vectors - modifies out in place
Vectormath::Aos::Vector3 *out = dmScript::CheckVector3(L, 1);
Vectormath::Aos::Vector3 *value = dmScript::CheckVector3(L, 2);

float min_x, min_y, min_z;
float max_x, max_y, max_z;

if (dmScript::IsVector3(L, 3))
{
Vectormath::Aos::Vector3 *min_v = dmScript::CheckVector3(L, 3);
min_x = min_v->getX();
min_y = min_v->getY();
min_z = min_v->getZ();
}
else
{
float min_val = (float) luaL_checknumber(L, 3);
min_x = min_y = min_z = min_val;
}

if (dmScript::IsVector3(L, 4))
{
Vectormath::Aos::Vector3 *max_v = dmScript::CheckVector3(L, 4);
max_x = max_v->getX();
max_y = max_v->getY();
max_z = max_v->getZ();
}
else
{
float max_val = (float) luaL_checknumber(L, 4);
max_x = max_y = max_z = max_val;
}

out->setX(clamp_value(value->getX(), min_x, max_x));
out->setY(clamp_value(value->getY(), min_y, max_y));
out->setZ(clamp_value(value->getZ(), min_z, max_z));
}
else if (dmScript::IsVector4(L, 1))
{
Vectormath::Aos::Vector4 *out = dmScript::CheckVector4(L, 1);
Vectormath::Aos::Vector4 *value = dmScript::CheckVector4(L, 2);

float min_x, min_y, min_z, min_w;
float max_x, max_y, max_z, max_w;

if (dmScript::IsVector4(L, 3))
{
Vectormath::Aos::Vector4 *min_v = dmScript::CheckVector4(L, 3);
min_x = min_v->getX();
min_y = min_v->getY();
min_z = min_v->getZ();
min_w = min_v->getW();
}
else
{
float min_val = (float) luaL_checknumber(L, 3);
min_x = min_y = min_z = min_w = min_val;
}

if (dmScript::IsVector4(L, 4))
{
Vectormath::Aos::Vector4 *max_v = dmScript::CheckVector4(L, 4);
max_x = max_v->getX();
max_y = max_v->getY();
max_z = max_v->getZ();
max_w = max_v->getW();
}
else
{
float max_val = (float) luaL_checknumber(L, 4);
max_x = max_y = max_z = max_w = max_val;
}

out->setX(clamp_value(value->getX(), min_x, max_x));
out->setY(clamp_value(value->getY(), min_y, max_y));
out->setZ(clamp_value(value->getZ(), min_z, max_z));
out->setW(clamp_value(value->getW(), min_w, max_w));
}

return 0;
}


//* Native Extension Bindings
//* ----------------------------------------------------------------------------
Expand All @@ -561,6 +737,7 @@ static const luaL_reg xMathModule_methods[] =
{"quat_rotation_y", xMath_quat_rotation_y},
{"quat_rotation_z", xMath_quat_rotation_z},
{"quat", xMath_quat},
{"quat_matrix4", xMath_quat_matrix4},
//* Vector + Quat
{"lerp", xMath_lerp},
{"slerp", xMath_slerp},
Expand All @@ -578,6 +755,10 @@ static const luaL_reg xMathModule_methods[] =
{"matrix_rotation_y", xMath_matrix_rotation_y},
{"matrix_rotation_z", xMath_matrix_rotation_z},
{"matrix_translation", xMath_matrix_translation},
{"matrix4_compose", xMath_matrix4_compose},
{"matrix4_scale", xMath_matrix4_scale},
//* Utility
{"clamp", xMath_clamp},
{0, 0}
};

Expand Down