From a648505f6b89903634a0a09b9a832a1543c7819b Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Mon, 20 Sep 2021 16:40:02 +0100 Subject: [PATCH 1/2] Geo bones --- include/geo_commands.h | 19 ++++++++++ src/engine/geo_layout.c | 33 +++++++++++++++- src/engine/geo_layout.h | 1 + src/engine/graph_node.c | 22 +++++++++++ src/engine/graph_node.h | 13 +++++++ src/game/rendering_graph_node.c | 67 +++++++++++++++++++++++++++++++++ 6 files changed, 154 insertions(+), 1 deletion(-) diff --git a/include/geo_commands.h b/include/geo_commands.h index 432ec1fd..4e8d7f54 100644 --- a/include/geo_commands.h +++ b/include/geo_commands.h @@ -429,4 +429,23 @@ #define GEO_CULLING_RADIUS(cullingRadius) \ CMD_BBH(0x20, 0x00, cullingRadius) +#define GEO_BONE_ID 0xFF + +/** + * 0x21: Create a scene graph node that is rotated by the object's animation + an initial rotation. + * u8 drawingLayer + * s16 xTranslation + * s16 yTranslation + * s16 zTranslation + * s16 xRotation + * s16 yRotation + * s16 zRotation + * u32 displayList: dislay list segmented address + */ +#define GEO_BONE(layer, tx, ty, tz, rx, ry, rz, displayList) \ + CMD_BBH(GEO_BONE_ID, layer, 0x0000), \ + CMD_HHHHHH(tx, ty, tz, rx, ry, rz), \ + CMD_PTR(displayList) + + #endif // GEO_COMMANDS_H diff --git a/src/engine/geo_layout.c b/src/engine/geo_layout.c index 4e88fa30..c97081c3 100644 --- a/src/engine/geo_layout.c +++ b/src/engine/geo_layout.c @@ -767,6 +767,30 @@ void geo_layout_cmd_node_culling_radius(void) { gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT; } +/* + Create a scene graph node that is rotated by the object's animation + an initial rotation. +*/ +void geo_layout_cmd_bone(void) { + struct GraphNodeBone *graphNode; + Vec3s translation; + Vec3s rotation; + s32 drawingLayer = cur_geo_cmd_u8(0x01); + void *displayList; + s16 *cmdPos = (s16 *) gGeoLayoutCommand; + + cmdPos = read_vec3s(translation, &cmdPos[2]); + cmdPos = read_vec3s(rotation, &cmdPos[0]); + displayList = *(void **) &cmdPos[0]; + cmdPos += 2 << CMD_SIZE_SHIFT; + + graphNode = + init_graph_node_bone(gGraphNodePool, NULL, drawingLayer, displayList, translation, rotation); + + register_scene_graph_node(&graphNode->node); + + gGeoLayoutCommand = (u8 *) cmdPos; +} + struct GraphNode *process_geo_layout(struct AllocOnlyPool *pool, void *segptr) { // set by register_scene_graph_node when gCurGraphNodeIndex is 0 // and gCurRootGraphNode is NULL @@ -788,7 +812,14 @@ struct GraphNode *process_geo_layout(struct AllocOnlyPool *pool, void *segptr) { gGeoLayoutStack[1] = 0; while (gGeoLayoutCommand != NULL) { - GeoLayoutJumpTable[gGeoLayoutCommand[0x00]](); + // Custom geo commands can be a part of the switch-case, otherwise use GeoLayoutJumpTable + switch (gGeoLayoutCommand[0x00]) { + case GEO_BONE_ID: + geo_layout_cmd_bone(); + break; + default: + GeoLayoutJumpTable[gGeoLayoutCommand[0x00]](); + } } return gCurRootGraphNode; diff --git a/src/engine/geo_layout.h b/src/engine/geo_layout.h index 6211e141..a0818c61 100644 --- a/src/engine/geo_layout.h +++ b/src/engine/geo_layout.h @@ -81,6 +81,7 @@ void geo_layout_cmd_nop(void); void geo_layout_cmd_copy_view(void); void geo_layout_cmd_node_held_obj(void); void geo_layout_cmd_node_culling_radius(void); +void geo_layout_cmd_bone(void); struct GraphNode *process_geo_layout(struct AllocOnlyPool *a0, void *segptr); diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index e22ddcd0..a9889e9a 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -365,6 +365,28 @@ struct GraphNodeAnimatedPart *init_graph_node_animated_part(struct AllocOnlyPool return graphNode; } +/** + * Allocates and returns a newly created bone node with initial rotation/translation + */ +struct GraphNodeBone *init_graph_node_bone(struct AllocOnlyPool *pool, + struct GraphNodeBone *graphNode, + s32 drawingLayer, void *displayList, + Vec3s translation, Vec3s rotation) { + if (pool != NULL) { + graphNode = alloc_only_pool_alloc(pool, sizeof(struct GraphNodeBone)); + } + + if (graphNode != NULL) { + init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_BONE); + vec3s_copy(graphNode->translation, translation); + vec3s_copy(graphNode->rotation, rotation); + graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); + graphNode->displayList = displayList; + } + + return graphNode; +} + /** * Allocates and returns a newly created billboard node */ diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index eef94c46..d9e3c4ad 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -6,6 +6,7 @@ #include "types.h" #include "sm64.h" +#include "geo_commands.h" #include "game/memory.h" #define UCODE_DEFAULT 0 @@ -35,6 +36,7 @@ #define GRAPH_NODE_TYPE_ROTATION 0x017 #define GRAPH_NODE_TYPE_OBJECT 0x018 #define GRAPH_NODE_TYPE_ANIMATED_PART 0x019 +#define GRAPH_NODE_TYPE_BONE GEO_BONE_ID #define GRAPH_NODE_TYPE_BILLBOARD 0x01A #define GRAPH_NODE_TYPE_DISPLAY_LIST 0x01B #define GRAPH_NODE_TYPE_SCALE 0x01C @@ -243,6 +245,15 @@ struct GraphNodeAnimatedPart /*0x18*/ Vec3s translation; }; +struct GraphNodeBone +{ + struct GraphNode node; + void *displayList; + Vec3s translation; + Vec3s rotation; +}; + + /** A GraphNode that draws a display list rotated in a way to always face the * camera. Note that if the entire object is a billboard (like a coin or 1-up) * then it simply sets the billboard flag for the entire object, this node is @@ -391,6 +402,8 @@ struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool, struc struct GraphNodeCullingRadius *init_graph_node_culling_radius(struct AllocOnlyPool *pool, struct GraphNodeCullingRadius *graphNode, s16 radius); struct GraphNodeAnimatedPart *init_graph_node_animated_part(struct AllocOnlyPool *pool, struct GraphNodeAnimatedPart *graphNode, s32 drawingLayer, void *displayList, Vec3s translation); +struct GraphNodeBone *init_graph_node_bone(struct AllocOnlyPool *pool, struct GraphNodeBone *graphNode, + s32 drawingLayer, void *displayList, Vec3s translation, Vec3s rotation); struct GraphNodeBillboard *init_graph_node_billboard(struct AllocOnlyPool *pool, struct GraphNodeBillboard *graphNode, s32 drawingLayer, void *displayList, Vec3s translation); struct GraphNodeDisplayList *init_graph_node_display_list(struct AllocOnlyPool *pool, struct GraphNodeDisplayList *graphNode, diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 5c8232eb..30f7eabb 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -803,6 +803,70 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) { gMatStackIndex--; } +/** + * Render an animated part that has an initial rotation value + */ +static void geo_process_bone(struct GraphNodeBone *node) { + Mat4 matrix; + Vec3s rotation; + Vec3f translation; + Mtx *matrixPtr = alloc_display_list(sizeof(*matrixPtr)); + + vec3s_copy(rotation, node->rotation); + vec3f_set(translation, node->translation[0], node->translation[1], node->translation[2]); + if (gCurAnimType == ANIM_TYPE_TRANSLATION) { + translation[0] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)] + * gCurAnimTranslationMultiplier; + translation[1] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)] + * gCurAnimTranslationMultiplier; + translation[2] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)] + * gCurAnimTranslationMultiplier; + gCurAnimType = ANIM_TYPE_ROTATION; + } else { + if (gCurAnimType == ANIM_TYPE_LATERAL_TRANSLATION) { + translation[0] += + gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)] + * gCurAnimTranslationMultiplier; + gCurrAnimAttribute += 2; + translation[2] += + gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)] + * gCurAnimTranslationMultiplier; + gCurAnimType = ANIM_TYPE_ROTATION; + } else { + if (gCurAnimType == ANIM_TYPE_VERTICAL_TRANSLATION) { + gCurrAnimAttribute += 2; + translation[1] += + gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)] + * gCurAnimTranslationMultiplier; + gCurrAnimAttribute += 2; + gCurAnimType = ANIM_TYPE_ROTATION; + } else if (gCurAnimType == ANIM_TYPE_NO_TRANSLATION) { + gCurrAnimAttribute += 6; + gCurAnimType = ANIM_TYPE_ROTATION; + } + } + } + + if (gCurAnimType == ANIM_TYPE_ROTATION) { + rotation[0] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]; + rotation[1] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]; + rotation[2] += gCurAnimData[retrieve_animation_index(gCurrAnimFrame, &gCurrAnimAttribute)]; + } + + mtxf_rotate_xyz_and_translate(matrix, translation, rotation); + mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]); + gMatStackIndex++; + mtxf_to_mtx(matrixPtr, gMatStack[gMatStackIndex]); + gMatStackFixed[gMatStackIndex] = matrixPtr; + if (node->displayList != NULL) { + geo_append_display_list(node->displayList, node->node.flags >> 8); + } + if (node->node.children != NULL) { + geo_process_node_and_siblings(node->node.children); + } + gMatStackIndex--; +} + /** * Initialize the animation-related global variables for the currently drawn * object's animation. @@ -1256,6 +1320,9 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) { case GRAPH_NODE_TYPE_HELD_OBJ: geo_process_held_object((struct GraphNodeHeldObject *) curGraphNode); break; + case GRAPH_NODE_TYPE_BONE: + geo_process_bone((struct GraphNodeBone *) curGraphNode); + break; default: geo_try_process_children((struct GraphNode *) curGraphNode); break; From fcc73fde9f3f9c96d8be88115a0b0b4cfd8fbba2 Mon Sep 17 00:00:00 2001 From: Arceveti <73617174+Arceveti@users.noreply.github.com> Date: Mon, 20 Sep 2021 12:10:14 -0700 Subject: [PATCH 2/2] Fix typo --- actors/group0_geo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actors/group0_geo.c b/actors/group0_geo.c index b92f5066..e2451f0d 100644 --- a/actors/group0_geo.c +++ b/actors/group0_geo.c @@ -28,7 +28,7 @@ #define LAYER_OPAQUE LAYER_OPAQUE_ORIG #define LAYER_ALPHA LAYER_ALPHA_ORIG #undef LAYER_OPAQUE_ORIG -#undef LAYER_ALPHA_OGIG +#undef LAYER_ALPHA_ORIG #else #include "mario/geo.inc.c" #endif