Added GEO_BONE geolayout command

This commit is contained in:
thecozies
2021-09-20 10:06:33 -05:00
parent c54952e9fc
commit 808106ae2f
6 changed files with 152 additions and 1 deletions

View File

@@ -429,4 +429,22 @@
#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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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
*/

View File

@@ -5,6 +5,7 @@
#include <PR/gbi.h>
#include "types.h"
#include "geo_commands.h"
#include "game/memory.h"
#define GRAPH_RENDER_ACTIVE (1 << 0)
@@ -34,6 +35,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
@@ -242,6 +244,14 @@ 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
@@ -390,6 +400,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,

View File

@@ -598,6 +598,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.
@@ -1021,6 +1085,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;