From a3b0041b5ae1e629109b7df48e3d649345ccc855 Mon Sep 17 00:00:00 2001 From: rPhase Date: Sat, 4 Jul 2026 15:43:13 -0700 Subject: [PATCH] Remove camera transforms from animPartsMtx Added a helper function to remove camera transforms from model-view matrix to get a world-space matrix. Store world-space mario part matrices instead of model-view in `animPartsMtx`. This is for consistency with `animPartsPos` coordinate space. --- autogen/lua_definitions/functions.lua | 8 +++++++ docs/lua/functions-4.md | 25 ++++++++++++++++++++++ docs/lua/functions.md | 1 + src/engine/math_util.c | 13 ++++++++++++ src/engine/math_util.h | 4 ++++ src/game/rendering_graph_node.c | 14 +++++++++++-- src/pc/lua/smlua_functions_autogen.c | 30 +++++++++++++++++++++++++++ 7 files changed, 93 insertions(+), 2 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 21a0e2888..9123e4015 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -7082,6 +7082,14 @@ function get_pos_from_transform_mtx(dest, objMtx, camMtx) -- ... end +--- @param dest Mat4 +--- @param objMtx Mat4 +--- @param camMtx Mat4 +--- Strip the camera-view matrix `camMtx` off of a model-view matrix `objMtx` and store the resulting matrix in `dest`. This can be used to get the object's transforms in world space. +function get_world_mtx_from_transform(dest, objMtx, camMtx) + -- ... +end + --- @param value number --- @param replacement number --- @return number diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index 114faf99d..11bef099b 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -5634,6 +5634,31 @@ Extracts the position (translation component) from the transformation matrix `ob
+## [get_world_mtx_from_transform](#get_world_mtx_from_transform) + +### Description +Strip the camera-view matrix `camMtx` off of a model-view matrix `objMtx` and store the resulting matrix in `dest`. This can be used to get the object's transforms in world space. + +### Lua Example +`get_world_mtx_from_transform(dest, objMtx, camMtx)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dest | [Mat4](structs.md#Mat4) | +| objMtx | [Mat4](structs.md#Mat4) | +| camMtx | [Mat4](structs.md#Mat4) | + +### Returns +- None + +### C Prototype +`void get_world_mtx_from_transform(VEC_OUT Mat4 dest, Mat4 objMtx, Mat4 camMtx);` + +[:arrow_up_small:](#) + +
+ --- # functions from math_util.inl diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 0c8e1ceb9..35ac3c04e 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1261,6 +1261,7 @@ - [mtxf_inverse](functions-4.md#mtxf_inverse) - [mtxf_inverse_non_affine](functions-4.md#mtxf_inverse_non_affine) - [get_pos_from_transform_mtx](functions-4.md#get_pos_from_transform_mtx) + - [get_world_mtx_from_transform](functions-4.md#get_world_mtx_from_transform)
diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 04c4ad3d6..a04382331 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -883,3 +883,16 @@ OPTIMIZE_O3 Vec3fp get_pos_from_transform_mtx(VEC_OUT Vec3f dest, Mat4 objMtx, M return dest; } +/** + * Extract world-space transformations given an object's model-view matrix and a + * camera matrix. A model-view matrix generated during rendering is a combination + * of world-space and camera transforms to position and orient objects in a scene + * relative to the camera view. By multiplying this matrix with the inverse of the + * camera matrix, the camera transforms can be removed to get the position and + * orientation of an object relative to world-space. + */ +OPTIMIZE_O3 void get_world_mtx_from_transform(VEC_OUT Mat4 dest, Mat4 objMtx, Mat4 camMtx) { + Mat4 invCamMtx; + mtxf_inverse(invCamMtx, camMtx); + mtxf_mul(dest, objMtx, invCamMtx); +} \ No newline at end of file diff --git a/src/engine/math_util.h b/src/engine/math_util.h index 888a64adf..31adca783 100644 --- a/src/engine/math_util.h +++ b/src/engine/math_util.h @@ -291,5 +291,9 @@ Extracts the position (translation component) from the transformation matrix `ob |descriptionEnd| */ OPTIMIZE_O3 Vec3fp get_pos_from_transform_mtx(VEC_OUT Vec3f dest, Mat4 objMtx, Mat4 camMtx); +/* |description| +Strip the camera-view matrix `camMtx` off of a model-view matrix `objMtx` and store the resulting matrix in `dest`. This can be used to get the object's transforms in world space. +|descriptionEnd| */ +OPTIMIZE_O3 void get_world_mtx_from_transform(VEC_OUT Mat4 dest, Mat4 objMtx, Mat4 camMtx); #endif // MATH_UTIL_H diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 50d0b87fc..8f4394657 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -1213,7 +1213,12 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) { Vec3s rot = { rotation[2], rotation[0], rotation[1] }; vec3s_copy(gCurMarioBodyState->animPartsRot[gCurMarioBodyState->currAnimPart], rot); - mtxf_copy(gCurMarioBodyState->animPartsMtx[gCurMarioBodyState->currAnimPart], gMatStack[gMatStackIndex]); + + get_world_mtx_from_transform( + gCurMarioBodyState->animPartsMtx[gCurMarioBodyState->currAnimPart], + gMatStack[gMatStackIndex], + *gCurGraphNodeCamera->matrixPtr + ); } if (gCurGraphNodeMarioState != NULL) { @@ -1872,7 +1877,12 @@ static void geo_process_bone(struct GraphNodeBone *node) { Vec3s rot = { rotation[2], rotation[0], rotation[1] }; vec3s_copy(gCurMarioBodyState->animPartsRot[gCurMarioBodyState->currAnimPart], rot); - mtxf_copy(gCurMarioBodyState->animPartsMtx[gCurMarioBodyState->currAnimPart], gMatStack[gMatStackIndex]); + + get_world_mtx_from_transform( + gCurMarioBodyState->animPartsMtx[gCurMarioBodyState->currAnimPart], + gMatStack[gMatStackIndex], + *gCurGraphNodeCamera->matrixPtr + ); } if (gCurGraphNodeMarioState != NULL) { diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 91917e2f7..b60c934aa 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -20321,6 +20321,35 @@ int smlua_func_get_pos_from_transform_mtx(lua_State* L) { return 1; } +int smlua_func_get_world_mtx_from_transform(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_world_mtx_from_transform", 3, top); + return 0; + } + + + Mat4 dest; + smlua_get_mat4(dest, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_world_mtx_from_transform"); return 0; } + + Mat4 objMtx; + smlua_get_mat4(objMtx, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "get_world_mtx_from_transform"); return 0; } + + Mat4 camMtx; + smlua_get_mat4(camMtx, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "get_world_mtx_from_transform"); return 0; } + + get_world_mtx_from_transform(dest, objMtx, camMtx); + + smlua_push_mat4(dest, 1); + + return 1; +} + /////////////////// // math_util.inl // /////////////////// @@ -38418,6 +38447,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "mtxf_inverse", smlua_func_mtxf_inverse); smlua_bind_function(L, "mtxf_inverse_non_affine", smlua_func_mtxf_inverse_non_affine); smlua_bind_function(L, "get_pos_from_transform_mtx", smlua_func_get_pos_from_transform_mtx); + smlua_bind_function(L, "get_world_mtx_from_transform", smlua_func_get_world_mtx_from_transform); // math_util.inl smlua_bind_function(L, "replace_value_if_not_zero", smlua_func_replace_value_if_not_zero);