Reformat to something more readable for me :3
Build libsm64 / Build libsm64 for linux (push) Failing after 28s
Build libsm64 / Build libsm64 for web (push) Failing after 29s
Build libsm64 / Build libsm64 for windows (push) Failing after 23s

This commit is contained in:
2026-05-24 11:31:35 -05:00
parent 4328104536
commit 9ff6947911
141 changed files with 29706 additions and 20450 deletions
+165 -115
View File
@@ -6,7 +6,7 @@
#include "graph_node.h"
#include "../shim.h"
static Vec3s gVec3sZero = { 0, 0, 0 };
static Vec3s gVec3sZero = {0, 0, 0};
typedef void (*GeoLayoutCommandProc)(void);
@@ -102,53 +102,60 @@ UNUSED s16 D_8038BD7C;
s16 gGeoLayoutReturnIndex; // similar to RA register in MIPS
u8 *gGeoLayoutCommand;
u32 unused_8038B894[3] = { 0 };
u32 unused_8038B894[3] = {0};
/*
0x00: Branch and store return address
cmd+0x04: void *branchTarget
*/
void geo_layout_cmd_branch_and_link(void) {
gGeoLayoutStack[gGeoLayoutStackIndex++] = (uintptr_t) (gGeoLayoutCommand + CMD_PROCESS_OFFSET(8));
void geo_layout_cmd_branch_and_link(void)
{
gGeoLayoutStack[gGeoLayoutStackIndex++] = (uintptr_t)(gGeoLayoutCommand + CMD_PROCESS_OFFSET(8));
gGeoLayoutStack[gGeoLayoutStackIndex++] = (gCurGraphNodeIndex << 16) + gGeoLayoutReturnIndex;
gGeoLayoutReturnIndex = gGeoLayoutStackIndex;
gGeoLayoutCommand = segmented_to_virtual(cur_geo_cmd_ptr(0x04));
}
// 0x01: Terminate geo layout
void geo_layout_cmd_end(void) {
void geo_layout_cmd_end(void)
{
gGeoLayoutStackIndex = gGeoLayoutReturnIndex;
gGeoLayoutReturnIndex = gGeoLayoutStack[--gGeoLayoutStackIndex] & 0xFFFF;
gCurGraphNodeIndex = gGeoLayoutStack[gGeoLayoutStackIndex] >> 16;
gGeoLayoutCommand = (u8 *) gGeoLayoutStack[--gGeoLayoutStackIndex];
gGeoLayoutCommand = (u8 *)gGeoLayoutStack[--gGeoLayoutStackIndex];
}
/*
0x02: Branch
cmd+0x04: void *branchTarget
*/
void geo_layout_cmd_branch(void) {
if (cur_geo_cmd_u8(0x01) == 1) {
gGeoLayoutStack[gGeoLayoutStackIndex++] = (uintptr_t) (gGeoLayoutCommand + CMD_PROCESS_OFFSET(8));
void geo_layout_cmd_branch(void)
{
if (cur_geo_cmd_u8(0x01) == 1)
{
gGeoLayoutStack[gGeoLayoutStackIndex++] = (uintptr_t)(gGeoLayoutCommand + CMD_PROCESS_OFFSET(8));
}
gGeoLayoutCommand = segmented_to_virtual(cur_geo_cmd_ptr(0x04));
}
// 0x03: Return from branch
void geo_layout_cmd_return(void) {
gGeoLayoutCommand = (u8 *) gGeoLayoutStack[--gGeoLayoutStackIndex];
void geo_layout_cmd_return(void)
{
gGeoLayoutCommand = (u8 *)gGeoLayoutStack[--gGeoLayoutStackIndex];
}
// 0x04: Open node
void geo_layout_cmd_open_node(void) {
void geo_layout_cmd_open_node(void)
{
gCurGraphNodeList[gCurGraphNodeIndex + 1] = gCurGraphNodeList[gCurGraphNodeIndex];
gCurGraphNodeIndex++;
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
}
// 0x05: Close node
void geo_layout_cmd_close_node(void) {
void geo_layout_cmd_close_node(void)
{
gCurGraphNodeIndex--;
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
}
@@ -159,10 +166,12 @@ void geo_layout_cmd_close_node(void) {
Register the current node in the gGeoViews array at the given index
*/
void geo_layout_cmd_assign_as_view(void) {
void geo_layout_cmd_assign_as_view(void)
{
u16 index = cur_geo_cmd_s16(0x02);
if (index < gGeoNumViews) {
if (index < gGeoNumViews)
{
gGeoViews[index] = gCurGraphNodeList[gCurGraphNodeIndex];
}
@@ -174,11 +183,13 @@ void geo_layout_cmd_assign_as_view(void) {
cmd+0x01: u8 operation (0 = reset, 1 = set, 2 = clear)
cmd+0x02: s16 bits
*/
void geo_layout_cmd_update_node_flags(void) {
void geo_layout_cmd_update_node_flags(void)
{
u16 operation = cur_geo_cmd_u8(0x01);
u16 flagBits = cur_geo_cmd_s16(0x02);
switch (operation) {
switch (operation)
{
case GEO_CMD_FLAGS_RESET:
gCurGraphNodeList[gCurGraphNodeIndex]->flags = flagBits;
break;
@@ -201,7 +212,8 @@ void geo_layout_cmd_update_node_flags(void) {
cmd+0x08: s16 width
cmd+0x0A: s16 height
*/
void geo_layout_cmd_node_root(void) {
void geo_layout_cmd_node_root(void)
{
s32 i;
struct GraphNodeRoot *graphNode;
@@ -215,16 +227,17 @@ void geo_layout_cmd_node_root(void) {
// cmd+0x02 = 0x00: Mario face, 0x0A: all other levels
gGeoNumViews = cur_geo_cmd_s16(0x02) + 2;
graphNode = init_graph_node_root(gGraphNodePool, NULL, 0, x, y, width, height);
graphNode = init_graph_node_root(gGraphNodePool, nullptr, 0, x, y, width, height);
// gGeoViews is unused in libsm64
gGeoViews = NULL; // alloc_only_pool_alloc(gGraphNodePool, gGeoNumViews * sizeof(struct GraphNode *));
gGeoViews = nullptr; // alloc_only_pool_alloc(gGraphNodePool, gGeoNumViews * sizeof(struct GraphNode *));
graphNode->views = gGeoViews;
graphNode->numViews = gGeoNumViews;
for (i = 0; i < gGeoNumViews; i++) {
gGeoViews[i] = NULL;
for (i = 0; i < gGeoNumViews; i++)
{
gGeoViews[i] = nullptr;
}
register_scene_graph_node(&graphNode->node);
@@ -236,11 +249,12 @@ void geo_layout_cmd_node_root(void) {
0x09: Create orthographic projection scene graph node
cmd+0x02: s16 scale as a percentage (usually it's 100)
*/
void geo_layout_cmd_node_ortho_projection(void) {
void geo_layout_cmd_node_ortho_projection(void)
{
struct GraphNodeOrthoProjection *graphNode;
f32 scale = (f32) cur_geo_cmd_s16(0x02) / 100.0f;
f32 scale = (f32)cur_geo_cmd_s16(0x02) / 100.0f;
graphNode = init_graph_node_ortho_projection(gGraphNodePool, NULL, scale);
graphNode = init_graph_node_ortho_projection(gGraphNodePool, nullptr, scale);
register_scene_graph_node(&graphNode->node);
@@ -255,20 +269,22 @@ void geo_layout_cmd_node_ortho_projection(void) {
cmd+0x06: s16 far
[cmd+0x08: GraphNodeFunc frustumFunc]
*/
void geo_layout_cmd_node_perspective(void) {
void geo_layout_cmd_node_perspective(void)
{
struct GraphNodePerspective *graphNode;
GraphNodeFunc frustumFunc = NULL;
GraphNodeFunc frustumFunc = nullptr;
s16 fov = cur_geo_cmd_s16(0x02);
s16 near = cur_geo_cmd_s16(0x04);
s16 far = cur_geo_cmd_s16(0x06);
if (cur_geo_cmd_u8(0x01) != 0) {
if (cur_geo_cmd_u8(0x01) != 0)
{
// optional asm function
frustumFunc = (GraphNodeFunc) cur_geo_cmd_ptr(0x08);
frustumFunc = (GraphNodeFunc)cur_geo_cmd_ptr(0x08);
gGeoLayoutCommand += 4 << CMD_SIZE_SHIFT;
}
graphNode = init_graph_node_perspective(gGraphNodePool, NULL, (f32) fov, near, far, frustumFunc, 0);
graphNode = init_graph_node_perspective(gGraphNodePool, nullptr, (f32)fov, near, far, frustumFunc, 0);
register_scene_graph_node(&graphNode->fnNode.node);
@@ -279,10 +295,11 @@ void geo_layout_cmd_node_perspective(void) {
0x0B: Create a scene graph node that groups other nodes without any
additional functionality
*/
void geo_layout_cmd_node_start(void) {
void geo_layout_cmd_node_start(void)
{
struct GraphNodeStart *graphNode;
graphNode = init_graph_node_start(gGraphNodePool, NULL);
graphNode = init_graph_node_start(gGraphNodePool, nullptr);
register_scene_graph_node(&graphNode->node);
@@ -290,7 +307,8 @@ void geo_layout_cmd_node_start(void) {
}
// 0x1F: No operation
void geo_layout_cmd_nop3(void) {
void geo_layout_cmd_nop3(void)
{
gGeoLayoutCommand += 0x10 << CMD_SIZE_SHIFT;
}
@@ -298,10 +316,11 @@ void geo_layout_cmd_nop3(void) {
0x0C: Create zbuffer-toggling scene graph node
cmd+0x01: u8 enableZBuffer (1 = on, 0 = off)
*/
void geo_layout_cmd_node_master_list(void) {
void geo_layout_cmd_node_master_list(void)
{
struct GraphNodeMasterList *graphNode;
graphNode = init_graph_node_master_list(gGraphNodePool, NULL, cur_geo_cmd_u8(0x01));
graphNode = init_graph_node_master_list(gGraphNodePool, nullptr, cur_geo_cmd_u8(0x01));
register_scene_graph_node(&graphNode->node);
@@ -314,12 +333,13 @@ void geo_layout_cmd_node_master_list(void) {
cmd+0x04: s16 minDistance
cmd+0x06: s16 maxDistance
*/
void geo_layout_cmd_node_level_of_detail(void) {
void geo_layout_cmd_node_level_of_detail(void)
{
struct GraphNodeLevelOfDetail *graphNode;
s16 minDistance = cur_geo_cmd_s16(0x04);
s16 maxDistance = cur_geo_cmd_s16(0x06);
graphNode = init_graph_node_render_range(gGraphNodePool, NULL, minDistance, maxDistance);
graphNode = init_graph_node_render_range(gGraphNodePool, nullptr, minDistance, maxDistance);
register_scene_graph_node(&graphNode->node);
@@ -334,15 +354,16 @@ void geo_layout_cmd_node_level_of_detail(void) {
caseSelectorFunc returns an index which is used to select the child node to render.
Used for animating coins, blinking, color selection, etc.
*/
void geo_layout_cmd_node_switch_case(void) {
void geo_layout_cmd_node_switch_case(void)
{
struct GraphNodeSwitchCase *graphNode;
graphNode =
init_graph_node_switch_case(gGraphNodePool, NULL,
cur_geo_cmd_s16(0x02), // case which is initially selected
0,
(GraphNodeFunc) cur_geo_cmd_ptr(0x04), // case update function
0);
init_graph_node_switch_case(gGraphNodePool, nullptr,
cur_geo_cmd_s16(0x02), // case which is initially selected
0,
(GraphNodeFunc)cur_geo_cmd_ptr(0x04), // case update function
0);
register_scene_graph_node(&graphNode->fnNode.node);
@@ -360,17 +381,18 @@ void geo_layout_cmd_node_switch_case(void) {
cmd+0x0E: s16 focusZ
cmd+0x10: GraphNodeFunc func
*/
void geo_layout_cmd_node_camera(void) {
void geo_layout_cmd_node_camera(void)
{
struct GraphNodeCamera *graphNode;
s16 *cmdPos = (s16 *) &gGeoLayoutCommand[4];
s16 *cmdPos = (s16 *)&gGeoLayoutCommand[4];
Vec3f pos, focus;
cmdPos = read_vec3s_to_vec3f(pos, cmdPos);
cmdPos = read_vec3s_to_vec3f(focus, cmdPos);
graphNode = init_graph_node_camera(gGraphNodePool, NULL, pos, focus,
(GraphNodeFunc) cur_geo_cmd_ptr(0x10), cur_geo_cmd_s16(0x02));
graphNode = init_graph_node_camera(gGraphNodePool, nullptr, pos, focus,
(GraphNodeFunc)cur_geo_cmd_ptr(0x10), cur_geo_cmd_s16(0x02));
register_scene_graph_node(&graphNode->fnNode.node);
@@ -413,18 +435,20 @@ void geo_layout_cmd_node_camera(void) {
[cmd+var: void *displayList]
*/
void geo_layout_cmd_node_translation_rotation(void) {
void geo_layout_cmd_node_translation_rotation(void)
{
struct GraphNodeTranslationRotation *graphNode;
Vec3s translation, rotation;
void *displayList = NULL;
void *displayList = nullptr;
s16 drawingLayer = 0;
s16 params = cur_geo_cmd_u8(0x01);
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
s16 *cmdPos = (s16 *)gGeoLayoutCommand;
switch ((params & 0x70) >> 4) {
switch ((params & 0x70) >> 4)
{
case 0:
cmdPos = read_vec3s(translation, &cmdPos[2]);
cmdPos = read_vec3s_angle(rotation, cmdPos);
@@ -444,17 +468,18 @@ void geo_layout_cmd_node_translation_rotation(void) {
break;
}
if (params & 0x80) {
displayList = *(void **) &cmdPos[0];
if (params & 0x80)
{
displayList = *(void **)&cmdPos[0];
drawingLayer = params & 0x0F;
cmdPos += 2 << CMD_SIZE_SHIFT;
}
graphNode = init_graph_node_translation_rotation(gGraphNodePool, NULL, drawingLayer, displayList,
graphNode = init_graph_node_translation_rotation(gGraphNodePool, nullptr, drawingLayer, displayList,
translation, rotation);
register_scene_graph_node(&graphNode->node);
gGeoLayoutCommand = (u8 *) cmdPos;
gGeoLayoutCommand = (u8 *)cmdPos;
}
/*
@@ -467,30 +492,32 @@ void geo_layout_cmd_node_translation_rotation(void) {
cmd+0x06: s16 zTranslation
[cmd+0x08: void *displayList]
*/
void geo_layout_cmd_node_translation(void) {
void geo_layout_cmd_node_translation(void)
{
struct GraphNodeTranslation *graphNode;
Vec3s translation;
s16 drawingLayer = 0;
s16 params = cur_geo_cmd_u8(0x01);
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
void *displayList = NULL;
s16 *cmdPos = (s16 *)gGeoLayoutCommand;
void *displayList = nullptr;
cmdPos = read_vec3s(translation, &cmdPos[1]);
if (params & 0x80) {
displayList = *(void **) &cmdPos[0];
if (params & 0x80)
{
displayList = *(void **)&cmdPos[0];
drawingLayer = params & 0x0F;
cmdPos += 2 << CMD_SIZE_SHIFT;
}
graphNode =
init_graph_node_translation(gGraphNodePool, NULL, drawingLayer, displayList, translation);
init_graph_node_translation(gGraphNodePool, nullptr, drawingLayer, displayList, translation);
register_scene_graph_node(&graphNode->node);
gGeoLayoutCommand = (u8 *) cmdPos;
gGeoLayoutCommand = (u8 *)cmdPos;
}
/*
@@ -503,29 +530,31 @@ void geo_layout_cmd_node_translation(void) {
cmd+0x06: s16 unkZ
[cmd+0x08: void *displayList]
*/
void geo_layout_cmd_node_rotation(void) {
void geo_layout_cmd_node_rotation(void)
{
struct GraphNodeRotation *graphNode;
Vec3s sp2c;
s16 drawingLayer = 0;
s16 params = cur_geo_cmd_u8(0x01);
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
void *displayList = NULL;
s16 *cmdPos = (s16 *)gGeoLayoutCommand;
void *displayList = nullptr;
cmdPos = read_vec3s_angle(sp2c, &cmdPos[1]);
if (params & 0x80) {
displayList = *(void **) &cmdPos[0];
if (params & 0x80)
{
displayList = *(void **)&cmdPos[0];
drawingLayer = params & 0x0F;
cmdPos += 2 << CMD_SIZE_SHIFT;
}
graphNode = init_graph_node_rotation(gGraphNodePool, NULL, drawingLayer, displayList, sp2c);
graphNode = init_graph_node_rotation(gGraphNodePool, nullptr, drawingLayer, displayList, sp2c);
register_scene_graph_node(&graphNode->node);
gGeoLayoutCommand = (u8 *) cmdPos;
gGeoLayoutCommand = (u8 *)cmdPos;
}
/*
@@ -536,21 +565,23 @@ void geo_layout_cmd_node_rotation(void) {
cmd+0x04: u32 scale (0x10000 = 1.0)
[cmd+0x08: void *displayList]
*/
void geo_layout_cmd_node_scale(void) {
void geo_layout_cmd_node_scale(void)
{
struct GraphNodeScale *graphNode;
s16 drawingLayer = 0;
s16 params = cur_geo_cmd_u8(0x01);
f32 scale = cur_geo_cmd_u32(0x04) / 65536.0f;
void *displayList = NULL;
void *displayList = nullptr;
if (params & 0x80) {
if (params & 0x80)
{
displayList = cur_geo_cmd_ptr(0x08);
drawingLayer = params & 0x0F;
gGeoLayoutCommand += 4 << CMD_SIZE_SHIFT;
}
graphNode = init_graph_node_scale(gGraphNodePool, NULL, drawingLayer, displayList, scale);
graphNode = init_graph_node_scale(gGraphNodePool, nullptr, drawingLayer, displayList, scale);
register_scene_graph_node(&graphNode->node);
@@ -558,7 +589,8 @@ void geo_layout_cmd_node_scale(void) {
}
// 0x1E: No operation
void geo_layout_cmd_nop2(void) {
void geo_layout_cmd_nop2(void)
{
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
}
@@ -570,17 +602,18 @@ void geo_layout_cmd_nop2(void) {
cmd+0x06: s16 zTranslation
cmd+0x08: void *displayList
*/
void geo_layout_cmd_node_animated_part(void) {
void geo_layout_cmd_node_animated_part(void)
{
struct GraphNodeAnimatedPart *graphNode;
Vec3s translation;
s32 drawingLayer = cur_geo_cmd_u8(0x01);
void *displayList = cur_geo_cmd_ptr(0x08);
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
s16 *cmdPos = (s16 *)gGeoLayoutCommand;
read_vec3s(translation, &cmdPos[1]);
graphNode =
init_graph_node_animated_part(gGraphNodePool, NULL, drawingLayer, displayList, translation);
init_graph_node_animated_part(gGraphNodePool, nullptr, drawingLayer, displayList, translation);
register_scene_graph_node(&graphNode->node);
@@ -597,27 +630,29 @@ void geo_layout_cmd_node_animated_part(void) {
cmd+0x06: s16 zTranslation
[cmd+0x08: void *displayList]
*/
void geo_layout_cmd_node_billboard(void) {
void geo_layout_cmd_node_billboard(void)
{
struct GraphNodeBillboard *graphNode;
Vec3s translation;
s16 drawingLayer = 0;
s16 params = cur_geo_cmd_u8(0x01);
s16 *cmdPos = (s16 *) gGeoLayoutCommand;
void *displayList = NULL;
s16 *cmdPos = (s16 *)gGeoLayoutCommand;
void *displayList = nullptr;
cmdPos = read_vec3s(translation, &cmdPos[1]);
if (params & 0x80) {
displayList = *(void **) &cmdPos[0];
if (params & 0x80)
{
displayList = *(void **)&cmdPos[0];
drawingLayer = params & 0x0F;
cmdPos += 2 << CMD_SIZE_SHIFT;
}
graphNode = init_graph_node_billboard(gGraphNodePool, NULL, drawingLayer, displayList, translation);
graphNode = init_graph_node_billboard(gGraphNodePool, nullptr, drawingLayer, displayList, translation);
register_scene_graph_node(&graphNode->node);
gGeoLayoutCommand = (u8 *) cmdPos;
gGeoLayoutCommand = (u8 *)cmdPos;
}
/*
@@ -625,12 +660,13 @@ void geo_layout_cmd_node_billboard(void) {
cmd+0x01: u8 drawingLayer
cmd+0x04: void *displayList
*/
void geo_layout_cmd_node_display_list(void) {
void geo_layout_cmd_node_display_list(void)
{
struct GraphNodeDisplayList *graphNode;
s32 drawingLayer = cur_geo_cmd_u8(0x01);
void *displayList = cur_geo_cmd_ptr(0x04);
graphNode = init_graph_node_display_list(gGraphNodePool, NULL, drawingLayer, displayList);
graphNode = init_graph_node_display_list(gGraphNodePool, nullptr, drawingLayer, displayList);
register_scene_graph_node(&graphNode->node);
@@ -643,13 +679,14 @@ void geo_layout_cmd_node_display_list(void) {
cmd+0x04: s16 shadowSolidity
cmd+0x06: s16 shadowScale
*/
void geo_layout_cmd_node_shadow(void) {
void geo_layout_cmd_node_shadow(void)
{
struct GraphNodeShadow *graphNode;
u8 shadowType = cur_geo_cmd_s16(0x02);
u8 shadowSolidity = cur_geo_cmd_s16(0x04);
s16 shadowScale = cur_geo_cmd_s16(0x06);
graphNode = init_graph_node_shadow(gGraphNodePool, NULL, shadowScale, shadowSolidity, shadowType);
graphNode = init_graph_node_shadow(gGraphNodePool, nullptr, shadowScale, shadowSolidity, shadowType);
register_scene_graph_node(&graphNode->node);
@@ -657,10 +694,11 @@ void geo_layout_cmd_node_shadow(void) {
}
// 0x17: Create scene graph node that manages the group of all object nodes
void geo_layout_cmd_node_object_parent(void) {
void geo_layout_cmd_node_object_parent(void)
{
struct GraphNodeObjectParent *graphNode;
graphNode = init_graph_node_object_parent(gGraphNodePool, NULL, &gObjParentGraphNode);
graphNode = init_graph_node_object_parent(gGraphNodePool, nullptr, &gObjParentGraphNode);
register_scene_graph_node(&graphNode->node);
@@ -672,12 +710,13 @@ void geo_layout_cmd_node_object_parent(void) {
cmd+0x02: s16 parameter
cmd+0x04: GraphNodeFunc func
*/
void geo_layout_cmd_node_generated(void) {
void geo_layout_cmd_node_generated(void)
{
struct GraphNodeGenerated *graphNode;
graphNode = init_graph_node_generated(gGraphNodePool, NULL,
(GraphNodeFunc) cur_geo_cmd_ptr(0x04), // asm function
cur_geo_cmd_s16(0x02)); // parameter
graphNode = init_graph_node_generated(gGraphNodePool, nullptr,
(GraphNodeFunc)cur_geo_cmd_ptr(0x04), // asm function
cur_geo_cmd_s16(0x02)); // parameter
register_scene_graph_node(&graphNode->fnNode.node);
@@ -689,13 +728,14 @@ void geo_layout_cmd_node_generated(void) {
cmd+0x02: s16 background // background ID, or RGBA5551 color if backgroundFunc is null
cmd+0x04: GraphNodeFunc backgroundFunc
*/
void geo_layout_cmd_node_background(void) {
void geo_layout_cmd_node_background(void)
{
struct GraphNodeBackground *graphNode;
graphNode = init_graph_node_background(
gGraphNodePool, NULL,
gGraphNodePool, nullptr,
cur_geo_cmd_s16(0x02), // background ID, or RGBA5551 color if asm function is null
(GraphNodeFunc) cur_geo_cmd_ptr(0x04), // asm function
(GraphNodeFunc)cur_geo_cmd_ptr(0x04), // asm function
0);
register_scene_graph_node(&graphNode->fnNode.node);
@@ -704,7 +744,8 @@ void geo_layout_cmd_node_background(void) {
}
// 0x1A: No operation
void geo_layout_cmd_nop(void) {
void geo_layout_cmd_nop(void)
{
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
}
@@ -713,22 +754,27 @@ void geo_layout_cmd_nop(void) {
to a newly created object parent node.
cmd+0x02: s16 index (of gGeoViews)
*/
void geo_layout_cmd_copy_view(void) {
void geo_layout_cmd_copy_view(void)
{
struct GraphNodeObjectParent *graphNode;
struct GraphNode *node = NULL;
struct GraphNode *node = nullptr;
s16 index = cur_geo_cmd_s16(0x02);
if (index >= 0) {
if (index >= 0)
{
node = gGeoViews[index];
if (node->type == GRAPH_NODE_TYPE_OBJECT_PARENT) {
node = ((struct GraphNodeObjectParent *) node)->sharedChild;
} else {
node = NULL;
if (node->type == GRAPH_NODE_TYPE_OBJECT_PARENT)
{
node = ((struct GraphNodeObjectParent *)node)->sharedChild;
}
else
{
node = nullptr;
}
}
graphNode = init_graph_node_object_parent(gGraphNodePool, NULL, node);
graphNode = init_graph_node_object_parent(gGraphNodePool, nullptr, node);
register_scene_graph_node(&graphNode->node);
@@ -743,14 +789,15 @@ void geo_layout_cmd_copy_view(void) {
cmd+0x06: s16 offsetZ
cmd+0x08: GraphNodeFunc nodeFunc
*/
void geo_layout_cmd_node_held_obj(void) {
void geo_layout_cmd_node_held_obj(void)
{
struct GraphNodeHeldObject *graphNode;
Vec3s offset;
read_vec3s(offset, (s16 *) &gGeoLayoutCommand[0x02]);
read_vec3s(offset, (s16 *)&gGeoLayoutCommand[0x02]);
graphNode = init_graph_node_held_object(
gGraphNodePool, NULL, NULL, offset, (GraphNodeFunc) cur_geo_cmd_ptr(0x08), cur_geo_cmd_u8(0x01));
gGraphNodePool, nullptr, nullptr, offset, (GraphNodeFunc)cur_geo_cmd_ptr(0x08), cur_geo_cmd_u8(0x01));
register_scene_graph_node(&graphNode->fnNode.node);
@@ -762,17 +809,19 @@ void geo_layout_cmd_node_held_obj(void) {
is used for frustum culling.
cmd+0x02: s16 cullingRadius
*/
void geo_layout_cmd_node_culling_radius(void) {
void geo_layout_cmd_node_culling_radius(void)
{
struct GraphNodeCullingRadius *graphNode;
graphNode = init_graph_node_culling_radius(gGraphNodePool, NULL, cur_geo_cmd_s16(0x02));
graphNode = init_graph_node_culling_radius(gGraphNodePool, nullptr, cur_geo_cmd_s16(0x02));
register_scene_graph_node(&graphNode->node);
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
}
struct GraphNode *process_geo_layout(struct AllocOnlyPool *pool, void *segptr) {
struct GraphNode *process_geo_layout(struct AllocOnlyPool *pool, void *segptr)
{
// set by register_scene_graph_node when gCurGraphNodeIndex is 0
// and gCurRootGraphNode is NULL
gCurRootGraphNode = NULL;
// and gCurRootGraphNode is nullptr
gCurRootGraphNode = nullptr;
gGeoNumViews = 0; // number of entries in gGeoViews
@@ -789,7 +838,8 @@ struct GraphNode *process_geo_layout(struct AllocOnlyPool *pool, void *segptr) {
gGeoLayoutStack[0] = 0;
gGeoLayoutStack[1] = 0;
while (gGeoLayoutCommand != NULL) {
while (gGeoLayoutCommand != nullptr)
{
GeoLayoutJumpTable[gGeoLayoutCommand[0x00]]();
}
+32
View File
@@ -49,37 +49,69 @@ extern s16 D_8038BD78;
extern struct GraphNode *D_8038BCF8[];
void geo_layout_cmd_branch_and_link(void);
void geo_layout_cmd_end(void);
void geo_layout_cmd_branch(void);
void geo_layout_cmd_return(void);
void geo_layout_cmd_open_node(void);
void geo_layout_cmd_close_node(void);
void geo_layout_cmd_assign_as_view(void);
void geo_layout_cmd_update_node_flags(void);
void geo_layout_cmd_node_root(void);
void geo_layout_cmd_node_ortho_projection(void);
void geo_layout_cmd_node_perspective(void);
void geo_layout_cmd_node_start(void);
void geo_layout_cmd_nop3(void);
void geo_layout_cmd_node_master_list(void);
void geo_layout_cmd_node_level_of_detail(void);
void geo_layout_cmd_node_switch_case(void);
void geo_layout_cmd_node_camera(void);
void geo_layout_cmd_node_translation_rotation(void);
void geo_layout_cmd_node_translation(void);
void geo_layout_cmd_node_rotation(void);
void geo_layout_cmd_node_scale(void);
void geo_layout_cmd_nop2(void);
void geo_layout_cmd_node_animated_part(void);
void geo_layout_cmd_node_billboard(void);
void geo_layout_cmd_node_display_list(void);
void geo_layout_cmd_node_shadow(void);
void geo_layout_cmd_node_object_parent(void);
void geo_layout_cmd_node_generated(void);
void geo_layout_cmd_node_background(void);
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);
struct GraphNode *process_geo_layout(struct AllocOnlyPool *a0, void *segptr);
File diff suppressed because it is too large Load Diff
+241 -113
View File
@@ -18,7 +18,7 @@
#define GRAPH_NODE_TYPE_FUNCTIONAL 0x100
// Type used for Bowser and an unused geo function in obj_behaviors.c
#define GRAPH_NODE_TYPE_400 0x400
#define GRAPH_NODE_TYPE_400 0x400
// The discriminant for different types of geo nodes
#define GRAPH_NODE_TYPE_ROOT 0x001
@@ -70,23 +70,34 @@ typedef Gfx *(*GraphNodeFunc)(s32 callContext, struct GraphNode *node, void *con
*/
struct FnGraphNode
{
/*0x00*/ struct GraphNode node;
/*0x14*/ GraphNodeFunc func;
/*0x00*/
struct GraphNode node;
/*0x14*/
GraphNodeFunc func;
};
/** The very root of the geo tree. Specifies the viewport.
*/
struct GraphNodeRoot
{
/*0x00*/ struct GraphNode node;
/*0x14*/ u8 areaIndex;
/*0x15*/ s8 unk15; // ?
/*0x16*/ s16 x;
/*0x18*/ s16 y;
/*0x1A*/ s16 width; // half width, 160
/*0x1C*/ s16 height; // half height
/*0x1E*/ s16 numViews; // number of entries in mystery array
/*0x20*/ struct GraphNode **views;
/*0x00*/
struct GraphNode node;
/*0x14*/
u8 areaIndex;
/*0x15*/
s8 unk15; // ?
/*0x16*/
s16 x;
/*0x18*/
s16 y;
/*0x1A*/
s16 width; // half width, 160
/*0x1C*/
s16 height; // half height
/*0x1E*/
s16 numViews; // number of entries in mystery array
/*0x20*/
struct GraphNode **views;
};
/** A node that sets up an orthographic projection based on the global
@@ -94,8 +105,10 @@ struct GraphNodeRoot
*/
struct GraphNodeOrthoProjection
{
/*0x00*/ struct GraphNode node;
/*0x14*/ f32 scale;
/*0x00*/
struct GraphNode node;
/*0x14*/
f32 scale;
};
/** A node that sets up a perspective projection. Used for drawing the
@@ -104,11 +117,16 @@ struct GraphNodeOrthoProjection
*/
struct GraphNodePerspective
{
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ s32 unused;
/*0x1C*/ f32 fov; // horizontal field of view in degrees
/*0x20*/ s16 near; // near clipping plane
/*0x22*/ s16 far; // far clipping plane
/*0x00*/
struct FnGraphNode fnNode;
/*0x18*/
s32 unused;
/*0x1C*/
f32 fov; // horizontal field of view in degrees
/*0x20*/
s16 near; // near clipping plane
/*0x22*/
s16 far; // far clipping plane
};
/** An entry in the master list. It is a linked list of display lists
@@ -128,9 +146,12 @@ struct DisplayListNode
*/
struct GraphNodeMasterList
{
/*0x00*/ struct GraphNode node;
/*0x14*/ struct DisplayListNode *listHeads[GFX_NUM_MASTER_LISTS];
/*0x34*/ struct DisplayListNode *listTails[GFX_NUM_MASTER_LISTS];
/*0x00*/
struct GraphNode node;
/*0x14*/
struct DisplayListNode *listHeads[GFX_NUM_MASTER_LISTS];
/*0x34*/
struct DisplayListNode *listTails[GFX_NUM_MASTER_LISTS];
};
/** Simply used as a parent to group multiple children.
@@ -138,7 +159,8 @@ struct GraphNodeMasterList
*/
struct GraphNodeStart
{
/*0x00*/ struct GraphNode node;
/*0x00*/
struct GraphNode node;
};
/** GraphNode that only renders its children if the current transformation matrix
@@ -149,9 +171,12 @@ struct GraphNodeStart
*/
struct GraphNodeLevelOfDetail
{
/*0x00*/ struct GraphNode node;
/*0x14*/ s16 minDistance;
/*0x16*/ s16 maxDistance;
/*0x00*/
struct GraphNode node;
/*0x14*/
s16 minDistance;
/*0x16*/
s16 maxDistance;
};
/** GraphNode that renders exactly one of its children.
@@ -161,10 +186,14 @@ struct GraphNodeLevelOfDetail
*/
struct GraphNodeSwitchCase
{
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ s32 unused;
/*0x1C*/ s16 numCases;
/*0x1E*/ s16 selectedCase;
/*0x00*/
struct FnGraphNode fnNode;
/*0x18*/
s32 unused;
/*0x1C*/
s16 numCases;
/*0x1E*/
s16 selectedCase;
};
/**
@@ -173,8 +202,12 @@ struct GraphNodeSwitchCase
*/
struct GraphNodeCamera
{
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ union {
/*0x00*/
struct FnGraphNode fnNode;
/*0x18*/
union
{
// When the node is created, a mode is assigned to the node.
// Later in geo_camera_main a Camera is allocated,
// the mode is passed to the struct, and the field is overridden
@@ -182,11 +215,17 @@ struct GraphNodeCamera
s32 mode;
struct Camera *camera;
} config;
/*0x1C*/ Vec3f pos;
/*0x28*/ Vec3f focus;
/*0x34*/ Mat4 *matrixPtr; // pointer to look-at matrix of this camera as a Mat4
/*0x38*/ s16 roll; // roll in look at matrix. Doesn't account for light direction unlike rollScreen.
/*0x3A*/ s16 rollScreen; // rolls screen while keeping the light direction consistent
/*0x1C*/
Vec3f pos;
/*0x28*/
Vec3f focus;
/*0x34*/
Mat4 *matrixPtr; // pointer to look-at matrix of this camera as a Mat4
/*0x38*/
s16 roll; // roll in look at matrix. Doesn't account for light direction unlike rollScreen.
/*0x3A*/
s16 rollScreen; // rolls screen while keeping the light direction consistent
};
/** GraphNode that translates and rotates its children.
@@ -197,10 +236,14 @@ struct GraphNodeCamera
*/
struct GraphNodeTranslationRotation
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ Vec3s translation;
/*0x1E*/ Vec3s rotation;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
/*0x18*/
Vec3s translation;
/*0x1E*/
Vec3s rotation;
};
/** GraphNode that translates itself and its children.
@@ -209,9 +252,12 @@ struct GraphNodeTranslationRotation
*/
struct GraphNodeTranslation
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ Vec3s translation;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
/*0x18*/
Vec3s translation;
u8 pad1E[2];
};
@@ -222,9 +268,12 @@ struct GraphNodeTranslation
*/
struct GraphNodeRotation
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ Vec3s rotation;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
/*0x18*/
Vec3s rotation;
u8 pad1E[2];
};
@@ -237,9 +286,12 @@ struct GraphNodeRotation
*/
struct GraphNodeAnimatedPart
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ Vec3s translation;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
/*0x18*/
Vec3s translation;
};
/** A GraphNode that draws a display list rotated in a way to always face the
@@ -249,9 +301,12 @@ struct GraphNodeAnimatedPart
*/
struct GraphNodeBillboard
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ Vec3s translation;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
/*0x18*/
Vec3s translation;
};
/** A GraphNode that simply draws a display list without doing any
@@ -259,8 +314,10 @@ struct GraphNodeBillboard
*/
struct GraphNodeDisplayList
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
};
/** GraphNode part that scales itself and its children.
@@ -273,9 +330,12 @@ struct GraphNodeDisplayList
*/
struct GraphNodeScale
{
/*0x00*/ struct GraphNode node;
/*0x14*/ void *displayList;
/*0x18*/ f32 scale;
/*0x00*/
struct GraphNode node;
/*0x14*/
void *displayList;
/*0x18*/
f32 scale;
};
/** GraphNode that draws a shadow under an object.
@@ -285,10 +345,14 @@ struct GraphNodeScale
*/
struct GraphNodeShadow
{
/*0x00*/ struct GraphNode node;
/*0x14*/ s16 shadowScale; // diameter (when a circle) or side (when a square) of shadow
/*0x16*/ u8 shadowSolidity; // opacity of shadow, 255 = opaque
/*0x17*/ u8 shadowType; // see ShadowType enum in shadow.h
/*0x00*/
struct GraphNode node;
/*0x14*/
s16 shadowScale; // diameter (when a circle) or side (when a square) of shadow
/*0x16*/
u8 shadowSolidity; // opacity of shadow, 255 = opaque
/*0x17*/
u8 shadowType; // see ShadowType enum in shadow.h
};
/** GraphNode that contains as its sharedChild a group node containing all
@@ -296,8 +360,10 @@ struct GraphNodeShadow
*/
struct GraphNodeObjectParent
{
/*0x00*/ struct GraphNode node;
/*0x14*/ struct GraphNode *sharedChild;
/*0x00*/
struct GraphNode node;
/*0x14*/
struct GraphNode *sharedChild;
};
/** GraphNode that draws display lists not directly in memory but generated by
@@ -310,8 +376,10 @@ struct GraphNodeObjectParent
*/
struct GraphNodeGenerated
{
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ u32 parameter; // extra context for the function
/*0x00*/
struct FnGraphNode fnNode;
/*0x18*/
u32 parameter; // extra context for the function
};
/** GraphNode that draws a background image or a rectangle of a color.
@@ -319,19 +387,26 @@ struct GraphNodeGenerated
*/
struct GraphNodeBackground
{
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ s32 unused;
/*0x1C*/ s32 background; // background ID, or rgba5551 color if fnNode.func is null
/*0x00*/
struct FnGraphNode fnNode;
/*0x18*/
s32 unused;
/*0x1C*/
s32 background; // background ID, or rgba5551 color if fnNode.func is null
};
/** Renders the object that Mario is holding.
*/
struct GraphNodeHeldObject
{
/*0x00*/ struct FnGraphNode fnNode;
/*0x18*/ s32 playerIndex;
/*0x1C*/ struct Object *objNode;
/*0x20*/ Vec3s translation;
/*0x00*/
struct FnGraphNode fnNode;
/*0x18*/
s32 playerIndex;
/*0x1C*/
struct Object *objNode;
/*0x20*/
Vec3s translation;
};
/** A node that allows an object to specify a different culling radius than the
@@ -341,8 +416,10 @@ struct GraphNodeHeldObject
*/
struct GraphNodeCullingRadius
{
/*0x00*/ struct GraphNode node;
/*0x14*/ s16 cullingRadius; // specifies the 'sphere radius' for purposes of frustum culling
/*0x00*/
struct GraphNode node;
/*0x14*/
s16 cullingRadius; // specifies the 'sphere radius' for purposes of frustum culling
u8 pad1E[2];
};
@@ -363,71 +440,122 @@ extern s16 gCurGraphNodeIndex;
void init_scene_graph_node_links(struct GraphNode *graphNode, s32 type);
struct GraphNodeRoot *init_graph_node_root(struct AllocOnlyPool *pool, struct GraphNodeRoot *graphNode,
s16 areaIndex, s16 x, s16 y, s16 width, s16 height);
struct GraphNodeRoot *init_graph_node_root(
struct AllocOnlyPool *pool, struct GraphNodeRoot *graphNode,
s16 areaIndex, s16 x, s16 y, s16 width, s16 height);
struct GraphNodeOrthoProjection *init_graph_node_ortho_projection(struct AllocOnlyPool *pool, struct GraphNodeOrthoProjection *graphNode, f32 scale);
struct GraphNodePerspective *init_graph_node_perspective(struct AllocOnlyPool *pool, struct GraphNodePerspective *graphNode,
f32 fov, s16 near, s16 far, GraphNodeFunc nodeFunc, s32 unused);
struct GraphNodePerspective *init_graph_node_perspective(
struct AllocOnlyPool *pool, struct GraphNodePerspective *graphNode,
f32 fov, s16 near, s16 far, GraphNodeFunc nodeFunc, s32 unused);
struct GraphNodeStart *init_graph_node_start(struct AllocOnlyPool *pool, struct GraphNodeStart *graphNode);
struct GraphNodeMasterList *init_graph_node_master_list(struct AllocOnlyPool *pool, struct GraphNodeMasterList *graphNode, s16 on);
struct GraphNodeLevelOfDetail *init_graph_node_render_range(struct AllocOnlyPool *pool, struct GraphNodeLevelOfDetail *graphNode,
s16 minDistance, s16 maxDistance);
struct GraphNodeSwitchCase *init_graph_node_switch_case(struct AllocOnlyPool *pool, struct GraphNodeSwitchCase *graphNode,
s16 numCases, s16 selectedCase, GraphNodeFunc nodeFunc, s32 unused);
struct GraphNodeCamera *init_graph_node_camera(struct AllocOnlyPool *pool, struct GraphNodeCamera *graphNode,
f32 *pos, f32 *focus, GraphNodeFunc func, s32 mode);
struct GraphNodeTranslationRotation *init_graph_node_translation_rotation(struct AllocOnlyPool *pool, struct GraphNodeTranslationRotation *graphNode,
s32 drawingLayer, void *displayList, Vec3s translation, Vec3s rotation);
struct GraphNodeTranslation *init_graph_node_translation(struct AllocOnlyPool *pool, struct GraphNodeTranslation *graphNode,
s32 drawingLayer, void *displayList, Vec3s translation);
struct GraphNodeRotation *init_graph_node_rotation(struct AllocOnlyPool *pool, struct GraphNodeRotation *graphNode,
s32 drawingLayer, void *displayList, Vec3s rotation);
struct GraphNodeScale *init_graph_node_scale(struct AllocOnlyPool *pool, struct GraphNodeScale *graphNode,
s32 drawingLayer, void *displayList, f32 scale);
struct GraphNodeObject *init_graph_node_object(struct AllocOnlyPool *pool, struct GraphNodeObject *graphNode,
struct GraphNode *sharedChild, Vec3f pos, Vec3s angle, Vec3f scale);
struct GraphNodeLevelOfDetail *init_graph_node_render_range(
struct AllocOnlyPool *pool, struct GraphNodeLevelOfDetail *graphNode,
s16 minDistance, s16 maxDistance);
struct GraphNodeSwitchCase *init_graph_node_switch_case(
struct AllocOnlyPool *pool, struct GraphNodeSwitchCase *graphNode,
s16 numCases, s16 selectedCase, GraphNodeFunc nodeFunc, s32 unused);
struct GraphNodeCamera *init_graph_node_camera(
struct AllocOnlyPool *pool, struct GraphNodeCamera *graphNode,
f32 *pos, f32 *focus, GraphNodeFunc func, s32 mode);
struct GraphNodeTranslationRotation *init_graph_node_translation_rotation(
struct AllocOnlyPool *pool, struct GraphNodeTranslationRotation *graphNode,
s32 drawingLayer, void *displayList, Vec3s translation, Vec3s rotation);
struct GraphNodeTranslation *init_graph_node_translation(
struct AllocOnlyPool *pool, struct GraphNodeTranslation *graphNode,
s32 drawingLayer, void *displayList, Vec3s translation);
struct GraphNodeRotation *init_graph_node_rotation(
struct AllocOnlyPool *pool, struct GraphNodeRotation *graphNode,
s32 drawingLayer, void *displayList, Vec3s rotation);
struct GraphNodeScale *init_graph_node_scale(
struct AllocOnlyPool *pool, struct GraphNodeScale *graphNode,
s32 drawingLayer, void *displayList, f32 scale);
struct GraphNodeObject *init_graph_node_object(
struct AllocOnlyPool *pool, struct GraphNodeObject *graphNode,
struct GraphNode *sharedChild, Vec3f pos, Vec3s angle, Vec3f scale);
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 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,
s32 drawingLayer, void *displayList);
struct GraphNodeShadow *init_graph_node_shadow(struct AllocOnlyPool *pool, struct GraphNodeShadow *graphNode,
s16 shadowScale, u8 shadowSolidity, u8 shadowType);
struct GraphNodeObjectParent *init_graph_node_object_parent(struct AllocOnlyPool *pool, struct GraphNodeObjectParent *sp1c,
struct GraphNode *sharedChild);
struct GraphNodeGenerated *init_graph_node_generated(struct AllocOnlyPool *pool, struct GraphNodeGenerated *sp1c,
GraphNodeFunc gfxFunc, s32 parameter);
struct GraphNodeBackground *init_graph_node_background(struct AllocOnlyPool *pool, struct GraphNodeBackground *sp1c,
u16 background, GraphNodeFunc backgroundFunc, s32 zero);
struct GraphNodeHeldObject *init_graph_node_held_object(struct AllocOnlyPool *pool, struct GraphNodeHeldObject *sp1c,
struct Object *objNode, Vec3s translation,
GraphNodeFunc nodeFunc, s32 playerIndex);
struct GraphNodeAnimatedPart *init_graph_node_animated_part(
struct AllocOnlyPool *pool, struct GraphNodeAnimatedPart *graphNode,
s32 drawingLayer, void *displayList, Vec3s translation);
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,
s32 drawingLayer, void *displayList);
struct GraphNodeShadow *init_graph_node_shadow(
struct AllocOnlyPool *pool, struct GraphNodeShadow *graphNode,
s16 shadowScale, u8 shadowSolidity, u8 shadowType);
struct GraphNodeObjectParent *init_graph_node_object_parent(
struct AllocOnlyPool *pool, struct GraphNodeObjectParent *sp1c,
struct GraphNode *sharedChild);
struct GraphNodeGenerated *init_graph_node_generated(
struct AllocOnlyPool *pool, struct GraphNodeGenerated *sp1c,
GraphNodeFunc gfxFunc, s32 parameter);
struct GraphNodeBackground *init_graph_node_background(
struct AllocOnlyPool *pool, struct GraphNodeBackground *sp1c,
u16 background, GraphNodeFunc backgroundFunc, s32 zero);
struct GraphNodeHeldObject *init_graph_node_held_object(
struct AllocOnlyPool *pool, struct GraphNodeHeldObject *sp1c,
struct Object *objNode, Vec3s translation,
GraphNodeFunc nodeFunc, s32 playerIndex);
struct GraphNode *geo_add_child(struct GraphNode *parent, struct GraphNode *childNode);
struct GraphNode *geo_remove_child(struct GraphNode *graphNode);
struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild);
void geo_call_global_function_nodes_helper(struct GraphNode *graphNode, s32 callContext);
void geo_call_global_function_nodes(struct GraphNode *graphNode, s32 callContext);
void geo_reset_object_node(struct GraphNodeObject *graphNode);
void geo_obj_init(struct GraphNodeObject *graphNode, void *sharedChild, Vec3f pos, Vec3s angle);
void geo_obj_init_spawninfo(struct GraphNodeObject *graphNode, struct SpawnInfo *spawn);
void geo_obj_init_animation(struct GraphNodeObject *graphNode, struct Animation **animPtrAddr);
void geo_obj_init_animation_accel(struct GraphNodeObject *graphNode, struct Animation **animPtrAddr, u32 animAccel);
s32 retrieve_animation_index(s32 frame, u16 **attributes);
s16 geo_update_animation_frame(struct AnimInfo *obj, s32 *accelAssist);
void geo_retreive_animation_translation(struct GraphNodeObject *obj, Vec3f position);
struct GraphNodeRoot *geo_find_root(struct GraphNode *graphNode);
// graph_node_manager
s16 *read_vec3s_to_vec3f(Vec3f, s16 *src);
s16 *read_vec3s_to_vec3f(Vec3f, s16 * src);
s16 *read_vec3s(Vec3s dst, s16 *src);
s16 *read_vec3s_angle(Vec3s dst, s16 *src);
void register_scene_graph_node(struct GraphNode *graphNode);
#endif // GRAPH_NODE_H
+32 -17
View File
@@ -6,14 +6,17 @@
#include "graph_node.h"
#if IS_64_BIT
static s16 next_s16_in_geo_script(s16 **src) {
static s16 next_s16_in_geo_script(s16 **src)
{
s16 ret;
if (((uintptr_t)(*src) & 7) == 4) {
*src += 2; // skip 32 bits
if (((uintptr_t)(*src) & 7) == 4)
{
*src += 2; // skip 32 bits
}
ret = *(*src)++;
if (((uintptr_t)(*src) & 7) == 4) {
*src += 2; // skip 32 bits
if (((uintptr_t)(*src) & 7) == 4)
{
*src += 2; // skip 32 bits
}
return ret;
}
@@ -25,7 +28,8 @@ static s16 next_s16_in_geo_script(s16 **src) {
* Takes a pointer to three shorts (supplied by a geo layout script) and
* copies it to the destination float vector.
*/
s16 *read_vec3s_to_vec3f(Vec3f dst, s16 *src) {
s16 *read_vec3s_to_vec3f(Vec3f dst, s16 *src)
{
dst[0] = next_s16_in_geo_script(&src);
dst[1] = next_s16_in_geo_script(&src);
dst[2] = next_s16_in_geo_script(&src);
@@ -37,7 +41,8 @@ s16 *read_vec3s_to_vec3f(Vec3f dst, s16 *src) {
* copies it to the destination vector. It's essentially a memcpy but consistent
* with the other two 'geo-script vector to internal vector' functions.
*/
s16 *read_vec3s(Vec3s dst, s16 *src) {
s16 *read_vec3s(Vec3s dst, s16 *src)
{
dst[0] = next_s16_in_geo_script(&src);
dst[1] = next_s16_in_geo_script(&src);
dst[2] = next_s16_in_geo_script(&src);
@@ -49,7 +54,8 @@ s16 *read_vec3s(Vec3s dst, s16 *src) {
* and converts it to a vector of three in-game angle units in [-32768, 32767]
* range.
*/
s16 *read_vec3s_angle(Vec3s dst, s16 *src) {
s16 *read_vec3s_angle(Vec3s dst, s16 *src)
{
dst[0] = (next_s16_in_geo_script(&src) << 15) / 180;
dst[1] = (next_s16_in_geo_script(&src) << 15) / 180;
dst[2] = (next_s16_in_geo_script(&src) << 15) / 180;
@@ -61,19 +67,28 @@ s16 *read_vec3s_angle(Vec3s dst, s16 *src) {
* 'gCurGraphNodeList'. This is called from geo_layout commands to add nodes
* to the scene graph.
*/
void register_scene_graph_node(struct GraphNode *graphNode) {
if (graphNode != NULL) {
void register_scene_graph_node(struct GraphNode *graphNode)
{
if (graphNode != nullptr)
{
gCurGraphNodeList[gCurGraphNodeIndex] = graphNode;
if (gCurGraphNodeIndex == 0) {
if (gCurRootGraphNode == NULL) {
if (gCurGraphNodeIndex == 0)
{
if (gCurRootGraphNode == nullptr)
{
gCurRootGraphNode = graphNode;
}
} else {
if (gCurGraphNodeList[gCurGraphNodeIndex - 1]->type == GRAPH_NODE_TYPE_OBJECT_PARENT) {
((struct GraphNodeObjectParent *) gCurGraphNodeList[gCurGraphNodeIndex - 1])
->sharedChild = graphNode;
} else {
}
else
{
if (gCurGraphNodeList[gCurGraphNodeIndex - 1]->type == GRAPH_NODE_TYPE_OBJECT_PARENT)
{
((struct GraphNodeObjectParent *)gCurGraphNodeList[gCurGraphNodeIndex - 1])
->sharedChild = graphNode;
}
else
{
geo_add_child(gCurGraphNodeList[gCurGraphNodeIndex - 1], graphNode);
}
}
+38 -21
View File
@@ -5,14 +5,17 @@
#endif
#ifndef GBI_FLOATS
void guMtxF2L(float mf[4][4], Mtx *m) {
void guMtxF2L(float mf[4][4], Mtx *m)
{
int r, c;
s32 tmp1;
s32 tmp2;
s32 *m1 = &m->m[0][0];
s32 *m2 = &m->m[2][0];
for (r = 0; r < 4; r++) {
for (c = 0; c < 2; c++) {
for (r = 0; r < 4; r++)
{
for (c = 0; c < 2; c++)
{
tmp1 = mf[r][2 * c] * 65536.0f;
tmp2 = mf[r][2 * c + 1] * 65536.0f;
*m1++ = (tmp1 & 0xffff0000) | ((tmp2 >> 0x10) & 0xffff);
@@ -20,53 +23,67 @@ void guMtxF2L(float mf[4][4], Mtx *m) {
}
}
}
void guMtxL2F(float mf[4][4], Mtx *m) {
void guMtxL2F(float mf[4][4], Mtx *m)
{
int r, c;
u32 tmp1;
u32 tmp2;
u32 *m1;
u32 *m2;
s32 stmp1, stmp2;
m1 = (u32 *) &m->m[0][0];
m2 = (u32 *) &m->m[2][0];
for (r = 0; r < 4; r++) {
for (c = 0; c < 2; c++) {
m1 = (u32 *)&m->m[0][0];
m2 = (u32 *)&m->m[2][0];
for (r = 0; r < 4; r++)
{
for (c = 0; c < 2; c++)
{
tmp1 = (*m1 & 0xffff0000) | ((*m2 >> 0x10) & 0xffff);
tmp2 = ((*m1++ << 0x10) & 0xffff0000) | (*m2++ & 0xffff);
stmp1 = *(s32 *) &tmp1;
stmp2 = *(s32 *) &tmp2;
stmp1 = *(s32 *)&tmp1;
stmp2 = *(s32 *)&tmp2;
mf[r][c * 2 + 0] = stmp1 / 65536.0f;
mf[r][c * 2 + 1] = stmp2 / 65536.0f;
}
}
}
#else
void guMtxF2L(float mf[4][4], Mtx *m) {
void guMtxF2L(float mf[4][4], Mtx *m)
{
memcpy(m, mf, sizeof(Mtx));
}
void guMtxL2F(float mf[4][4], Mtx *m) {
void guMtxL2F(float mf[4][4], Mtx *m)
{
memcpy(mf, m, sizeof(Mtx));
}
#endif
void guMtxIdentF(float mf[4][4]) {
void guMtxIdentF(float mf[4][4])
{
int r, c;
for (r = 0; r < 4; r++) {
for (c = 0; c < 4; c++) {
if (r == c) {
for (r = 0; r < 4; r++)
{
for (c = 0; c < 4; c++)
{
if (r == c)
{
mf[r][c] = 1.0f;
} else {
}
else
{
mf[r][c] = 0.0f;
}
}
}
}
void guMtxIdent(Mtx *m) {
#ifndef GBI_FLOATS
void guMtxIdent(Mtx *m)
{
#ifndef GBI_FLOATS
float mf[4][4];
guMtxIdentF(mf);
guMtxF2L(mf, m);
#else
#else
guMtxIdentF(m->m);
#endif
#endif
}
+1
View File
@@ -4,6 +4,7 @@
#include "../include/PR/gbi.h"
extern void guMtxF2L(float mf[4][4], Mtx *m);
extern void guMtxL2F(float mf[4][4], Mtx *m);
#endif//GUMTXF2L_H
+199 -111
View File
@@ -8,13 +8,13 @@
#include "graph_node.h"
#include "surface_collision.h"
static Vec3f gVec3fZero = { 0.0f, 0.0f, 0.0f };
static Vec3f gVec3fZero = {0.0f, 0.0f, 0.0f};
// Inlined tables
f32 gSineTable[] = {
0.000000000f, 0.0015339801f,0.0030679568f,0.004601926f,
0.0061358847f,0.007669829f, 0.009203754f, 0.010737659f,
0.012271538f, 0.0138053885f,0.015339206f, 0.016872987f,
0.000000000f, 0.0015339801f, 0.0030679568f, 0.004601926f,
0.0061358847f, 0.007669829f, 0.009203754f, 0.010737659f,
0.012271538f, 0.0138053885f, 0.015339206f, 0.016872987f,
0.018406730f, 0.019940428f, 0.021474080f, 0.023007682f,
0.024541229f, 0.026074719f, 0.027608145f, 0.029141508f,
0.030674804f, 0.032208025f, 0.033741172f, 0.035274237f,
@@ -268,11 +268,11 @@ f32 gSineTable[] = {
0.999830604f, 0.999857664f, 0.999882340f, 0.999904692f,
0.999924719f, 0.999942362f, 0.999957621f, 0.999970615f,
0.999981165f, 0.999989390f, 0.999995291f, 0.999998808f,
#ifndef AVOID_UB
#ifndef AVOID_UB
};
f32 gCosineTable[0x1000] = {
#endif
#endif
// cosine
1.000000000f, 0.999998808f, 0.999995291f, 0.999989390f,
0.999981165f, 0.999970615f, 0.999957621f, 0.999942362f,
@@ -529,12 +529,12 @@ f32 gCosineTable[0x1000] = {
0.024541229f, 0.023007682f, 0.021474080f, 0.019940428f,
0.018406730f, 0.016872987f, 0.015339206f, 0.0138053885f,
0.012271538f, 0.010737659f, 0.009203754f, 0.007669829f,
0.0061358847f,0.004601926f, 0.0030679568f,0.0015339801f,
0.0061358847f, 0.004601926f, 0.0030679568f, 0.0015339801f,
// negative sine
0.000000000f, -0.0015339801f,-0.0030679568f,-0.004601926f,
-0.0061358847f,-0.007669829f, -0.009203754f, -0.010737659f,
-0.012271538f, -0.0138053885f,-0.015339206f, -0.016872987f,
0.000000000f, -0.0015339801f, -0.0030679568f, -0.004601926f,
-0.0061358847f, -0.007669829f, -0.009203754f, -0.010737659f,
-0.012271538f, -0.0138053885f, -0.015339206f, -0.016872987f,
-0.018406730f, -0.019940428f, -0.021474080f, -0.023007682f,
-0.024541229f, -0.026074719f, -0.027608145f, -0.029141508f,
-0.030674804f, -0.032208025f, -0.033741172f, -0.035274237f,
@@ -1045,12 +1045,12 @@ f32 gCosineTable[0x1000] = {
-0.024541229f, -0.023007682f, -0.021474080f, -0.019940428f,
-0.018406730f, -0.016872987f, -0.015339206f, -0.0138053885f,
-0.012271538f, -0.010737659f, -0.009203754f, -0.007669829f,
-0.0061358847f,-0.004601926f, -0.0030679568f,-0.0015339801f,
-0.0061358847f, -0.004601926f, -0.0030679568f, -0.0015339801f,
// sine
0.000000000f, 0.0015339801f,0.0030679568f,0.004601926f,
0.0061358847f,0.007669829f, 0.009203754f, 0.010737659f,
0.012271538f, 0.0138053885f,0.015339206f, 0.016872987f,
0.000000000f, 0.0015339801f, 0.0030679568f, 0.004601926f,
0.0061358847f, 0.007669829f, 0.009203754f, 0.010737659f,
0.012271538f, 0.0138053885f, 0.015339206f, 0.016872987f,
0.018406730f, 0.019940428f, 0.021474080f, 0.023007682f,
0.024541229f, 0.026074719f, 0.027608145f, 0.029141508f,
0.030674804f, 0.032208025f, 0.033741172f, 0.035274237f,
@@ -1450,7 +1450,8 @@ int gSplineState;
#pragma GCC diagnostic ignored "-Wreturn-local-addr"
/// Copy vector 'src' to 'dest'
void *vec3f_copy(Vec3f dest, Vec3f src) {
void *vec3f_copy(Vec3f dest, Vec3f src)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
@@ -1458,7 +1459,8 @@ void *vec3f_copy(Vec3f dest, Vec3f src) {
}
/// Set vector 'dest' to (x, y, z)
void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z) {
void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z)
{
dest[0] = x;
dest[1] = y;
dest[2] = z;
@@ -1466,7 +1468,8 @@ void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z) {
}
/// Add vector 'a' to 'dest'
void *vec3f_add(Vec3f dest, Vec3f a) {
void *vec3f_add(Vec3f dest, Vec3f a)
{
dest[0] += a[0];
dest[1] += a[1];
dest[2] += a[2];
@@ -1474,7 +1477,8 @@ void *vec3f_add(Vec3f dest, Vec3f a) {
}
/// Make 'dest' the sum of vectors a and b.
void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b) {
void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b)
{
dest[0] = a[0] + b[0];
dest[1] = a[1] + b[1];
dest[2] = a[2] + b[2];
@@ -1482,7 +1486,8 @@ void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b) {
}
/// Copy vector src to dest
void *vec3s_copy(Vec3s dest, Vec3s src) {
void *vec3s_copy(Vec3s dest, Vec3s src)
{
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
@@ -1490,7 +1495,8 @@ void *vec3s_copy(Vec3s dest, Vec3s src) {
}
/// Set vector 'dest' to (x, y, z)
void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z) {
void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z)
{
dest[0] = x;
dest[1] = y;
dest[2] = z;
@@ -1498,7 +1504,8 @@ void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z) {
}
/// Add vector a to 'dest'
void *vec3s_add(Vec3s dest, Vec3s a) {
void *vec3s_add(Vec3s dest, Vec3s a)
{
dest[0] += a[0];
dest[1] += a[1];
dest[2] += a[2];
@@ -1506,7 +1513,8 @@ void *vec3s_add(Vec3s dest, Vec3s a) {
}
/// Make 'dest' the sum of vectors a and b.
void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b) {
void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b)
{
dest[0] = a[0] + b[0];
dest[1] = a[1] + b[1];
dest[2] = a[2] + b[2];
@@ -1514,7 +1522,8 @@ void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b) {
}
/// Subtract vector a from 'dest'
void *vec3s_sub(Vec3s dest, Vec3s a) {
void *vec3s_sub(Vec3s dest, Vec3s a)
{
dest[0] -= a[0];
dest[1] -= a[1];
dest[2] -= a[2];
@@ -1522,7 +1531,8 @@ void *vec3s_sub(Vec3s dest, Vec3s a) {
}
/// Convert short vector a to float vector 'dest'
void *vec3s_to_vec3f(Vec3f dest, Vec3s a) {
void *vec3s_to_vec3f(Vec3f dest, Vec3s a)
{
dest[0] = a[0];
dest[1] = a[1];
dest[2] = a[2];
@@ -1533,7 +1543,8 @@ void *vec3s_to_vec3f(Vec3f dest, Vec3s a) {
* Convert float vector a to a short vector 'dest' by rounding the components
* to the nearest integer.
*/
void *vec3f_to_vec3s(Vec3s dest, Vec3f a) {
void *vec3f_to_vec3s(Vec3s dest, Vec3f a)
{
// add/subtract 0.5 in order to round to the nearest s32 instead of truncating
dest[0] = a[0] + ((a[0] > 0) ? 0.5f : -0.5f);
dest[1] = a[1] + ((a[1] > 0) ? 0.5f : -0.5f);
@@ -1546,7 +1557,8 @@ void *vec3f_to_vec3s(Vec3s dest, Vec3f a) {
* It is similar to vec3f_cross, but it calculates the vectors (c-b) and (b-a)
* at the same time.
*/
void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c) {
void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c)
{
dest[0] = (b[1] - a[1]) * (c[2] - b[2]) - (c[1] - b[1]) * (b[2] - a[2]);
dest[1] = (b[2] - a[2]) * (c[0] - b[0]) - (c[2] - b[2]) * (b[0] - a[0]);
dest[2] = (b[0] - a[0]) * (c[1] - b[1]) - (c[0] - b[0]) * (b[1] - a[1]);
@@ -1554,7 +1566,8 @@ void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c)
}
/// Make vector 'dest' the cross product of vectors a and b.
void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b) {
void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b)
{
dest[0] = a[1] * b[2] - b[1] * a[2];
dest[1] = a[2] * b[0] - b[2] * a[0];
dest[2] = a[0] * b[1] - b[0] * a[1];
@@ -1562,7 +1575,8 @@ void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b) {
}
/// Scale vector 'dest' so it has length 1
void *vec3f_normalize(Vec3f dest) {
void *vec3f_normalize(Vec3f dest)
{
//! Possible division by zero
f32 invsqrt = 1.0f / sqrtf(dest[0] * dest[0] + dest[1] * dest[1] + dest[2] * dest[2]);
@@ -1575,12 +1589,14 @@ void *vec3f_normalize(Vec3f dest) {
#pragma GCC diagnostic pop
/// Copy matrix 'src' to 'dest'
void mtxf_copy(Mat4 dest, Mat4 src) {
void mtxf_copy(Mat4 dest, Mat4 src)
{
register s32 i;
register u32 *d = (u32 *) dest;
register u32 *s = (u32 *) src;
register u32 *d = (u32 *)dest;
register u32 *s = (u32 *)src;
for (i = 0; i < 16; i++) {
for (i = 0; i < 16; i++)
{
*d++ = *s++;
}
}
@@ -1588,22 +1604,24 @@ void mtxf_copy(Mat4 dest, Mat4 src) {
/**
* Set mtx to the identity matrix
*/
void mtxf_identity(Mat4 mtx) {
void mtxf_identity(Mat4 mtx)
{
register s32 i;
register f32 *dest;
// These loops must be one line to match on -O2
// initialize everything except the first and last cells to 0
for (dest = (f32 *) mtx + 1, i = 0; i < 14; dest++, i++) *dest = 0;
for (dest = (f32 *)mtx + 1, i = 0; i < 14; dest++, i++) *dest = 0;
// initialize the diagonal cells to 1
for (dest = (f32 *) mtx, i = 0; i < 4; dest += 5, i++) *dest = 1;
for (dest = (f32 *)mtx, i = 0; i < 4; dest += 5, i++) *dest = 1;
}
/**
* Set dest to a translation matrix of vector b
*/
void mtxf_translate(Mat4 dest, Vec3f b) {
void mtxf_translate(Mat4 dest, Vec3f b)
{
mtxf_identity(dest);
dest[3][0] = b[0];
dest[3][1] = b[1];
@@ -1616,7 +1634,8 @@ void mtxf_translate(Mat4 dest, Vec3f b) {
* at the position 'to'. The up-vector is assumed to be (0, 1, 0), but the 'roll'
* angle allows a bank rotation of the camera.
*/
void mtxf_lookat(Mat4 mtx, Vec3f from, Vec3f to, s16 roll) {
void mtxf_lookat(Mat4 mtx, Vec3f from, Vec3f to, s16 roll)
{
register f32 invLength;
f32 dx;
f32 dz;
@@ -1694,7 +1713,8 @@ void mtxf_lookat(Mat4 mtx, Vec3f from, Vec3f to, s16 roll) {
* Build a matrix that rotates around the z axis, then the x axis, then the y
* axis, and then translates.
*/
void mtxf_rotate_zxy_and_translate(Mat4 dest, Vec3f translate, Vec3s rotate) {
void mtxf_rotate_zxy_and_translate(Mat4 dest, Vec3f translate, Vec3s rotate)
{
register f32 sx = sins(rotate[0]);
register f32 cx = coss(rotate[0]);
@@ -1727,7 +1747,8 @@ void mtxf_rotate_zxy_and_translate(Mat4 dest, Vec3f translate, Vec3s rotate) {
* Build a matrix that rotates around the x axis, then the y axis, then the z
* axis, and then translates.
*/
void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c) {
void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c)
{
register f32 sx = sins(c[0]);
register f32 cx = coss(c[0]);
@@ -1764,7 +1785,8 @@ void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c) {
* 'position' is the position of the object in the world
* 'angle' rotates the object while still facing the camera.
*/
void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) {
void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle)
{
dest[0][0] = coss(angle);
dest[0][1] = sins(angle);
dest[0][2] = 0;
@@ -1781,11 +1803,11 @@ void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) {
dest[2][3] = 0;
dest[3][0] =
mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0];
dest[3][1] =
mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1];
dest[3][2] =
mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2];
dest[3][3] = 1;
}
@@ -1796,7 +1818,8 @@ void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle) {
* 'yaw' is the angle which it should face
* 'pos' is the object's position in the world
*/
void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s16 yaw) {
void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s16 yaw)
{
Vec3f lateralDir;
Vec3f leftDir;
Vec3f forwardDir;
@@ -1839,7 +1862,8 @@ void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s16 yaw) {
* 'pos' is the object's position in the world
* 'radius' is the distance from each triangle vertex to the center
*/
void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s16 yaw, f32 radius) {
void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s16 yaw, f32 radius)
{
struct SM64SurfaceCollisionData *sp74;
Vec3f point0;
Vec3f point1;
@@ -1862,15 +1886,18 @@ void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s16 yaw, f32 radius) {
point1[1] = find_floor(point1[0], pos[1] + 150, point1[2], &sp74);
point2[1] = find_floor(point2[0], pos[1] + 150, point2[2], &sp74);
if (point0[1] - pos[1] < minY) {
if (point0[1] - pos[1] < minY)
{
point0[1] = pos[1];
}
if (point1[1] - pos[1] < minY) {
if (point1[1] - pos[1] < minY)
{
point1[1] = pos[1];
}
if (point2[1] - pos[1] < minY) {
if (point2[1] - pos[1] < minY)
{
point2[1] = pos[1];
}
@@ -1913,7 +1940,8 @@ void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s16 yaw, f32 radius) {
* The resulting matrix represents first applying transformation b and
* then a.
*/
void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b) {
void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b)
{
Mat4 temp;
register f32 entry0;
register f32 entry1;
@@ -1960,10 +1988,12 @@ void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b) {
/**
* Set matrix 'dest' to 'mtx' scaled by vector s
*/
void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s) {
void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s)
{
register s32 i;
for (i = 0; i < 4; i++) {
for (i = 0; i < 4; i++)
{
dest[0][i] = mtx[0][i] * s[0];
dest[1][i] = mtx[1][i] * s[1];
dest[2][i] = mtx[2][i] * s[2];
@@ -1976,7 +2006,8 @@ void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s) {
* to the point. Note that the bottom row is assumed to be [0, 0, 0, 1], which is
* true for transformation matrices if the translation has a w component of 1.
*/
void mtxf_mul_vec3s(Mat4 mtx, Vec3s b) {
void mtxf_mul_vec3s(Mat4 mtx, Vec3s b)
{
register f32 x = b[0];
register f32 y = b[1];
register f32 z = b[2];
@@ -1986,7 +2017,8 @@ void mtxf_mul_vec3s(Mat4 mtx, Vec3s b) {
b[2] = x * mtx[0][2] + y * mtx[1][2] + z * mtx[2][2] + mtx[3][2];
}
void mtxf_mul_vec3f(Mat4 mtx, Vec3f b) {
void mtxf_mul_vec3f(Mat4 mtx, Vec3f b)
{
register f32 x = b[0];
register f32 y = b[1];
register f32 z = b[2];
@@ -1994,7 +2026,8 @@ void mtxf_mul_vec3f(Mat4 mtx, Vec3f b) {
b[0] = x * mtx[0][0] + y * mtx[1][0] + z * mtx[2][0] + mtx[3][0];
b[1] = x * mtx[0][1] + y * mtx[1][1] + z * mtx[2][1] + mtx[3][1];
b[2] = x * mtx[0][2] + y * mtx[1][2] + z * mtx[2][2] + mtx[3][2];
}
}
/**
* Convert float matrix 'src' to fixed point matrix 'dest'.
* The float matrix may not contain entries larger than 65536 or the console
@@ -2004,30 +2037,33 @@ void mtxf_mul_vec3f(Mat4 mtx, Vec3f b) {
* exception. On Wii and Wii U Virtual Console the value will simply be clamped
* and no crashes occur.
*/
void mtxf_to_mtx(Mtx *dest, Mat4 src) {
#ifdef AVOID_UB
void mtxf_to_mtx(Mtx *dest, Mat4 src)
{
#ifdef AVOID_UB
// Avoid type-casting which is technically UB by calling the equivalent
// guMtxF2L function. This helps little-endian systems, as well.
guMtxF2L(src, dest);
#else
#else
s32 asFixedPoint;
register s32 i;
register s16 *a3 = (s16 *) dest; // all integer parts stored in first 16 bytes
register s16 *t0 = (s16 *) dest + 16; // all fraction parts stored in last 16 bytes
register f32 *t1 = (f32 *) src;
register s16 *a3 = (s16 *)dest; // all integer parts stored in first 16 bytes
register s16 *t0 = (s16 *)dest + 16; // all fraction parts stored in last 16 bytes
register f32 *t1 = (f32 *)src;
for (i = 0; i < 16; i++) {
for (i = 0; i < 16; i++)
{
asFixedPoint = *t1++ * (1 << 16); //! float-to-integer conversion responsible for PU crashes
*a3++ = GET_HIGH_S16_OF_32(asFixedPoint); // integer part
*t0++ = GET_LOW_S16_OF_32(asFixedPoint); // fraction part
*t0++ = GET_LOW_S16_OF_32(asFixedPoint); // fraction part
}
#endif
#endif
}
/**
* Set 'mtx' to a transformation matrix that rotates around the z axis.
*/
void mtxf_rotate_xy(Mtx *mtx, s16 angle) {
void mtxf_rotate_xy(Mtx *mtx, s16 angle)
{
Mat4 temp;
mtxf_identity(temp);
@@ -2046,17 +2082,18 @@ void mtxf_rotate_xy(Mtx *mtx, s16 angle) {
* objMtx back from screen orientation to world orientation, and then subtracting
* the camera position.
*/
void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx) {
void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx)
{
f32 camX = camMtx[3][0] * camMtx[0][0] + camMtx[3][1] * camMtx[0][1] + camMtx[3][2] * camMtx[0][2];
f32 camY = camMtx[3][0] * camMtx[1][0] + camMtx[3][1] * camMtx[1][1] + camMtx[3][2] * camMtx[1][2];
f32 camZ = camMtx[3][0] * camMtx[2][0] + camMtx[3][1] * camMtx[2][1] + camMtx[3][2] * camMtx[2][2];
dest[0] =
objMtx[3][0] * camMtx[0][0] + objMtx[3][1] * camMtx[0][1] + objMtx[3][2] * camMtx[0][2] - camX;
objMtx[3][0] * camMtx[0][0] + objMtx[3][1] * camMtx[0][1] + objMtx[3][2] * camMtx[0][2] - camX;
dest[1] =
objMtx[3][0] * camMtx[1][0] + objMtx[3][1] * camMtx[1][1] + objMtx[3][2] * camMtx[1][2] - camY;
objMtx[3][0] * camMtx[1][0] + objMtx[3][1] * camMtx[1][1] + objMtx[3][2] * camMtx[1][2] - camY;
dest[2] =
objMtx[3][0] * camMtx[2][0] + objMtx[3][1] * camMtx[2][1] + objMtx[3][2] * camMtx[2][2] - camZ;
objMtx[3][0] * camMtx[2][0] + objMtx[3][1] * camMtx[2][1] + objMtx[3][2] * camMtx[2][2] - camZ;
}
/**
@@ -2064,7 +2101,8 @@ void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx) {
* of that vector, as well as the yaw and pitch angles.
* Basically it converts the direction to spherical coordinates.
*/
void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 *yaw) {
void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 *yaw)
{
register f32 x = to[0] - from[0];
register f32 y = to[1] - from[1];
register f32 z = to[2] - from[2];
@@ -2078,7 +2116,8 @@ void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 *
* Construct the 'to' point which is distance 'dist' away from the 'from' position,
* and has the angles pitch and yaw.
*/
void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw) {
void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw)
{
to[0] = from[0] + dist * coss(pitch) * sins(yaw);
to[1] = from[1] + dist * sins(pitch);
to[2] = from[2] + dist * coss(pitch) * coss(yaw);
@@ -2088,18 +2127,24 @@ void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw
* Return the value 'current' after it tries to approach target, going up at
* most 'inc' and going down at most 'dec'.
*/
s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec) {
s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec)
{
//! If target is close to the max or min s32, then it's possible to overflow
// past it without stopping.
if (current < target) {
if (current < target)
{
current += inc;
if (current > target) {
if (current > target)
{
current = target;
}
} else {
}
else
{
current -= dec;
if (current < target) {
if (current < target)
{
current = target;
}
}
@@ -2110,15 +2155,21 @@ s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec) {
* Return the value 'current' after it tries to approach target, going up at
* most 'inc' and going down at most 'dec'.
*/
f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec) {
if (current < target) {
f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec)
{
if (current < target)
{
current += inc;
if (current > target) {
if (current > target)
{
current = target;
}
} else {
}
else
{
current -= dec;
if (current < target) {
if (current < target)
{
current = target;
}
}
@@ -2129,12 +2180,16 @@ f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec) {
* Helper function for atan2s. Does a look up of the arctangent of y/x assuming
* the resulting angle is in range [0, 0x2000] (1/8 of a circle).
*/
static u16 atan2_lookup(f32 y, f32 x) {
static u16 atan2_lookup(f32 y, f32 x)
{
u16 ret;
if (x == 0) {
if (x == 0)
{
ret = gArctanTable[0];
} else {
}
else
{
ret = gArctanTable[(s32)(y / x * 1024 + 0.5f)];
}
return ret;
@@ -2144,37 +2199,59 @@ static u16 atan2_lookup(f32 y, f32 x) {
* Compute the angle from (0, 0) to (x, y) as a s16. Given that terrain is in
* the xz-plane, this is commonly called with (z, x) to get a yaw angle.
*/
s16 atan2s(f32 y, f32 x) {
s16 atan2s(f32 y, f32 x)
{
u16 ret;
if (x >= 0) {
if (y >= 0) {
if (y >= x) {
if (x >= 0)
{
if (y >= 0)
{
if (y >= x)
{
ret = atan2_lookup(x, y);
} else {
}
else
{
ret = 0x4000 - atan2_lookup(y, x);
}
} else {
}
else
{
y = -y;
if (y < x) {
if (y < x)
{
ret = 0x4000 + atan2_lookup(y, x);
} else {
}
else
{
ret = 0x8000 - atan2_lookup(x, y);
}
}
} else {
}
else
{
x = -x;
if (y < 0) {
if (y < 0)
{
y = -y;
if (y >= x) {
if (y >= x)
{
ret = 0x8000 + atan2_lookup(x, y);
} else {
}
else
{
ret = 0xC000 - atan2_lookup(y, x);
}
} else {
if (y < x) {
}
else
{
if (y < x)
{
ret = 0xC000 + atan2_lookup(y, x);
} else {
}
else
{
ret = -atan2_lookup(x, y);
}
}
@@ -2220,14 +2297,16 @@ s16 atan2s(f32 y, f32 x) {
* [0, 0, 0, 0, 1, 2, ... n-1, n, n, n, n]
* TODO: verify the classification of the spline / figure out how polynomials were computed
*/
void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c) {
void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c)
{
f32 tinv = 1 - t;
f32 tinv2 = tinv * tinv;
f32 tinv3 = tinv2 * tinv;
f32 t2 = t * t;
f32 t3 = t2 * t;
switch (gSplineState) {
switch (gSplineState)
{
case CURVE_BEGIN_1:
result[0] = tinv3;
result[1] = t3 * 1.75f - t2 * 4.5f + t * 3.0f;
@@ -2269,7 +2348,8 @@ void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c) {
* The array should end with three entries with s=0 (infinite keyframe duration).
* That's because the spline has a 3rd degree polynomial, so it looks 3 points ahead.
*/
void anim_spline_init(Vec4s *keyFrames) {
void anim_spline_init(Vec4s *keyFrames)
{
gSplineKeyframe = keyFrames;
gSplineKeyframeFraction = 0;
gSplineState = 1;
@@ -2280,28 +2360,33 @@ void anim_spline_init(Vec4s *keyFrames) {
* anim_spline_init should be called before polling for vectors.
* Returns TRUE when the last point is reached, FALSE otherwise.
*/
s32 anim_spline_poll(Vec3f result) {
s32 anim_spline_poll(Vec3f result)
{
Vec4f weights;
s32 i;
s32 hasEnded = FALSE;
vec3f_copy(result, gVec3fZero);
spline_get_weights(weights, gSplineKeyframeFraction, gSplineState);
for (i = 0; i < 4; i++) {
for (i = 0; i < 4; i++)
{
result[0] += weights[i] * gSplineKeyframe[i][1];
result[1] += weights[i] * gSplineKeyframe[i][2];
result[2] += weights[i] * gSplineKeyframe[i][3];
}
if ((gSplineKeyframeFraction += gSplineKeyframe[0][0] / 1000.0f) >= 1) {
if ((gSplineKeyframeFraction += gSplineKeyframe[0][0] / 1000.0f) >= 1)
{
gSplineKeyframe++;
gSplineKeyframeFraction--;
switch (gSplineState) {
switch (gSplineState)
{
case CURVE_END_2:
hasEnded = TRUE;
break;
case CURVE_MIDDLE:
if (gSplineKeyframe[2][0] == 0) {
if (gSplineKeyframe[2][0] == 0)
{
gSplineState = CURVE_END_1;
}
break;
@@ -2315,7 +2400,6 @@ s32 anim_spline_poll(Vec3f result) {
}
// From object_helpers.c
/**
@@ -2326,9 +2410,11 @@ s32 anim_spline_poll(Vec3f result) {
* | 0 0 0 1 |
* i.e. a matrix representing a linear transformation over 3 space.
*/
void linear_mtxf_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v) {
void linear_mtxf_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v)
{
s32 i;
for (i = 0; i < 3; i++) {
for (i = 0; i < 3; i++)
{
dst[i] = m[0][i] * v[0] + m[1][i] * v[1] + m[2][i] * v[2];
}
}
@@ -2341,9 +2427,11 @@ void linear_mtxf_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v) {
* | 0 0 0 1 |
* i.e. a matrix representing a linear transformation over 3 space.
*/
void linear_mtxf_transpose_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v) {
void linear_mtxf_transpose_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v)
{
s32 i;
for (i = 0; i < 3; i++) {
for (i = 0; i < 3; i++)
{
dst[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][2] * v[2];
}
}
+40 -2
View File
@@ -34,49 +34,87 @@ extern f32 gCosineTable[];
#define sqr(x) ((x) * (x))
void *vec3f_copy(Vec3f dest, Vec3f src);
void *vec3f_set(Vec3f dest, f32 x, f32 y, f32 z);
void *vec3f_add(Vec3f dest, Vec3f a);
void *vec3f_sum(Vec3f dest, Vec3f a, Vec3f b);
void *vec3s_copy(Vec3s dest, Vec3s src);
void *vec3s_set(Vec3s dest, s16 x, s16 y, s16 z);
void *vec3s_add(Vec3s dest, Vec3s a);
void *vec3s_sum(Vec3s dest, Vec3s a, Vec3s b);
void *vec3s_sub(Vec3s dest, Vec3s a);
void *vec3s_to_vec3f(Vec3f dest, Vec3s a);
void *vec3f_to_vec3s(Vec3s dest, Vec3f a);
void *find_vector_perpendicular_to_plane(Vec3f dest, Vec3f a, Vec3f b, Vec3f c);
void *vec3f_cross(Vec3f dest, Vec3f a, Vec3f b);
void *vec3f_normalize(Vec3f dest);
void mtxf_copy(Mat4 dest, Mat4 src);
void mtxf_identity(Mat4 mtx);
void mtxf_translate(Mat4 dest, Vec3f b);
void mtxf_lookat(Mat4 mtx, Vec3f from, Vec3f to, s16 roll);
void mtxf_rotate_zxy_and_translate(Mat4 dest, Vec3f translate, Vec3s rotate);
void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c);
void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s16 angle);
void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s16 yaw);
void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s16 yaw, f32 radius);
void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b);
void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s);
void mtxf_mul_vec3s(Mat4 mtx, Vec3s b);
void mtxf_mul_vec3f(Mat4 mtx, Vec3f b);
void mtxf_to_mtx(Mtx *dest, Mat4 src);
void mtxf_rotate_xy(Mtx *mtx, s16 angle);
void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx);
void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 *yaw);
void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw);
void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s16 pitch, s16 yaw);
s32 approach_s32(s32 current, s32 target, s32 inc, s32 dec);
f32 approach_f32(f32 current, f32 target, f32 inc, f32 dec);
s16 atan2s(f32 y, f32 x);
// libsm64: `atan2f()` is not used anywhere and collides with `math.h`'s definition of the function, better to remove it entirely.
// f32 atan2f(f32 a, f32 b);
void spline_get_weights(Vec4f result, f32 t, UNUSED s32 c);
void anim_spline_init(Vec4s *keyFrames);
void anim_spline_init(Vec4s * keyFrames);
s32 anim_spline_poll(Vec3f result);
// From object_helpers.c
void linear_mtxf_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v);
void linear_mtxf_transpose_mul_vec3f(Mat4 m, Vec3f dst, Vec3f v);
+279 -218
View File
@@ -8,149 +8,168 @@
/**
* Iterate through the list of ceilings and find the first ceiling over a given point.
*/
static struct SM64SurfaceCollisionData *find_ceil_from_list( f32 x, f32 y, f32 z, f32 *pheight) {
static struct SM64SurfaceCollisionData *find_ceil_from_list(f32 x, f32 y, f32 z, f32 *pheight)
{
register struct SM64SurfaceCollisionData *surf;
register f32 x1, z1, x2, z2, x3, z3;
struct SM64SurfaceCollisionData *ceil = NULL;
struct SM64SurfaceCollisionData *ceil = nullptr;
ceil = NULL;
ceil = nullptr;
uint32_t groupCount = loaded_surface_iter_group_count();
for( int i = 0; i < groupCount; ++i ) {
uint32_t surfCount = loaded_surface_iter_group_size( i );
for( int j = 0; j < surfCount; ++j ) {
surf = loaded_surface_iter_get_at_index( i, j );
// libsm64: Weed out surfaces whose triangles are actually line segs. TODO do this at surface load time
if( !surf->isValid ) continue;
// Do the check normally done in add_surface_to_cell
if( surf->normal.y >= -0.01f ) continue;
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
z2 = surf->vertex2[2];
x2 = surf->vertex2[0];
// Checking if point is in bounds of the triangle laterally.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) > 0) {
continue;
}
// Slight optimization by checking these later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) > 0) {
continue;
}
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) > 0) {
continue;
}
for (int i = 0; i < groupCount; ++i)
{
uint32_t surfCount = loaded_surface_iter_group_size(i);
for (int j = 0; j < surfCount; ++j)
{
f32 nx = surf->normal.x;
f32 ny = surf->normal.y;
f32 nz = surf->normal.z;
f32 oo = surf->originOffset;
f32 height;
surf = loaded_surface_iter_get_at_index(i, j);
// If a wall, ignore it. Likely a remnant, should never occur.
if (ny == 0.0f) {
continue;
}
// libsm64: Weed out surfaces whose triangles are actually line segs. TODO do this at surface load time
if (!surf->isValid) continue;
// Find the ceil height at the specific point.
height = -(x * nx + nz * z + oo) / ny;
// Do the check normally done in add_surface_to_cell
if (surf->normal.y >= -0.01f) continue;
// Checks for ceiling interaction with a 78 unit buffer.
//! (Exposed Ceilings) Because any point above a ceiling counts
// as interacting with a ceiling, ceilings far below can cause
// "invisible walls" that are really just exposed ceilings.
if (y - (height - -78.0f) > 0.0f) {
continue;
}
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
z2 = surf->vertex2[2];
x2 = surf->vertex2[0];
if( height < *pheight )
// Checking if point is in bounds of the triangle laterally.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) > 0)
{
*pheight = height;
ceil = surf;
continue;
}
// Slight optimization by checking these later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) > 0)
{
continue;
}
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) > 0)
{
continue;
}
{
f32 nx = surf->normal.x;
f32 ny = surf->normal.y;
f32 nz = surf->normal.z;
f32 oo = surf->originOffset;
f32 height;
// If a wall, ignore it. Likely a remnant, should never occur.
if (ny == 0.0f)
{
continue;
}
// Find the ceil height at the specific point.
height = -(x * nx + nz * z + oo) / ny;
// Checks for ceiling interaction with a 78 unit buffer.
//! (Exposed Ceilings) Because any point above a ceiling counts
// as interacting with a ceiling, ceilings far below can cause
// "invisible walls" that are really just exposed ceilings.
if (y - (height - -78.0f) > 0.0f)
{
continue;
}
if (height < *pheight)
{
*pheight = height;
ceil = surf;
}
}
}
}}
}
return ceil;
}
/**
* Iterate through the list of floors and find the first floor under a given point.
*/
static struct SM64SurfaceCollisionData *find_floor_from_list( f32 x, f32 y, f32 z, f32 *pheight) {
static struct SM64SurfaceCollisionData *find_floor_from_list(f32 x, f32 y, f32 z, f32 *pheight)
{
register struct SM64SurfaceCollisionData *surf;
register f32 x1, z1, x2, z2, x3, z3;
f32 nx, ny, nz;
f32 oo;
f32 height;
struct SM64SurfaceCollisionData *floor = NULL;
struct SM64SurfaceCollisionData *floor = nullptr;
uint32_t groupCount = loaded_surface_iter_group_count();
for( int i = 0; i < groupCount; ++i ) {
uint32_t surfCount = loaded_surface_iter_group_size( i );
for( int j = 0; j < surfCount; ++j ) {
surf = loaded_surface_iter_get_at_index( i, j );
// libsm64: Weed out surfaces whose triangles are actually line segs. TODO do this at surface load time
if( !surf->isValid ) continue;
// Do the check normally done in add_surface_to_cell
if( surf->normal.y <= 0.01f ) continue;
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
x2 = surf->vertex2[0];
z2 = surf->vertex2[2];
// Check that the point is within the triangle bounds.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) < 0) {
continue;
}
// To slightly save on computation time, set this later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) < 0) {
continue;
}
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) < 0) {
continue;
}
nx = surf->normal.x;
ny = surf->normal.y;
nz = surf->normal.z;
oo = surf->originOffset;
// If a wall, ignore it. Likely a remnant, should never occur.
if (ny == 0.0f) {
continue;
}
// Find the height of the floor at a given location.
height = -(x * nx + nz * z + oo) / ny;
// Checks for floor interaction with a 78 unit buffer.
if (y - (height + -78.0f) < 0.0f) {
continue;
}
if( height > *pheight )
for (int i = 0; i < groupCount; ++i)
{
uint32_t surfCount = loaded_surface_iter_group_size(i);
for (int j = 0; j < surfCount; ++j)
{
*pheight = height;
floor = surf;
surf = loaded_surface_iter_get_at_index(i, j);
// libsm64: Weed out surfaces whose triangles are actually line segs. TODO do this at surface load time
if (!surf->isValid) continue;
// Do the check normally done in add_surface_to_cell
if (surf->normal.y <= 0.01f) continue;
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
x2 = surf->vertex2[0];
z2 = surf->vertex2[2];
// Check that the point is within the triangle bounds.
if ((z1 - z) * (x2 - x1) - (x1 - x) * (z2 - z1) < 0)
{
continue;
}
// To slightly save on computation time, set this later.
x3 = surf->vertex3[0];
z3 = surf->vertex3[2];
if ((z2 - z) * (x3 - x2) - (x2 - x) * (z3 - z2) < 0)
{
continue;
}
if ((z3 - z) * (x1 - x3) - (x3 - x) * (z1 - z3) < 0)
{
continue;
}
nx = surf->normal.x;
ny = surf->normal.y;
nz = surf->normal.z;
oo = surf->originOffset;
// If a wall, ignore it. Likely a remnant, should never occur.
if (ny == 0.0f)
{
continue;
}
// Find the height of the floor at a given location.
height = -(x * nx + nz * z + oo) / ny;
// Checks for floor interaction with a 78 unit buffer.
if (y - (height + -78.0f) < 0.0f)
{
continue;
}
if (height > *pheight)
{
*pheight = height;
floor = surf;
}
}
}}
}
return floor;
}
static s32 find_wall_collisions_from_list( struct SM64WallCollisionData *data) {
static s32 find_wall_collisions_from_list(struct SM64WallCollisionData *data)
{
register struct SM64SurfaceCollisionData *surf;
register f32 offset;
register f32 radius = data->radius;
@@ -163,129 +182,170 @@ static s32 find_wall_collisions_from_list( struct SM64WallCollisionData *data) {
s32 numCols = 0;
// Max collision radius = 200
if (radius > 200.0f) {
if (radius > 200.0f)
{
radius = 200.0f;
}
uint32_t groupCount = loaded_surface_iter_group_count();
for( int i = 0; i < groupCount; ++i ) {
uint32_t surfCount = loaded_surface_iter_group_size( i );
for( int j = 0; j < surfCount; ++j ) {
surf = loaded_surface_iter_get_at_index( i, j );
for (int i = 0; i < groupCount; ++i)
{
uint32_t surfCount = loaded_surface_iter_group_size(i);
for (int j = 0; j < surfCount; ++j)
{
surf = loaded_surface_iter_get_at_index(i, j);
// libsm64: Weed out surfaces whose triangles are actually line segs. TODO do this at surface load time
if( !surf->isValid ) continue;
// libsm64: Weed out surfaces whose triangles are actually line segs. TODO do this at surface load time
if (!surf->isValid) continue;
// Do the check normally done in add_surface_to_cell
if( surf->normal.y < -0.01f || surf->normal.y > 0.01f ) continue;
// Do the check normally done in add_surface_to_cell
if (surf->normal.y < -0.01f || surf->normal.y > 0.01f) continue;
if( surf->normal.x < -0.707f || surf->normal.x > 0.707f ) {
surf->flags |= SURFACE_FLAG_X_PROJECTION;
}
if (surf->normal.x < -0.707f || surf->normal.x > 0.707f)
{
surf->flags |= SURFACE_FLAG_X_PROJECTION;
}
// Exclude a large number of walls immediately to optimize.
if (y < surf->lowerY || y > surf->upperY) {
continue;
}
// Exclude a large number of walls immediately to optimize.
if (y < surf->lowerY || y > surf->upperY)
{
continue;
}
offset = surf->normal.x * x + surf->normal.y * y + surf->normal.z * z + surf->originOffset;
offset = surf->normal.x * x + surf->normal.y * y + surf->normal.z * z + surf->originOffset;
if (offset < -radius || offset > radius) {
continue;
}
if (offset < -radius || offset > radius)
{
continue;
}
px = x;
pz = z;
px = x;
pz = z;
//! (Quantum Tunneling) Due to issues with the vertices walls choose and
// the fact they are floating point, certain floating point positions
// along the seam of two walls may collide with neither wall or both walls.
if (surf->flags & SURFACE_FLAG_X_PROJECTION) {
w1 = -surf->vertex1[2]; w2 = -surf->vertex2[2]; w3 = -surf->vertex3[2];
y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
//! (Quantum Tunneling) Due to issues with the vertices walls choose and
// the fact they are floating point, certain floating point positions
// along the seam of two walls may collide with neither wall or both walls.
if (surf->flags & SURFACE_FLAG_X_PROJECTION)
{
w1 = -surf->vertex1[2];
w2 = -surf->vertex2[2];
w3 = -surf->vertex3[2];
y1 = surf->vertex1[1];
y2 = surf->vertex2[1];
y3 = surf->vertex3[1];
if (surf->normal.x > 0.0f) {
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) > 0.0f) {
continue;
if (surf->normal.x > 0.0f)
{
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) > 0.0f)
{
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) > 0.0f)
{
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) > 0.0f)
{
continue;
}
}
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) > 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) > 0.0f) {
continue;
}
} else {
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) < 0.0f) {
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) < 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) < 0.0f) {
continue;
else
{
if ((y1 - y) * (w2 - w1) - (w1 - -pz) * (y2 - y1) < 0.0f)
{
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - -pz) * (y3 - y2) < 0.0f)
{
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - -pz) * (y1 - y3) < 0.0f)
{
continue;
}
}
}
} else {
w1 = surf->vertex1[0]; w2 = surf->vertex2[0]; w3 = surf->vertex3[0];
y1 = surf->vertex1[1]; y2 = surf->vertex2[1]; y3 = surf->vertex3[1];
else
{
w1 = surf->vertex1[0];
w2 = surf->vertex2[0];
w3 = surf->vertex3[0];
y1 = surf->vertex1[1];
y2 = surf->vertex2[1];
y3 = surf->vertex3[1];
if (surf->normal.z > 0.0f) {
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) > 0.0f) {
continue;
if (surf->normal.z > 0.0f)
{
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) > 0.0f)
{
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) > 0.0f)
{
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) > 0.0f)
{
continue;
}
}
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) > 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) > 0.0f) {
continue;
}
} else {
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) < 0.0f) {
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) < 0.0f) {
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) < 0.0f) {
continue;
else
{
if ((y1 - y) * (w2 - w1) - (w1 - px) * (y2 - y1) < 0.0f)
{
continue;
}
if ((y2 - y) * (w3 - w2) - (w2 - px) * (y3 - y2) < 0.0f)
{
continue;
}
if ((y3 - y) * (w1 - w3) - (w3 - px) * (y1 - y3) < 0.0f)
{
continue;
}
}
}
}
// Ignore camera only surfaces.
if (surf->type == SURFACE_CAMERA_BOUNDARY) {
continue;
}
// Ignore camera only surfaces.
if (surf->type == SURFACE_CAMERA_BOUNDARY)
{
continue;
}
// If an object can pass through a vanish cap wall, pass through.
if (surf->type == SURFACE_VANISH_CAP_WALLS) {
// If an object can pass through a vanish cap wall, pass through.
if (gCurrentObject != NULL
&& (gCurrentObject->activeFlags & ACTIVE_FLAG_MOVE_THROUGH_GRATE)) {
continue;
if (surf->type == SURFACE_VANISH_CAP_WALLS)
{
// If an object can pass through a vanish cap wall, pass through.
if (gCurrentObject != nullptr
&& (gCurrentObject->activeFlags & ACTIVE_FLAG_MOVE_THROUGH_GRATE))
{
continue;
}
// If Mario has a vanish cap, pass through the vanish cap wall.
if (gCurrentObject != nullptr && gCurrentObject == gMarioObject
&& (gMarioState->flags & MARIO_VANISH_CAP))
{
continue;
}
}
// If Mario has a vanish cap, pass through the vanish cap wall.
if (gCurrentObject != NULL && gCurrentObject == gMarioObject
&& (gMarioState->flags & MARIO_VANISH_CAP)) {
continue;
//! (Wall Overlaps) Because this doesn't update the x and z local variables,
// multiple walls can push mario more than is required.
data->x += surf->normal.x * (radius - offset);
data->z += surf->normal.z * (radius - offset);
//! (Unreferenced Walls) Since this only returns the first four walls,
// this can lead to wall interaction being missed. Typically unreferenced walls
// come from only using one wall, however.
if (data->numWalls < 4)
{
data->walls[data->numWalls++] = surf;
}
numCols++;
}
//! (Wall Overlaps) Because this doesn't update the x and z local variables,
// multiple walls can push mario more than is required.
data->x += surf->normal.x * (radius - offset);
data->z += surf->normal.z * (radius - offset);
//! (Unreferenced Walls) Since this only returns the first four walls,
// this can lead to wall interaction being missed. Typically unreferenced walls
// come from only using one wall, however.
if (data->numWalls < 4) {
data->walls[data->numWalls++] = surf;
}
numCols++;
}}
}
return numCols;
}
@@ -335,8 +395,8 @@ s32 find_wall_collisions(struct SM64WallCollisionData *colData)
f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct SM64SurfaceCollisionData **pceil)
{
f32 height = CELL_HEIGHT_LIMIT;
*pceil = find_ceil_from_list( posX, posY, posZ, &height );
return height;
*pceil = find_ceil_from_list(posX, posY, posZ, &height);
return height;
}
struct SM64FloorCollisionData sFloorGeo;
@@ -346,9 +406,10 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct SM64FloorCol
struct SM64SurfaceCollisionData *floor;
f32 floorHeight = find_floor(xPos, yPos, zPos, &floor);
*floorGeo = NULL;
*floorGeo = nullptr;
if (floor != NULL) {
if (floor != nullptr)
{
sFloorGeo.normalX = floor->normal.x;
sFloorGeo.normalY = floor->normal.y;
sFloorGeo.normalZ = floor->normal.z;
@@ -362,23 +423,23 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct SM64FloorCol
f32 find_floor_height(f32 x, f32 y, f32 z)
{
f32 height = FLOOR_LOWER_LIMIT;
find_floor_from_list( x, y, z, &height );
return height;
find_floor_from_list(x, y, z, &height);
return height;
}
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct SM64SurfaceCollisionData **pfloor)
{
f32 height = FLOOR_LOWER_LIMIT;
*pfloor = find_floor_from_list( xPos, yPos, zPos, &height );
return height;
*pfloor = find_floor_from_list(xPos, yPos, zPos, &height);
return height;
}
f32 find_water_level(f32 x, f32 z)
{
return -10000.0f;
return -10000.0f;
}
f32 find_poison_gas_level(f32 x, f32 z)
{
return -10000.0f;
return -10000.0f;
}
+8 -1
View File
@@ -7,18 +7,25 @@
#include "../include/types.h"
#define LEVEL_BOUNDARY_MAX 0x2000
#define CELL_SIZE 0x400
#define CELL_SIZE 0x400
#define CELL_HEIGHT_LIMIT 100000.f
#define FLOOR_LOWER_LIMIT -110000.f
s32 f32_find_wall_collision(f32 *xPtr, f32 *yPtr, f32 *zPtr, f32 offsetY, f32 radius);
s32 find_wall_collisions(struct SM64WallCollisionData *colData);
f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct SM64SurfaceCollisionData **pceil);
f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct SM64FloorCollisionData **floorGeo);
f32 find_floor_height(f32 x, f32 y, f32 z);
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct SM64SurfaceCollisionData **pfloor);
f32 find_water_level(f32 x, f32 z);
f32 find_poison_gas_level(f32 x, f32 z);
#endif // SURFACE_COLLISION_H