mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Fix graph node interpolation (#917)
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run
Shared graph nodes were incorrectly interpolated, only the first object with a shared graph node was interpolated properly. Thanks to @Cooliokid956 for noticing that most of node types were **never** interpolated. - Use a double hashmap to store interpolated data for each graph node and object. All translations, rotations and scales are now interpolated correctly. - Add `GraphNodeScaleXYZ` type to scale to all 3 dimensions; Add `GEO_SCALE_XYZ` command. gMtxTbl was also reaching it's limit, so dynamic allocation was added.
This commit is contained in:
parent
b671458f81
commit
6e4373adc9
26 changed files with 428 additions and 144 deletions
|
|
@ -3050,6 +3050,9 @@ GRAPH_NODE_TYPE_DISPLAY_LIST = 0x01B
|
||||||
--- @type integer
|
--- @type integer
|
||||||
GRAPH_NODE_TYPE_SCALE = 0x01C
|
GRAPH_NODE_TYPE_SCALE = 0x01C
|
||||||
|
|
||||||
|
--- @type integer
|
||||||
|
GRAPH_NODE_TYPE_SCALE_XYZ = 0x01D
|
||||||
|
|
||||||
--- @type integer
|
--- @type integer
|
||||||
GRAPH_NODE_TYPE_SHADOW = 0x028
|
GRAPH_NODE_TYPE_SHADOW = 0x028
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -969,16 +969,18 @@
|
||||||
--- @class GraphNodeRotation
|
--- @class GraphNodeRotation
|
||||||
--- @field public displayList Pointer_Gfx
|
--- @field public displayList Pointer_Gfx
|
||||||
--- @field public node GraphNode
|
--- @field public node GraphNode
|
||||||
--- @field public prevRotation Vec3s
|
|
||||||
--- @field public prevTimestamp integer
|
|
||||||
--- @field public rotation Vec3s
|
--- @field public rotation Vec3s
|
||||||
|
|
||||||
--- @class GraphNodeScale
|
--- @class GraphNodeScale
|
||||||
--- @field public displayList Pointer_Gfx
|
--- @field public displayList Pointer_Gfx
|
||||||
--- @field public node GraphNode
|
--- @field public node GraphNode
|
||||||
--- @field public prevScale number
|
|
||||||
--- @field public scale number
|
--- @field public scale number
|
||||||
|
|
||||||
|
--- @class GraphNodeScaleXYZ
|
||||||
|
--- @field public displayList Pointer_Gfx
|
||||||
|
--- @field public node GraphNode
|
||||||
|
--- @field public scale Vec3f
|
||||||
|
|
||||||
--- @class GraphNodeShadow
|
--- @class GraphNodeShadow
|
||||||
--- @field public node GraphNode
|
--- @field public node GraphNode
|
||||||
--- @field public shadowScale integer
|
--- @field public shadowScale integer
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,8 @@ static void ParseGeoSymbol(GfxData* aGfxData, DataNode<GeoLayout>* aNode, GeoLay
|
||||||
geo_symbol_5(GEO_HELD_OBJECT, 2);
|
geo_symbol_5(GEO_HELD_OBJECT, 2);
|
||||||
geo_symbol_2(GEO_SCALE, 0);
|
geo_symbol_2(GEO_SCALE, 0);
|
||||||
geo_symbol_3(GEO_SCALE_WITH_DL, 2);
|
geo_symbol_3(GEO_SCALE_WITH_DL, 2);
|
||||||
|
geo_symbol_4(GEO_SCALE_XYZ, 0);
|
||||||
|
geo_symbol_5(GEO_SCALE_XYZ_WITH_DL, 4);
|
||||||
geo_symbol_0(GEO_NOP_1E);
|
geo_symbol_0(GEO_NOP_1E);
|
||||||
geo_symbol_0(GEO_NOP_1F);
|
geo_symbol_0(GEO_NOP_1F);
|
||||||
geo_symbol_1(GEO_CULLING_RADIUS, 0);
|
geo_symbol_1(GEO_CULLING_RADIUS, 0);
|
||||||
|
|
|
||||||
|
|
@ -135,8 +135,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void* hmap_create(MapType type) {
|
void* hmap_create(bool useUnordered) {
|
||||||
return new HMap(type);
|
return new HMap(useUnordered ? MapType::Unordered : MapType::Ordered);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* hmap_get(void* map, int64_t key) {
|
void* hmap_get(void* map, int64_t key) {
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,7 @@ static std::unordered_map<s16, size_t> sGraphNodeSizeMap = {
|
||||||
{ GRAPH_NODE_TYPE_TRANSLATION, sizeof(GraphNodeTranslation) },
|
{ GRAPH_NODE_TYPE_TRANSLATION, sizeof(GraphNodeTranslation) },
|
||||||
{ GRAPH_NODE_TYPE_ROTATION, sizeof(GraphNodeRotation) },
|
{ GRAPH_NODE_TYPE_ROTATION, sizeof(GraphNodeRotation) },
|
||||||
{ GRAPH_NODE_TYPE_SCALE, sizeof(GraphNodeScale) },
|
{ GRAPH_NODE_TYPE_SCALE, sizeof(GraphNodeScale) },
|
||||||
|
{ GRAPH_NODE_TYPE_SCALE_XYZ, sizeof(GraphNodeScaleXYZ) },
|
||||||
{ GRAPH_NODE_TYPE_OBJECT, sizeof(GraphNodeObject) },
|
{ GRAPH_NODE_TYPE_OBJECT, sizeof(GraphNodeObject) },
|
||||||
{ GRAPH_NODE_TYPE_CULLING_RADIUS, sizeof(GraphNodeCullingRadius) },
|
{ GRAPH_NODE_TYPE_CULLING_RADIUS, sizeof(GraphNodeCullingRadius) },
|
||||||
{ GRAPH_NODE_TYPE_ANIMATED_PART, sizeof(GraphNodeAnimatedPart) },
|
{ GRAPH_NODE_TYPE_ANIMATED_PART, sizeof(GraphNodeAnimatedPart) },
|
||||||
|
|
|
||||||
|
|
@ -1352,6 +1352,7 @@
|
||||||
- GRAPH_NODE_TYPE_BILLBOARD
|
- GRAPH_NODE_TYPE_BILLBOARD
|
||||||
- GRAPH_NODE_TYPE_DISPLAY_LIST
|
- GRAPH_NODE_TYPE_DISPLAY_LIST
|
||||||
- GRAPH_NODE_TYPE_SCALE
|
- GRAPH_NODE_TYPE_SCALE
|
||||||
|
- GRAPH_NODE_TYPE_SCALE_XYZ
|
||||||
- GRAPH_NODE_TYPE_SHADOW
|
- GRAPH_NODE_TYPE_SHADOW
|
||||||
- GRAPH_NODE_TYPE_OBJECT_PARENT
|
- GRAPH_NODE_TYPE_OBJECT_PARENT
|
||||||
- GRAPH_NODE_TYPE_GENERATED_LIST
|
- GRAPH_NODE_TYPE_GENERATED_LIST
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
- [GraphNodeRoot](#GraphNodeRoot)
|
- [GraphNodeRoot](#GraphNodeRoot)
|
||||||
- [GraphNodeRotation](#GraphNodeRotation)
|
- [GraphNodeRotation](#GraphNodeRotation)
|
||||||
- [GraphNodeScale](#GraphNodeScale)
|
- [GraphNodeScale](#GraphNodeScale)
|
||||||
|
- [GraphNodeScaleXYZ](#GraphNodeScaleXYZ)
|
||||||
- [GraphNodeShadow](#GraphNodeShadow)
|
- [GraphNodeShadow](#GraphNodeShadow)
|
||||||
- [GraphNodeStart](#GraphNodeStart)
|
- [GraphNodeStart](#GraphNodeStart)
|
||||||
- [GraphNodeSwitchCase](#GraphNodeSwitchCase)
|
- [GraphNodeSwitchCase](#GraphNodeSwitchCase)
|
||||||
|
|
@ -1477,8 +1478,6 @@
|
||||||
| ----- | ---- | ------ |
|
| ----- | ---- | ------ |
|
||||||
| displayList | `Pointer` <`Gfx`> | |
|
| displayList | `Pointer` <`Gfx`> | |
|
||||||
| node | [GraphNode](structs.md#GraphNode) | read-only |
|
| node | [GraphNode](structs.md#GraphNode) | read-only |
|
||||||
| prevRotation | [Vec3s](structs.md#Vec3s) | read-only |
|
|
||||||
| prevTimestamp | `integer` | |
|
|
||||||
| rotation | [Vec3s](structs.md#Vec3s) | read-only |
|
| rotation | [Vec3s](structs.md#Vec3s) | read-only |
|
||||||
|
|
||||||
[:arrow_up_small:](#)
|
[:arrow_up_small:](#)
|
||||||
|
|
@ -1491,13 +1490,24 @@
|
||||||
| ----- | ---- | ------ |
|
| ----- | ---- | ------ |
|
||||||
| displayList | `Pointer` <`Gfx`> | |
|
| displayList | `Pointer` <`Gfx`> | |
|
||||||
| node | [GraphNode](structs.md#GraphNode) | read-only |
|
| node | [GraphNode](structs.md#GraphNode) | read-only |
|
||||||
| prevScale | `number` | |
|
|
||||||
| scale | `number` | |
|
| scale | `number` | |
|
||||||
|
|
||||||
[:arrow_up_small:](#)
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
## [GraphNodeScaleXYZ](#GraphNodeScaleXYZ)
|
||||||
|
|
||||||
|
| Field | Type | Access |
|
||||||
|
| ----- | ---- | ------ |
|
||||||
|
| displayList | `Pointer` <`Gfx`> | |
|
||||||
|
| node | [GraphNode](structs.md#GraphNode) | read-only |
|
||||||
|
| scale | [Vec3f](structs.md#Vec3f) | read-only |
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## [GraphNodeShadow](#GraphNodeShadow)
|
## [GraphNodeShadow](#GraphNodeShadow)
|
||||||
|
|
||||||
| Field | Type | Access |
|
| Field | Type | Access |
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,30 @@ enum SkyBackgroundParams {
|
||||||
CMD_W(scale), \
|
CMD_W(scale), \
|
||||||
CMD_PTR(displayList)
|
CMD_PTR(displayList)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0x1D: Create scale scene graph node with optional display list
|
||||||
|
* 0x01: u8 params
|
||||||
|
* 0b1000_0000: if set, enable displayList field and drawingLayer
|
||||||
|
* 0b0100_0000: if set, enable scale XYZ
|
||||||
|
* 0b0000_1111: drawingLayer
|
||||||
|
* 0x02-0x03: unused
|
||||||
|
* 0x04: u32 scale X (0x10000 = 1.0)
|
||||||
|
* 0x08: u32 scale Y (0x10000 = 1.0)
|
||||||
|
* 0x0C: u32 scale Z (0x10000 = 1.0)
|
||||||
|
* 0x10: [u32 displayList: if MSbit bit of params is set, display list segment address]
|
||||||
|
*/
|
||||||
|
#define GEO_SCALE_XYZ(layer, sx, sy, sz) \
|
||||||
|
CMD_BBH(0x1D, (layer | 0x40), 0x0000), \
|
||||||
|
CMD_W(sx), \
|
||||||
|
CMD_W(sy), \
|
||||||
|
CMD_W(sz)
|
||||||
|
#define GEO_SCALE_XYZ_WITH_DL(layer, sx, sy, sz, displayList) \
|
||||||
|
CMD_BBH(0x1D, (layer | 0xC0), 0x0000), \
|
||||||
|
CMD_W(sx), \
|
||||||
|
CMD_W(sy), \
|
||||||
|
CMD_W(sz), \
|
||||||
|
CMD_PTR(displayList)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0x1E: No operation
|
* 0x1E: No operation
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -535,29 +535,45 @@ void geo_layout_cmd_node_rotation(void) {
|
||||||
0x1D: Create scale scene graph node with optional display list
|
0x1D: Create scale scene graph node with optional display list
|
||||||
cmd+0x01: u8 params
|
cmd+0x01: u8 params
|
||||||
(params & 0x80): if set, enable displayList field and drawingLayer
|
(params & 0x80): if set, enable displayList field and drawingLayer
|
||||||
|
(params & 0x40): if set, enable scale XYZ
|
||||||
(params & 0x0F): drawingLayer
|
(params & 0x0F): drawingLayer
|
||||||
cmd+0x04: u32 scale (0x10000 = 1.0)
|
cmd+0x04: u32 scale (0x10000 = 1.0)
|
||||||
[cmd+0x08: void *displayList]
|
or
|
||||||
|
cmd+0x04: u32 scale X (0x10000 = 1.0)
|
||||||
|
cmd+0x08: u32 scale Y (0x10000 = 1.0)
|
||||||
|
cmd+0x0C: u32 scale Z (0x10000 = 1.0)
|
||||||
|
[cmd+0x08/0x10: void *displayList]
|
||||||
*/
|
*/
|
||||||
void geo_layout_cmd_node_scale(void) {
|
void geo_layout_cmd_node_scale(void) {
|
||||||
struct GraphNodeScale *graphNode;
|
|
||||||
|
|
||||||
s16 drawingLayer = 0;
|
s16 drawingLayer = 0;
|
||||||
s16 params = cur_geo_cmd_u8(0x01);
|
s16 params = cur_geo_cmd_u8(0x01);
|
||||||
f32 scale = cur_geo_cmd_u32(0x04) / 65536.0f;
|
Vec3f scale;
|
||||||
void *displayList = NULL;
|
void *displayList = NULL;
|
||||||
|
bool isScaleXYZ = (params & 0x40) != 0;
|
||||||
|
|
||||||
if (params & 0x80) {
|
if (isScaleXYZ) {
|
||||||
displayList = cur_geo_cmd_ptr(0x08);
|
scale[0] = cur_geo_cmd_u32(0x04) / 65536.0f;
|
||||||
drawingLayer = params & 0x0F;
|
scale[1] = cur_geo_cmd_u32(0x08) / 65536.0f;
|
||||||
gGeoLayoutCommand += 4 << CMD_SIZE_SHIFT;
|
scale[2] = cur_geo_cmd_u32(0x0C) / 65536.0f;
|
||||||
|
gGeoLayoutCommand += 0x10 << CMD_SIZE_SHIFT;
|
||||||
|
} else {
|
||||||
|
scale[0] = cur_geo_cmd_u32(0x04) / 65536.0f;
|
||||||
|
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
graphNode = init_graph_node_scale(gGraphNodePool, NULL, drawingLayer, displayList, scale);
|
if (params & 0x80) {
|
||||||
|
displayList = cur_geo_cmd_ptr(0x00);
|
||||||
|
drawingLayer = params & 0x0F;
|
||||||
|
gGeoLayoutCommand += 0x04 << CMD_SIZE_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
register_scene_graph_node(&graphNode->node);
|
struct GraphNode *graphNode = (
|
||||||
|
isScaleXYZ ?
|
||||||
|
(struct GraphNode *) init_graph_node_scale_xyz(gGraphNodePool, NULL, drawingLayer, displayList, scale) :
|
||||||
|
(struct GraphNode *) init_graph_node_scale(gGraphNodePool, NULL, drawingLayer, displayList, scale[0])
|
||||||
|
);
|
||||||
|
|
||||||
gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT;
|
register_scene_graph_node(graphNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x1E: No operation
|
// 0x1E: No operation
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,26 @@ struct GraphNodeScale *init_graph_node_scale(struct DynamicPool *pool,
|
||||||
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_SCALE);
|
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_SCALE);
|
||||||
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||||
graphNode->scale = scale;
|
graphNode->scale = scale;
|
||||||
graphNode->prevScale = scale;
|
graphNode->displayList = dynos_gfx_get_writable_display_list(displayList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return graphNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates and returns a newly created XYZ scaling node
|
||||||
|
*/
|
||||||
|
struct GraphNodeScaleXYZ *init_graph_node_scale_xyz(struct DynamicPool *pool,
|
||||||
|
struct GraphNodeScaleXYZ *graphNode, s32 drawingLayer,
|
||||||
|
void *displayList, Vec3f scale) {
|
||||||
|
if (pool != NULL) {
|
||||||
|
graphNode = dynamic_pool_alloc(pool, sizeof(struct GraphNodeScaleXYZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphNode != NULL) {
|
||||||
|
init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_SCALE_XYZ);
|
||||||
|
graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF);
|
||||||
|
vec3f_copy(graphNode->scale, scale);
|
||||||
graphNode->displayList = dynos_gfx_get_writable_display_list(displayList);
|
graphNode->displayList = dynos_gfx_get_writable_display_list(displayList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
#define GRAPH_NODE_TYPE_BILLBOARD 0x01A
|
#define GRAPH_NODE_TYPE_BILLBOARD 0x01A
|
||||||
#define GRAPH_NODE_TYPE_DISPLAY_LIST 0x01B
|
#define GRAPH_NODE_TYPE_DISPLAY_LIST 0x01B
|
||||||
#define GRAPH_NODE_TYPE_SCALE 0x01C
|
#define GRAPH_NODE_TYPE_SCALE 0x01C
|
||||||
|
#define GRAPH_NODE_TYPE_SCALE_XYZ 0x01D
|
||||||
#define GRAPH_NODE_TYPE_SHADOW 0x028
|
#define GRAPH_NODE_TYPE_SHADOW 0x028
|
||||||
#define GRAPH_NODE_TYPE_OBJECT_PARENT 0x029
|
#define GRAPH_NODE_TYPE_OBJECT_PARENT 0x029
|
||||||
#define GRAPH_NODE_TYPE_GENERATED_LIST (0x02A | GRAPH_NODE_TYPE_FUNCTIONAL)
|
#define GRAPH_NODE_TYPE_GENERATED_LIST (0x02A | GRAPH_NODE_TYPE_FUNCTIONAL)
|
||||||
|
|
@ -241,8 +242,6 @@ struct GraphNodeRotation
|
||||||
/*0x00*/ struct GraphNode node;
|
/*0x00*/ struct GraphNode node;
|
||||||
/*0x14*/ Gfx *displayList;
|
/*0x14*/ Gfx *displayList;
|
||||||
/*0x18*/ Vec3s rotation;
|
/*0x18*/ Vec3s rotation;
|
||||||
Vec3s prevRotation;
|
|
||||||
u32 prevTimestamp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** GraphNode part that transforms itself and its children based on animation
|
/** GraphNode part that transforms itself and its children based on animation
|
||||||
|
|
@ -293,7 +292,16 @@ struct GraphNodeScale
|
||||||
/*0x00*/ struct GraphNode node;
|
/*0x00*/ struct GraphNode node;
|
||||||
/*0x14*/ Gfx *displayList;
|
/*0x14*/ Gfx *displayList;
|
||||||
/*0x18*/ f32 scale;
|
/*0x18*/ f32 scale;
|
||||||
/*????*/ f32 prevScale;
|
};
|
||||||
|
|
||||||
|
/** GraphNodeScale but on X, Y and Z independently.
|
||||||
|
* Must be another graph node type for retro-compatibility.
|
||||||
|
*/
|
||||||
|
struct GraphNodeScaleXYZ
|
||||||
|
{
|
||||||
|
/*0x00*/ struct GraphNode node;
|
||||||
|
/*0x14*/ Gfx *displayList;
|
||||||
|
/*0x18*/ Vec3f scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** GraphNode that draws a shadow under an object.
|
/** GraphNode that draws a shadow under an object.
|
||||||
|
|
@ -403,6 +411,8 @@ struct GraphNodeRotation *init_graph_node_rotation(struct DynamicPool *pool, str
|
||||||
s32 drawingLayer, void *displayList, Vec3s rotation);
|
s32 drawingLayer, void *displayList, Vec3s rotation);
|
||||||
struct GraphNodeScale *init_graph_node_scale(struct DynamicPool *pool, struct GraphNodeScale *graphNode,
|
struct GraphNodeScale *init_graph_node_scale(struct DynamicPool *pool, struct GraphNodeScale *graphNode,
|
||||||
s32 drawingLayer, void *displayList, f32 scale);
|
s32 drawingLayer, void *displayList, f32 scale);
|
||||||
|
struct GraphNodeScaleXYZ *init_graph_node_scale_xyz(struct DynamicPool *pool, struct GraphNodeScaleXYZ *graphNode,
|
||||||
|
s32 drawingLayer, void *displayList, Vec3f scale);
|
||||||
struct GraphNodeObject *init_graph_node_object(struct DynamicPool *pool, struct GraphNodeObject *graphNode,
|
struct GraphNodeObject *init_graph_node_object(struct DynamicPool *pool, struct GraphNodeObject *graphNode,
|
||||||
struct GraphNode *sharedChild, Vec3f pos, Vec3s angle, Vec3f scale);
|
struct GraphNode *sharedChild, Vec3f pos, Vec3s angle, Vec3f scale);
|
||||||
struct GraphNodeCullingRadius *init_graph_node_culling_radius(struct DynamicPool *pool, struct GraphNodeCullingRadius *graphNode, s16 radius);
|
struct GraphNodeCullingRadius *init_graph_node_culling_radius(struct DynamicPool *pool, struct GraphNodeCullingRadius *graphNode, s16 radius);
|
||||||
|
|
|
||||||
|
|
@ -471,8 +471,8 @@ void alloc_surface_pools(void) {
|
||||||
clear_static_surfaces();
|
clear_static_surfaces();
|
||||||
clear_dynamic_surfaces();
|
clear_dynamic_surfaces();
|
||||||
|
|
||||||
sSurfaceNodePool = growing_array_init(sSurfaceNodePool, 0x1000);
|
sSurfaceNodePool = growing_array_init(sSurfaceNodePool, 0x1000, malloc, free);
|
||||||
sSurfacePool = growing_array_init(sSurfacePool, 0x400);
|
sSurfacePool = growing_array_init(sSurfacePool, 0x400, malloc, smlua_free_surface);
|
||||||
|
|
||||||
gEnvironmentRegions = NULL;
|
gEnvironmentRegions = NULL;
|
||||||
gSurfaceNodesAllocated = 0;
|
gSurfaceNodesAllocated = 0;
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,7 @@ void clear_areas(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
le_clear();
|
le_clear();
|
||||||
|
geo_clear_interp_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_area_graph_nodes(void) {
|
void clear_area_graph_nodes(void) {
|
||||||
|
|
@ -311,6 +312,7 @@ void unload_area(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
le_clear();
|
le_clear();
|
||||||
|
geo_clear_interp_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_mario_area(void) {
|
void load_mario_area(void) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
#include "engine/graph_node.h"
|
#include "engine/graph_node.h"
|
||||||
|
#include "rendering_graph_node.h"
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
#include "save_file.h"
|
#include "save_file.h"
|
||||||
#include "sound_init.h"
|
#include "sound_init.h"
|
||||||
|
|
@ -1749,6 +1750,7 @@ s32 update_level(void) {
|
||||||
|
|
||||||
s32 init_level(void) {
|
s32 init_level(void) {
|
||||||
sync_objects_clear();
|
sync_objects_clear();
|
||||||
|
geo_clear_interp_data();
|
||||||
reset_dialog_render_state();
|
reset_dialog_render_state();
|
||||||
|
|
||||||
s32 val4 = 0;
|
s32 val4 = 0;
|
||||||
|
|
|
||||||
|
|
@ -460,11 +460,6 @@ Gfx* geo_mario_tilt_torso(s32 callContext, struct GraphNode* node, Mat4* mtx) {
|
||||||
rotNode->rotation[0] = bodyState->torsoAngle[1] * character->torsoRotMult;
|
rotNode->rotation[0] = bodyState->torsoAngle[1] * character->torsoRotMult;
|
||||||
rotNode->rotation[1] = bodyState->torsoAngle[2] * character->torsoRotMult;
|
rotNode->rotation[1] = bodyState->torsoAngle[2] * character->torsoRotMult;
|
||||||
rotNode->rotation[2] = bodyState->torsoAngle[0] * character->torsoRotMult;
|
rotNode->rotation[2] = bodyState->torsoAngle[0] * character->torsoRotMult;
|
||||||
if (plrIdx != 0) {
|
|
||||||
// only interpolate angles for the local player
|
|
||||||
vec3s_copy(rotNode->prevRotation, rotNode->rotation);
|
|
||||||
rotNode->prevTimestamp = gGlobalTimer;
|
|
||||||
}
|
|
||||||
// update torso position in bodyState
|
// update torso position in bodyState
|
||||||
get_pos_from_transform_mtx(bodyState->torsoPos, *curTransform, *gCurGraphNodeCamera->matrixPtr);
|
get_pos_from_transform_mtx(bodyState->torsoPos, *curTransform, *gCurGraphNodeCamera->matrixPtr);
|
||||||
bodyState->updateTorsoTime = gGlobalTimer;
|
bodyState->updateTorsoTime = gGlobalTimer;
|
||||||
|
|
@ -502,12 +497,6 @@ Gfx* geo_mario_head_rotation(s32 callContext, struct GraphNode* node, Mat4* c) {
|
||||||
vec3s_set(rotNode->rotation, 0, 0, 0);
|
vec3s_set(rotNode->rotation, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plrIdx != 0) {
|
|
||||||
// only interpolate angles for the local player
|
|
||||||
vec3s_copy(rotNode->prevRotation, rotNode->rotation);
|
|
||||||
rotNode->prevTimestamp = gGlobalTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update head position in bodyState
|
// update head position in bodyState
|
||||||
get_pos_from_transform_mtx(bodyState->headPos,
|
get_pos_from_transform_mtx(bodyState->headPos,
|
||||||
*c,
|
*c,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "pc/debuglog.h"
|
#include "pc/debuglog.h"
|
||||||
#include "pc/lua/smlua.h"
|
|
||||||
|
|
||||||
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
|
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
|
||||||
|
|
||||||
|
|
@ -186,12 +185,14 @@ void growing_pool_free_pool(struct GrowingPool *pool) {
|
||||||
// growing array //
|
// growing array //
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity) {
|
struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free) {
|
||||||
growing_array_free(&array);
|
growing_array_free(&array);
|
||||||
array = calloc(1, sizeof(struct GrowingArray));
|
array = calloc(1, sizeof(struct GrowingArray));
|
||||||
array->buffer = calloc(capacity, sizeof(void *));
|
array->buffer = calloc(capacity, sizeof(void *));
|
||||||
array->capacity = capacity;
|
array->capacity = capacity;
|
||||||
array->count = 0;
|
array->count = 0;
|
||||||
|
array->alloc = alloc;
|
||||||
|
array->free = free;
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,7 +212,7 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) {
|
||||||
// Alloc element if needed
|
// Alloc element if needed
|
||||||
void **elem = &array->buffer[array->count++];
|
void **elem = &array->buffer[array->count++];
|
||||||
if (!*elem) {
|
if (!*elem) {
|
||||||
*elem = malloc(size);
|
*elem = array->alloc(size);
|
||||||
}
|
}
|
||||||
memset(*elem, 0, size);
|
memset(*elem, 0, size);
|
||||||
return *elem;
|
return *elem;
|
||||||
|
|
@ -223,7 +224,7 @@ void growing_array_free(struct GrowingArray **array) {
|
||||||
if (*array) {
|
if (*array) {
|
||||||
for (u32 i = 0; i != (*array)->capacity; ++i) {
|
for (u32 i = 0; i != (*array)->capacity; ++i) {
|
||||||
if ((*array)->buffer[i]) {
|
if ((*array)->buffer[i]) {
|
||||||
smlua_free((*array)->buffer[i]);
|
(*array)->free((*array)->buffer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free((*array)->buffer);
|
free((*array)->buffer);
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,16 @@ struct GrowingPoolNode
|
||||||
struct GrowingPoolNode* prev;
|
struct GrowingPoolNode* prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef void *(*GrowingArrayAllocFunc)(size_t);
|
||||||
|
typedef void (*GrowingArrayFreeFunc)(void *);
|
||||||
|
|
||||||
struct GrowingArray
|
struct GrowingArray
|
||||||
{
|
{
|
||||||
void **buffer;
|
void **buffer;
|
||||||
u32 count;
|
u32 count;
|
||||||
u32 capacity;
|
u32 capacity;
|
||||||
|
GrowingArrayAllocFunc alloc;
|
||||||
|
GrowingArrayFreeFunc free;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MarioAnimation;
|
struct MarioAnimation;
|
||||||
|
|
@ -70,7 +75,7 @@ struct GrowingPool* growing_pool_init(struct GrowingPool* pool, u32 nodeSize);
|
||||||
void* growing_pool_alloc(struct GrowingPool *pool, u32 size);
|
void* growing_pool_alloc(struct GrowingPool *pool, u32 size);
|
||||||
void growing_pool_free_pool(struct GrowingPool *pool);
|
void growing_pool_free_pool(struct GrowingPool *pool);
|
||||||
|
|
||||||
struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity);
|
struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free);
|
||||||
void *growing_array_alloc(struct GrowingArray *array, u32 size);
|
void *growing_array_alloc(struct GrowingArray *array, u32 size);
|
||||||
void growing_array_free(struct GrowingArray **array);
|
void growing_array_free(struct GrowingArray **array);
|
||||||
void growing_array_debug_print(struct GrowingArray *array, const char *name, s32 x, s32 y);
|
void growing_array_debug_print(struct GrowingArray *array, const char *name, s32 x, s32 y);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "obj_behaviors.h"
|
#include "obj_behaviors.h"
|
||||||
#include "platform_displacement.h"
|
#include "platform_displacement.h"
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
|
#include "rendering_graph_node.h"
|
||||||
#include "spawn_object.h"
|
#include "spawn_object.h"
|
||||||
#include "first_person_cam.h"
|
#include "first_person_cam.h"
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
|
|
@ -624,6 +625,7 @@ void clear_objects(void) {
|
||||||
gObjectLists = gObjectListArray;
|
gObjectLists = gObjectListArray;
|
||||||
|
|
||||||
clear_dynamic_surfaces();
|
clear_dynamic_surfaces();
|
||||||
|
geo_clear_interp_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
#include "engine/math_util.h"
|
#include "engine/math_util.h"
|
||||||
#include "engine/lighting_engine.h"
|
#include "engine/lighting_engine.h"
|
||||||
|
#include "data/dynos_cmap.cpp.h"
|
||||||
#include "game_init.h"
|
#include "game_init.h"
|
||||||
#include "gfx_dimensions.h"
|
#include "gfx_dimensions.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
@ -183,28 +184,27 @@ static Gfx* sViewportClipPos = NULL;
|
||||||
static Vp sViewportPrev = { 0 };
|
static Vp sViewportPrev = { 0 };
|
||||||
static Vp sViewportInterp = { 0 };
|
static Vp sViewportInterp = { 0 };
|
||||||
|
|
||||||
static struct GraphNodeBackground* sBackgroundNode = NULL;
|
|
||||||
Gfx* gBackgroundSkyboxGfx = NULL;
|
Gfx* gBackgroundSkyboxGfx = NULL;
|
||||||
Vtx* gBackgroundSkyboxVerts[SKYBOX_TILES_Y][SKYBOX_TILES_X] = { 0 };
|
Vtx* gBackgroundSkyboxVerts[SKYBOX_TILES_Y][SKYBOX_TILES_X] = { 0 };
|
||||||
Mtx* gBackgroundSkyboxMtx = NULL;
|
Mtx* gBackgroundSkyboxMtx = NULL;
|
||||||
struct GraphNodeRoot* sBackgroundNodeRoot = NULL;
|
|
||||||
|
|
||||||
#define MAX_SHADOW_NODES 128
|
static struct GraphNodeBackground* sBackgroundNode = NULL;
|
||||||
struct ShadowInterp sShadowInterp[MAX_SHADOW_NODES] = { 0 };
|
static struct GraphNodeRoot* sBackgroundNodeRoot = NULL;
|
||||||
|
static struct GraphNodeCamera* sCameraNode = NULL;
|
||||||
|
|
||||||
|
static struct GrowingArray* sShadowInterp = NULL;
|
||||||
struct ShadowInterp* gShadowInterpCurrent = NULL;
|
struct ShadowInterp* gShadowInterpCurrent = NULL;
|
||||||
static u8 sShadowInterpCount = 0;
|
|
||||||
|
|
||||||
static struct GraphNodeCamera * sCameraNode = NULL;
|
struct MtxInterp {
|
||||||
|
|
||||||
struct {
|
|
||||||
Gfx *pos;
|
Gfx *pos;
|
||||||
Mtx *mtx;
|
Mtx *mtx;
|
||||||
Mtx *mtxPrev;
|
Mtx *mtxPrev;
|
||||||
void *displayList;
|
void *displayList;
|
||||||
Mtx interp;
|
Mtx interp;
|
||||||
u8 usingCamSpace;
|
u8 usingCamSpace;
|
||||||
} gMtxTbl[6400];
|
};
|
||||||
s32 gMtxTblSize = 0;
|
|
||||||
|
static struct GrowingArray* sMtxTbl = NULL;
|
||||||
|
|
||||||
struct Object* gCurGraphNodeProcessingObject = NULL;
|
struct Object* gCurGraphNodeProcessingObject = NULL;
|
||||||
struct MarioState* gCurGraphNodeMarioState = NULL;
|
struct MarioState* gCurGraphNodeMarioState = NULL;
|
||||||
|
|
@ -213,8 +213,36 @@ f32 gOverrideFOV = 0;
|
||||||
f32 gOverrideNear = 0;
|
f32 gOverrideNear = 0;
|
||||||
f32 gOverrideFar = 0;
|
f32 gOverrideFar = 0;
|
||||||
|
|
||||||
|
static void init_mtx(void) {
|
||||||
|
|
||||||
|
// matrices
|
||||||
|
if (!sMtxTbl) {
|
||||||
|
sMtxTbl = growing_array_init(NULL, 1024, malloc, free);
|
||||||
|
if (!sMtxTbl) {
|
||||||
|
sys_fatal("Cannot allocate matrix buffer for interpolation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sMtxTbl->count = 0;
|
||||||
|
|
||||||
|
// shadows
|
||||||
|
if (!sShadowInterp) {
|
||||||
|
sShadowInterp = growing_array_init(NULL, 32, malloc, free);
|
||||||
|
if (!sShadowInterp) {
|
||||||
|
sys_fatal("Cannot allocate shadow buffer for interpolation");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sShadowInterp->count = 0;
|
||||||
|
gShadowInterpCurrent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_mtx(void) {
|
||||||
|
growing_array_free(&sMtxTbl);
|
||||||
|
growing_array_free(&sShadowInterp);
|
||||||
|
init_mtx();
|
||||||
|
}
|
||||||
|
|
||||||
void patch_mtx_before(void) {
|
void patch_mtx_before(void) {
|
||||||
gMtxTblSize = 0;
|
init_mtx();
|
||||||
|
|
||||||
if (sPerspectiveNode != NULL) {
|
if (sPerspectiveNode != NULL) {
|
||||||
sPerspectiveNode->prevFov = sPerspectiveNode->fov;
|
sPerspectiveNode->prevFov = sPerspectiveNode->fov;
|
||||||
|
|
@ -235,8 +263,6 @@ void patch_mtx_before(void) {
|
||||||
sBackgroundNode = NULL;
|
sBackgroundNode = NULL;
|
||||||
gBackgroundSkyboxGfx = NULL;
|
gBackgroundSkyboxGfx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sShadowInterpCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void patch_mtx_interpolated(f32 delta) {
|
void patch_mtx_interpolated(f32 delta) {
|
||||||
|
|
@ -285,8 +311,8 @@ void patch_mtx_interpolated(f32 delta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GraphNodeObject* savedObj = gCurGraphNodeObject;
|
struct GraphNodeObject* savedObj = gCurGraphNodeObject;
|
||||||
for (s32 i = 0; i < sShadowInterpCount; i++) {
|
for (u32 i = 0; i < sShadowInterp->count; i++) {
|
||||||
struct ShadowInterp* interp = &sShadowInterp[i];
|
struct ShadowInterp* interp = sShadowInterp->buffer[i];
|
||||||
if (!interp->gfx) { continue; }
|
if (!interp->gfx) { continue; }
|
||||||
gShadowInterpCurrent = interp;
|
gShadowInterpCurrent = interp;
|
||||||
Vec3f posInterp;
|
Vec3f posInterp;
|
||||||
|
|
@ -304,7 +330,7 @@ void patch_mtx_interpolated(f32 delta) {
|
||||||
// technically this is improper use of mtxf functions, but coop doesn't target N64
|
// technically this is improper use of mtxf functions, but coop doesn't target N64
|
||||||
Mtx camTranfInv, prevCamTranfInv;
|
Mtx camTranfInv, prevCamTranfInv;
|
||||||
Mtx camInterp;
|
Mtx camInterp;
|
||||||
bool translateCamSpace = (gMtxTblSize > 0) && sCameraNode && (sCameraNode->matrixPtr != NULL) && (sCameraNode->matrixPtrPrev != NULL);
|
bool translateCamSpace = (sMtxTbl->count > 0) && sCameraNode && (sCameraNode->matrixPtr != NULL) && (sCameraNode->matrixPtrPrev != NULL);
|
||||||
if (translateCamSpace) {
|
if (translateCamSpace) {
|
||||||
// compute inverse camera matrix to transform out of camera space later
|
// compute inverse camera matrix to transform out of camera space later
|
||||||
mtxf_inverse(camTranfInv.m, *sCameraNode->matrixPtr);
|
mtxf_inverse(camTranfInv.m, *sCameraNode->matrixPtr);
|
||||||
|
|
@ -318,12 +344,13 @@ void patch_mtx_interpolated(f32 delta) {
|
||||||
mtxf_to_mtx(&camInterp, camInterp.m);
|
mtxf_to_mtx(&camInterp, camInterp.m);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s32 i = 0; i < gMtxTblSize; i++) {
|
for (u32 i = 0; i < sMtxTbl->count; i++) {
|
||||||
Gfx *pos = gMtxTbl[i].pos;
|
struct MtxInterp *interp = sMtxTbl->buffer[i];
|
||||||
Mtx *srcMtx = gMtxTbl[i].mtx;
|
Gfx *pos = interp->pos;
|
||||||
Mtx *srcMtxPrev = gMtxTbl[i].mtxPrev;
|
Mtx *srcMtx = interp->mtx;
|
||||||
|
Mtx *srcMtxPrev = interp->mtxPrev;
|
||||||
|
|
||||||
if (gMtxTbl[i].usingCamSpace && translateCamSpace) {
|
if (interp->usingCamSpace && translateCamSpace) {
|
||||||
// transform out of camera space so the matrix can interp in world space
|
// transform out of camera space so the matrix can interp in world space
|
||||||
Mtx bufMtx, bufMtxPrev;
|
Mtx bufMtx, bufMtxPrev;
|
||||||
mtxf_copy(bufMtx.m, srcMtx->m);
|
mtxf_copy(bufMtx.m, srcMtx->m);
|
||||||
|
|
@ -333,18 +360,96 @@ void patch_mtx_interpolated(f32 delta) {
|
||||||
srcMtx = &bufMtx;
|
srcMtx = &bufMtx;
|
||||||
srcMtxPrev = &bufMtxPrev;
|
srcMtxPrev = &bufMtxPrev;
|
||||||
}
|
}
|
||||||
delta_interpolate_mtx(&gMtxTbl[i].interp, srcMtxPrev, srcMtx, delta);
|
delta_interpolate_mtx(&interp->interp, srcMtxPrev, srcMtx, delta);
|
||||||
if (gMtxTbl[i].usingCamSpace) {
|
if (interp->usingCamSpace) {
|
||||||
// transform back to camera space, respecting camera interpolation
|
// transform back to camera space, respecting camera interpolation
|
||||||
mtxf_mul(gMtxTbl[i].interp.m, gMtxTbl[i].interp.m, camInterp.m);
|
mtxf_mul(interp->interp.m, interp->interp.m, camInterp.m);
|
||||||
}
|
}
|
||||||
gSPMatrix(pos++, VIRTUAL_TO_PHYSICAL(&gMtxTbl[i].interp),
|
gSPMatrix(pos++, VIRTUAL_TO_PHYSICAL(&interp->interp),
|
||||||
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
gCamSkipInterp = 0;
|
gCamSkipInterp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Graph node interpolation
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct GraphNodeInterpData {
|
||||||
|
Vec3s translation;
|
||||||
|
Vec3s rotation;
|
||||||
|
Vec3f scale;
|
||||||
|
u32 timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *sGraphNodeInterpDataMap = NULL;
|
||||||
|
|
||||||
|
static struct GraphNodeInterpData *geo_get_interp_data(void *node, struct GraphNodeObject *obj) {
|
||||||
|
|
||||||
|
// Map for nodes
|
||||||
|
if (!sGraphNodeInterpDataMap) {
|
||||||
|
sGraphNodeInterpDataMap = hmap_create(true);
|
||||||
|
if (!sGraphNodeInterpDataMap) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map for objects
|
||||||
|
void *nodeInterpData = hmap_get(sGraphNodeInterpDataMap, (int64_t) node);
|
||||||
|
if (!nodeInterpData) {
|
||||||
|
nodeInterpData = hmap_create(true);
|
||||||
|
if (!nodeInterpData) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hmap_put(sGraphNodeInterpDataMap, (int64_t) node, nodeInterpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node/object interp data
|
||||||
|
struct GraphNodeInterpData *interp = hmap_get(nodeInterpData, (int64_t) obj);
|
||||||
|
if (!interp) {
|
||||||
|
interp = calloc(1, sizeof(struct GraphNodeInterpData));
|
||||||
|
if (!interp) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hmap_put(nodeInterpData, (int64_t) obj, interp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return interp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void geo_init_or_update_interp_data(struct GraphNodeInterpData *interp, Vec3s translation, Vec3s rotation, Vec3f scale, bool update) {
|
||||||
|
if (interp && (update || interp->timestamp < gGlobalTimer - 1)) {
|
||||||
|
if (translation) { vec3s_copy(interp->translation, translation); }
|
||||||
|
if (rotation) { vec3s_copy(interp->rotation, rotation); }
|
||||||
|
if (scale) { vec3f_copy(interp->scale, scale); }
|
||||||
|
interp->timestamp = gGlobalTimer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool geo_should_interpolate(struct GraphNodeInterpData *interp) {
|
||||||
|
return interp != NULL && interp->timestamp == gGlobalTimer - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void geo_clear_interp_data() {
|
||||||
|
for (void *nodeInterpData = hmap_begin(sGraphNodeInterpDataMap); nodeInterpData; nodeInterpData = hmap_next(sGraphNodeInterpDataMap)) {
|
||||||
|
for (struct GraphNodeInterpData *interp = hmap_begin(nodeInterpData); interp; interp = hmap_next(nodeInterpData)) {
|
||||||
|
free(interp);
|
||||||
|
}
|
||||||
|
hmap_destroy(nodeInterpData);
|
||||||
|
}
|
||||||
|
hmap_destroy(sGraphNodeInterpDataMap);
|
||||||
|
sGraphNodeInterpDataMap = NULL;
|
||||||
|
reset_mtx();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define geo_update_interpolation(translation, rotation, scale, ...) { \
|
||||||
|
struct GraphNodeInterpData *interp = geo_get_interp_data(node, gCurGraphNodeObject); \
|
||||||
|
geo_init_or_update_interp_data(interp, translation, rotation, scale, false); \
|
||||||
|
{ __VA_ARGS__; } \
|
||||||
|
geo_init_or_update_interp_data(interp, translation, rotation, scale, true); \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increments the matrix stack index and sets the matrixs at the new index.
|
* Increments the matrix stack index and sets the matrixs at the new index.
|
||||||
*/
|
*/
|
||||||
|
|
@ -397,13 +502,13 @@ static void geo_process_master_list_sub(struct GraphNodeMasterList *node) {
|
||||||
gDPSetRenderMode(gDisplayListHead++, modeList->modes[i], mode2List->modes[i]);
|
gDPSetRenderMode(gDisplayListHead++, modeList->modes[i], mode2List->modes[i]);
|
||||||
while (currList != NULL) {
|
while (currList != NULL) {
|
||||||
detect_and_skip_mtx_interpolation(&currList->transform, &currList->transformPrev);
|
detect_and_skip_mtx_interpolation(&currList->transform, &currList->transformPrev);
|
||||||
if ((u32) gMtxTblSize < sizeof(gMtxTbl) / sizeof(gMtxTbl[0])) {
|
|
||||||
gMtxTbl[gMtxTblSize].pos = gDisplayListHead;
|
struct MtxInterp *interp = growing_array_alloc(sMtxTbl, sizeof(struct MtxInterp));
|
||||||
gMtxTbl[gMtxTblSize].mtx = currList->transform;
|
interp->pos = gDisplayListHead;
|
||||||
gMtxTbl[gMtxTblSize].mtxPrev = currList->transformPrev;
|
interp->mtx = currList->transform;
|
||||||
gMtxTbl[gMtxTblSize].displayList = currList->displayList;
|
interp->mtxPrev = currList->transformPrev;
|
||||||
gMtxTbl[gMtxTblSize++].usingCamSpace = currList->usingCamSpace;
|
interp->displayList = currList->displayList;
|
||||||
}
|
interp->usingCamSpace = currList->usingCamSpace;
|
||||||
|
|
||||||
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transformPrev),
|
gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(currList->transformPrev),
|
||||||
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH);
|
||||||
|
|
@ -648,10 +753,19 @@ static void geo_process_translation_rotation(struct GraphNodeTranslationRotation
|
||||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
|
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB.
|
||||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||||
|
|
||||||
|
// current frame
|
||||||
vec3s_to_vec3f(translation, node->translation);
|
vec3s_to_vec3f(translation, node->translation);
|
||||||
mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation);
|
mtxf_rotate_zxy_and_translate(mtxf, translation, node->rotation);
|
||||||
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
|
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
|
||||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
|
|
||||||
|
// previous frame
|
||||||
|
geo_update_interpolation(node->translation, node->rotation, NULL,
|
||||||
|
if (geo_should_interpolate(interp)) {
|
||||||
|
vec3s_to_vec3f(translation, interp->translation);
|
||||||
|
mtxf_rotate_zxy_and_translate(mtxf, translation, interp->rotation);
|
||||||
|
}
|
||||||
|
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
|
||||||
|
);
|
||||||
|
|
||||||
// Increment the matrix stack, If we fail to do so. Just return.
|
// Increment the matrix stack, If we fail to do so. Just return.
|
||||||
if (!increment_mat_stack()) { return; }
|
if (!increment_mat_stack()) { return; }
|
||||||
|
|
@ -677,10 +791,19 @@ static void geo_process_translation(struct GraphNodeTranslation *node) {
|
||||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||||
|
|
||||||
|
// current frame
|
||||||
vec3s_to_vec3f(translation, node->translation);
|
vec3s_to_vec3f(translation, node->translation);
|
||||||
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
|
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
|
||||||
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
|
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
|
||||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
|
|
||||||
|
// previous frame
|
||||||
|
geo_update_interpolation(node->translation, NULL, NULL,
|
||||||
|
if (geo_should_interpolate(interp)) {
|
||||||
|
vec3s_to_vec3f(translation, interp->translation);
|
||||||
|
mtxf_rotate_zxy_and_translate(mtxf, translation, gVec3sZero);
|
||||||
|
}
|
||||||
|
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
|
||||||
|
);
|
||||||
|
|
||||||
// Increment the matrix stack, If we fail to do so. Just return.
|
// Increment the matrix stack, If we fail to do so. Just return.
|
||||||
if (!increment_mat_stack()) { return; }
|
if (!increment_mat_stack()) { return; }
|
||||||
|
|
@ -705,17 +828,17 @@ static void geo_process_rotation(struct GraphNodeRotation *node) {
|
||||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||||
|
|
||||||
|
// current frame
|
||||||
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
|
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
|
||||||
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
|
mtxf_mul(gMatStack[gMatStackIndex + 1], mtxf, gMatStack[gMatStackIndex]);
|
||||||
|
|
||||||
if (gGlobalTimer == node->prevTimestamp + 1) {
|
// previous frame
|
||||||
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->prevRotation);
|
geo_update_interpolation(NULL, node->rotation, NULL,
|
||||||
} else {
|
if (geo_should_interpolate(interp)) {
|
||||||
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, node->rotation);
|
mtxf_rotate_zxy_and_translate(mtxf, gVec3fZero, interp->rotation);
|
||||||
}
|
}
|
||||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
|
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], mtxf, gMatStackPrev[gMatStackIndex]);
|
||||||
vec3s_copy(node->prevRotation, node->rotation);
|
);
|
||||||
node->prevTimestamp = gGlobalTimer;
|
|
||||||
|
|
||||||
// Increment the matrix stack, If we fail to do so. Just return.
|
// Increment the matrix stack, If we fail to do so. Just return.
|
||||||
if (!increment_mat_stack()) { return; }
|
if (!increment_mat_stack()) { return; }
|
||||||
|
|
@ -741,17 +864,53 @@ static void geo_process_scale(struct GraphNodeScale *node) {
|
||||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||||
|
|
||||||
|
// current frame
|
||||||
vec3f_set(scaleVec, node->scale, node->scale, node->scale);
|
vec3f_set(scaleVec, node->scale, node->scale, node->scale);
|
||||||
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec);
|
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], scaleVec);
|
||||||
|
|
||||||
/* TODO: this fails because multiple player models reuse the same scalenode
|
// previous frame
|
||||||
vec3f_set(prevScaleVec, node->prevScale, node->prevScale, node->prevScale);
|
geo_update_interpolation(NULL, NULL, scaleVec,
|
||||||
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex], prevScaleVec);
|
vec3f_copy(prevScaleVec,
|
||||||
node->prevScale = node->scale;*/
|
geo_should_interpolate(interp) ?
|
||||||
|
interp->scale :
|
||||||
|
scaleVec
|
||||||
|
);
|
||||||
|
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex], prevScaleVec);
|
||||||
|
);
|
||||||
|
|
||||||
// just use the current scale for now
|
// Increment the matrix stack, If we fail to do so. Just return.
|
||||||
vec3f_set(prevScaleVec, node->scale, node->scale, node->scale);
|
if (!increment_mat_stack()) { return; }
|
||||||
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex], scaleVec);
|
|
||||||
|
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--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an XYZ scaling node. A transformation matrix based on the node's
|
||||||
|
* scale is created and pushed on both the float and fixed point matrix stacks.
|
||||||
|
* For the rest it acts as a normal display list node.
|
||||||
|
*/
|
||||||
|
static void geo_process_scale_xyz(struct GraphNodeScaleXYZ *node) {
|
||||||
|
|
||||||
|
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||||
|
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||||
|
|
||||||
|
// current frame
|
||||||
|
mtxf_scale_vec3f(gMatStack[gMatStackIndex + 1], gMatStack[gMatStackIndex], node->scale);
|
||||||
|
|
||||||
|
// previous frame
|
||||||
|
geo_update_interpolation(NULL, NULL, node->scale,
|
||||||
|
mtxf_scale_vec3f(gMatStackPrev[gMatStackIndex + 1], gMatStackPrev[gMatStackIndex],
|
||||||
|
geo_should_interpolate(interp) ?
|
||||||
|
interp->scale :
|
||||||
|
node->scale
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
// Increment the matrix stack, If we fail to do so. Just return.
|
// Increment the matrix stack, If we fail to do so. Just return.
|
||||||
if (!increment_mat_stack()) { return; }
|
if (!increment_mat_stack()) { return; }
|
||||||
|
|
@ -779,21 +938,28 @@ static void geo_process_billboard(struct GraphNodeBillboard *node) {
|
||||||
|
|
||||||
s16 nextMatStackIndex = gMatStackIndex + 1;
|
s16 nextMatStackIndex = gMatStackIndex + 1;
|
||||||
|
|
||||||
|
// current frame
|
||||||
vec3s_to_vec3f(translation, node->translation);
|
vec3s_to_vec3f(translation, node->translation);
|
||||||
mtxf_billboard(gMatStack[nextMatStackIndex], gMatStack[gMatStackIndex], translation,
|
mtxf_billboard(gMatStack[nextMatStackIndex], gMatStack[gMatStackIndex], translation, gCurGraphNodeCamera->roll);
|
||||||
gCurGraphNodeCamera->roll);
|
|
||||||
mtxf_billboard(gMatStackPrev[nextMatStackIndex], gMatStackPrev[gMatStackIndex], translation,
|
// previous frame
|
||||||
gCurGraphNodeCamera->roll);
|
geo_update_interpolation(node->translation, NULL, NULL,
|
||||||
|
if (geo_should_interpolate(interp)) {
|
||||||
|
vec3s_to_vec3f(translation, interp->translation);
|
||||||
|
}
|
||||||
|
mtxf_billboard(gMatStackPrev[nextMatStackIndex], gMatStackPrev[gMatStackIndex], translation, gCurGraphNodeCamera->roll);
|
||||||
|
);
|
||||||
|
|
||||||
if (gCurGraphNodeHeldObject != NULL) {
|
if (gCurGraphNodeHeldObject != NULL) {
|
||||||
mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex],
|
mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex],
|
||||||
gCurGraphNodeHeldObject->objNode->header.gfx.scale);
|
gCurGraphNodeHeldObject->objNode->header.gfx.scale);
|
||||||
mtxf_scale_vec3f(gMatStackPrev[nextMatStackIndex], gMatStackPrev[nextMatStackIndex],
|
mtxf_scale_vec3f(gMatStackPrev[nextMatStackIndex], gMatStackPrev[nextMatStackIndex],
|
||||||
gCurGraphNodeHeldObject->objNode->header.gfx.scale);
|
gCurGraphNodeHeldObject->objNode->header.gfx.prevScale);
|
||||||
} else if (gCurGraphNodeObject != NULL) {
|
} else if (gCurGraphNodeObject != NULL) {
|
||||||
mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex],
|
mtxf_scale_vec3f(gMatStack[nextMatStackIndex], gMatStack[nextMatStackIndex],
|
||||||
gCurGraphNodeObject->scale);
|
gCurGraphNodeObject->scale);
|
||||||
mtxf_scale_vec3f(gMatStackPrev[nextMatStackIndex], gMatStackPrev[nextMatStackIndex],
|
mtxf_scale_vec3f(gMatStackPrev[nextMatStackIndex], gMatStackPrev[nextMatStackIndex],
|
||||||
gCurGraphNodeObject->scale);
|
gCurGraphNodeObject->prevScale);
|
||||||
} else {
|
} else {
|
||||||
//LOG_ERROR("gCurGraphNodeObject and gCurGraphNodeHeldObject are both NULL!");
|
//LOG_ERROR("gCurGraphNodeObject and gCurGraphNodeHeldObject are both NULL!");
|
||||||
}
|
}
|
||||||
|
|
@ -938,8 +1104,6 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
||||||
Mat4 matrix;
|
Mat4 matrix;
|
||||||
Vec3s rotation;
|
Vec3s rotation;
|
||||||
Vec3f translation;
|
Vec3f translation;
|
||||||
Vec3s rotationPrev;
|
|
||||||
Vec3f translationPrev;
|
|
||||||
|
|
||||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||||
|
|
@ -947,20 +1111,25 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
||||||
u16 *animAttribute = gCurrAnimAttribute;
|
u16 *animAttribute = gCurrAnimAttribute;
|
||||||
u8 animType = gCurAnimType;
|
u8 animType = gCurAnimType;
|
||||||
|
|
||||||
|
// current frame
|
||||||
vec3s_copy(rotation, gVec3sZero);
|
vec3s_copy(rotation, gVec3sZero);
|
||||||
vec3f_set(translation, node->translation[0], node->translation[1], node->translation[2]);
|
vec3s_to_vec3f(translation, node->translation);
|
||||||
|
|
||||||
vec3s_copy(rotationPrev, rotation);
|
|
||||||
vec3f_copy(translationPrev, translation);
|
|
||||||
|
|
||||||
anim_process(translationPrev, rotationPrev, &animType, gPrevAnimFrame, &animAttribute);
|
|
||||||
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||||
|
|
||||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||||
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
|
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
|
||||||
|
|
||||||
mtxf_rotate_xyz_and_translate(matrix, translationPrev, rotationPrev);
|
// previous frame
|
||||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
|
geo_update_interpolation(node->translation, NULL, NULL,
|
||||||
|
vec3s_to_vec3f(translation,
|
||||||
|
geo_should_interpolate(interp) ?
|
||||||
|
interp->translation :
|
||||||
|
node->translation
|
||||||
|
);
|
||||||
|
vec3s_copy(rotation, gVec3sZero);
|
||||||
|
anim_process(translation, rotation, &animType, gPrevAnimFrame, &animAttribute);
|
||||||
|
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||||
|
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
|
||||||
|
);
|
||||||
|
|
||||||
// Increment the matrix stack, If we fail to do so. Just return.
|
// Increment the matrix stack, If we fail to do so. Just return.
|
||||||
if (!increment_mat_stack()) { return; }
|
if (!increment_mat_stack()) { return; }
|
||||||
|
|
@ -1058,18 +1227,25 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
|
||||||
shadowScale = node->shadowScale * gCurGraphNodeObject->scale[0];
|
shadowScale = node->shadowScale * gCurGraphNodeObject->scale[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 objScale = 1.0f;
|
Vec3f objScale = { 1, 1, 1 };
|
||||||
if (gCurAnimEnabled) {
|
if (gCurAnimEnabled) {
|
||||||
if (gCurAnimType == ANIM_TYPE_TRANSLATION
|
if (gCurAnimType == ANIM_TYPE_TRANSLATION
|
||||||
|| gCurAnimType == ANIM_TYPE_LATERAL_TRANSLATION) {
|
|| gCurAnimType == ANIM_TYPE_LATERAL_TRANSLATION) {
|
||||||
struct GraphNode *geo = node->node.children;
|
struct GraphNode *geo = node->node.children;
|
||||||
if (geo != NULL && geo->type == GRAPH_NODE_TYPE_SCALE) {
|
if (geo != NULL) {
|
||||||
objScale = ((struct GraphNodeScale *) geo)->scale;
|
switch (geo->type) {
|
||||||
|
case GRAPH_NODE_TYPE_SCALE:
|
||||||
|
vec3f_mul(objScale, ((struct GraphNodeScale *) geo)->scale);
|
||||||
|
break;
|
||||||
|
case GRAPH_NODE_TYPE_SCALE_XYZ:
|
||||||
|
vec3f_copy(objScale, ((struct GraphNodeScaleXYZ *) geo)->scale);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
animOffset[0] = retrieve_animation_value(gCurAnim, gCurrAnimFrame, &gCurrAnimAttribute) * gCurAnimTranslationMultiplier * objScale;
|
animOffset[0] = retrieve_animation_value(gCurAnim, gCurrAnimFrame, &gCurrAnimAttribute) * gCurAnimTranslationMultiplier * objScale[0];
|
||||||
animOffset[1] = 0.0f;
|
animOffset[1] = 0.0f;
|
||||||
gCurrAnimAttribute += 2;
|
gCurrAnimAttribute += 2;
|
||||||
animOffset[2] = retrieve_animation_value(gCurAnim, gCurrAnimFrame, &gCurrAnimAttribute) * gCurAnimTranslationMultiplier * objScale;
|
animOffset[2] = retrieve_animation_value(gCurAnim, gCurrAnimFrame, &gCurrAnimAttribute) * gCurAnimTranslationMultiplier * objScale[2];
|
||||||
gCurrAnimAttribute -= 6;
|
gCurrAnimAttribute -= 6;
|
||||||
|
|
||||||
// simple matrix rotation so the shadow offset rotates along with the object
|
// simple matrix rotation so the shadow offset rotates along with the object
|
||||||
|
|
@ -1103,18 +1279,14 @@ static void geo_process_shadow(struct GraphNodeShadow *node) {
|
||||||
gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer;
|
gCurGraphNodeObject->prevShadowPosTimestamp = gGlobalTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sShadowInterpCount < MAX_SHADOW_NODES) {
|
struct ShadowInterp* interp = growing_array_alloc(sShadowInterp, sizeof(struct ShadowInterp));
|
||||||
struct ShadowInterp* interp = &sShadowInterp[sShadowInterpCount++];
|
gShadowInterpCurrent = interp;
|
||||||
gShadowInterpCurrent = interp;
|
interp->gfx = NULL;
|
||||||
interp->gfx = NULL;
|
interp->node = node;
|
||||||
interp->node = node;
|
interp->shadowScale = shadowScale;
|
||||||
interp->shadowScale = shadowScale;
|
interp->obj = gCurGraphNodeObject;
|
||||||
interp->obj = gCurGraphNodeObject;
|
vec3f_copy(interp->shadowPos, gCurGraphNodeObject->shadowPos);
|
||||||
vec3f_copy(interp->shadowPos, gCurGraphNodeObject->shadowPos);
|
vec3f_copy(interp->shadowPosPrev, shadowPosPrev);
|
||||||
vec3f_copy(interp->shadowPosPrev, shadowPosPrev);
|
|
||||||
} else {
|
|
||||||
gShadowInterpCurrent = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1],
|
Gfx *shadowListPrev = create_shadow_below_xyz(shadowPosPrev[0], shadowPosPrev[1],
|
||||||
shadowPosPrev[2], shadowScale,
|
shadowPosPrev[2], shadowScale,
|
||||||
|
|
@ -1640,6 +1812,9 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
|
||||||
case GRAPH_NODE_TYPE_SCALE:
|
case GRAPH_NODE_TYPE_SCALE:
|
||||||
geo_process_scale((struct GraphNodeScale *) curGraphNode);
|
geo_process_scale((struct GraphNodeScale *) curGraphNode);
|
||||||
break;
|
break;
|
||||||
|
case GRAPH_NODE_TYPE_SCALE_XYZ:
|
||||||
|
geo_process_scale_xyz((struct GraphNodeScaleXYZ *) curGraphNode);
|
||||||
|
break;
|
||||||
case GRAPH_NODE_TYPE_SHADOW:
|
case GRAPH_NODE_TYPE_SHADOW:
|
||||||
geo_process_shadow((struct GraphNodeShadow *) curGraphNode);
|
geo_process_shadow((struct GraphNodeShadow *) curGraphNode);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1685,11 +1860,11 @@ static void geo_clear_interp_variables(void) {
|
||||||
gBackgroundSkyboxMtx = NULL;
|
gBackgroundSkyboxMtx = NULL;
|
||||||
sBackgroundNodeRoot = NULL;
|
sBackgroundNodeRoot = NULL;
|
||||||
|
|
||||||
|
sShadowInterp->count = 0;
|
||||||
gShadowInterpCurrent = NULL;
|
gShadowInterpCurrent = NULL;
|
||||||
sShadowInterpCount = 0;
|
|
||||||
|
|
||||||
|
sMtxTbl->count = 0;
|
||||||
sCameraNode = NULL;
|
sCameraNode = NULL;
|
||||||
gMtxTblSize = 0;
|
|
||||||
gCurGraphNodeProcessingObject = NULL;
|
gCurGraphNodeProcessingObject = NULL;
|
||||||
gCurGraphNodeMarioState = NULL;
|
gCurGraphNodeMarioState = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ extern f32 gOverrideFar;
|
||||||
|
|
||||||
void geo_process_node_and_siblings(struct GraphNode *firstNode);
|
void geo_process_node_and_siblings(struct GraphNode *firstNode);
|
||||||
void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor);
|
void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor);
|
||||||
|
void geo_clear_interp_data();
|
||||||
|
|
||||||
struct ShadowInterp {
|
struct ShadowInterp {
|
||||||
Gfx* gfx;
|
Gfx* gfx;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
DialogTable *gDialogTable = NULL;
|
DialogTable *gDialogTable = NULL;
|
||||||
|
|
||||||
void dialog_table_init(void) {
|
void dialog_table_init(void) {
|
||||||
gDialogTable = growing_array_init(gDialogTable, 256);
|
gDialogTable = growing_array_init(gDialogTable, 256, malloc, free);
|
||||||
|
|
||||||
for (u32 i = 0; i < DIALOG_COUNT; i++) {
|
for (u32 i = 0; i < DIALOG_COUNT; i++) {
|
||||||
const struct DialogEntry* dialogOrig = smlua_text_utils_dialog_get_unmodified(i);
|
const struct DialogEntry* dialogOrig = smlua_text_utils_dialog_get_unmodified(i);
|
||||||
|
|
|
||||||
|
|
@ -1248,23 +1248,27 @@ static struct LuaObjectField sGraphNodeRootFields[LUA_GRAPH_NODE_ROOT_FIELD_COUN
|
||||||
{ "y", LVT_S16, offsetof(struct GraphNodeRoot, y), false, LOT_NONE, 1, sizeof(s16) },
|
{ "y", LVT_S16, offsetof(struct GraphNodeRoot, y), false, LOT_NONE, 1, sizeof(s16) },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LUA_GRAPH_NODE_ROTATION_FIELD_COUNT 5
|
#define LUA_GRAPH_NODE_ROTATION_FIELD_COUNT 3
|
||||||
static struct LuaObjectField sGraphNodeRotationFields[LUA_GRAPH_NODE_ROTATION_FIELD_COUNT] = {
|
static struct LuaObjectField sGraphNodeRotationFields[LUA_GRAPH_NODE_ROTATION_FIELD_COUNT] = {
|
||||||
{ "displayList", LVT_COBJECT_P, offsetof(struct GraphNodeRotation, displayList), false, LOT_GFX, 1, sizeof(Gfx*) },
|
{ "displayList", LVT_COBJECT_P, offsetof(struct GraphNodeRotation, displayList), false, LOT_GFX, 1, sizeof(Gfx*) },
|
||||||
{ "node", LVT_COBJECT, offsetof(struct GraphNodeRotation, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
{ "node", LVT_COBJECT, offsetof(struct GraphNodeRotation, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
||||||
{ "prevRotation", LVT_COBJECT, offsetof(struct GraphNodeRotation, prevRotation), true, LOT_VEC3S, 1, sizeof(Vec3s) },
|
{ "rotation", LVT_COBJECT, offsetof(struct GraphNodeRotation, rotation), true, LOT_VEC3S, 1, sizeof(Vec3s) },
|
||||||
{ "prevTimestamp", LVT_U32, offsetof(struct GraphNodeRotation, prevTimestamp), false, LOT_NONE, 1, sizeof(u32) },
|
|
||||||
{ "rotation", LVT_COBJECT, offsetof(struct GraphNodeRotation, rotation), true, LOT_VEC3S, 1, sizeof(Vec3s) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LUA_GRAPH_NODE_SCALE_FIELD_COUNT 4
|
#define LUA_GRAPH_NODE_SCALE_FIELD_COUNT 3
|
||||||
static struct LuaObjectField sGraphNodeScaleFields[LUA_GRAPH_NODE_SCALE_FIELD_COUNT] = {
|
static struct LuaObjectField sGraphNodeScaleFields[LUA_GRAPH_NODE_SCALE_FIELD_COUNT] = {
|
||||||
{ "displayList", LVT_COBJECT_P, offsetof(struct GraphNodeScale, displayList), false, LOT_GFX, 1, sizeof(Gfx*) },
|
{ "displayList", LVT_COBJECT_P, offsetof(struct GraphNodeScale, displayList), false, LOT_GFX, 1, sizeof(Gfx*) },
|
||||||
{ "node", LVT_COBJECT, offsetof(struct GraphNodeScale, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
{ "node", LVT_COBJECT, offsetof(struct GraphNodeScale, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
||||||
{ "prevScale", LVT_F32, offsetof(struct GraphNodeScale, prevScale), false, LOT_NONE, 1, sizeof(f32) },
|
|
||||||
{ "scale", LVT_F32, offsetof(struct GraphNodeScale, scale), false, LOT_NONE, 1, sizeof(f32) },
|
{ "scale", LVT_F32, offsetof(struct GraphNodeScale, scale), false, LOT_NONE, 1, sizeof(f32) },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LUA_GRAPH_NODE_SCALE_XYZ_FIELD_COUNT 3
|
||||||
|
static struct LuaObjectField sGraphNodeScaleXYZFields[LUA_GRAPH_NODE_SCALE_XYZ_FIELD_COUNT] = {
|
||||||
|
{ "displayList", LVT_COBJECT_P, offsetof(struct GraphNodeScaleXYZ, displayList), false, LOT_GFX, 1, sizeof(Gfx*) },
|
||||||
|
{ "node", LVT_COBJECT, offsetof(struct GraphNodeScaleXYZ, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
||||||
|
{ "scale", LVT_COBJECT, offsetof(struct GraphNodeScaleXYZ, scale), true, LOT_VEC3F, 1, sizeof(Vec3f) },
|
||||||
|
};
|
||||||
|
|
||||||
#define LUA_GRAPH_NODE_SHADOW_FIELD_COUNT 4
|
#define LUA_GRAPH_NODE_SHADOW_FIELD_COUNT 4
|
||||||
static struct LuaObjectField sGraphNodeShadowFields[LUA_GRAPH_NODE_SHADOW_FIELD_COUNT] = {
|
static struct LuaObjectField sGraphNodeShadowFields[LUA_GRAPH_NODE_SHADOW_FIELD_COUNT] = {
|
||||||
{ "node", LVT_COBJECT, offsetof(struct GraphNodeShadow, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
{ "node", LVT_COBJECT, offsetof(struct GraphNodeShadow, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) },
|
||||||
|
|
@ -2924,6 +2928,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
|
||||||
{ LOT_GRAPHNODEROOT, sGraphNodeRootFields, LUA_GRAPH_NODE_ROOT_FIELD_COUNT },
|
{ LOT_GRAPHNODEROOT, sGraphNodeRootFields, LUA_GRAPH_NODE_ROOT_FIELD_COUNT },
|
||||||
{ LOT_GRAPHNODEROTATION, sGraphNodeRotationFields, LUA_GRAPH_NODE_ROTATION_FIELD_COUNT },
|
{ LOT_GRAPHNODEROTATION, sGraphNodeRotationFields, LUA_GRAPH_NODE_ROTATION_FIELD_COUNT },
|
||||||
{ LOT_GRAPHNODESCALE, sGraphNodeScaleFields, LUA_GRAPH_NODE_SCALE_FIELD_COUNT },
|
{ LOT_GRAPHNODESCALE, sGraphNodeScaleFields, LUA_GRAPH_NODE_SCALE_FIELD_COUNT },
|
||||||
|
{ LOT_GRAPHNODESCALEXYZ, sGraphNodeScaleXYZFields, LUA_GRAPH_NODE_SCALE_XYZ_FIELD_COUNT },
|
||||||
{ LOT_GRAPHNODESHADOW, sGraphNodeShadowFields, LUA_GRAPH_NODE_SHADOW_FIELD_COUNT },
|
{ LOT_GRAPHNODESHADOW, sGraphNodeShadowFields, LUA_GRAPH_NODE_SHADOW_FIELD_COUNT },
|
||||||
{ LOT_GRAPHNODESTART, sGraphNodeStartFields, LUA_GRAPH_NODE_START_FIELD_COUNT },
|
{ LOT_GRAPHNODESTART, sGraphNodeStartFields, LUA_GRAPH_NODE_START_FIELD_COUNT },
|
||||||
{ LOT_GRAPHNODESWITCHCASE, sGraphNodeSwitchCaseFields, LUA_GRAPH_NODE_SWITCH_CASE_FIELD_COUNT },
|
{ LOT_GRAPHNODESWITCHCASE, sGraphNodeSwitchCaseFields, LUA_GRAPH_NODE_SWITCH_CASE_FIELD_COUNT },
|
||||||
|
|
@ -3052,6 +3057,7 @@ const char *sLuaLotNames[] = {
|
||||||
[LOT_GRAPHNODEROOT] = "GraphNodeRoot",
|
[LOT_GRAPHNODEROOT] = "GraphNodeRoot",
|
||||||
[LOT_GRAPHNODEROTATION] = "GraphNodeRotation",
|
[LOT_GRAPHNODEROTATION] = "GraphNodeRotation",
|
||||||
[LOT_GRAPHNODESCALE] = "GraphNodeScale",
|
[LOT_GRAPHNODESCALE] = "GraphNodeScale",
|
||||||
|
[LOT_GRAPHNODESCALEXYZ] = "GraphNodeScaleXYZ",
|
||||||
[LOT_GRAPHNODESHADOW] = "GraphNodeShadow",
|
[LOT_GRAPHNODESHADOW] = "GraphNodeShadow",
|
||||||
[LOT_GRAPHNODESTART] = "GraphNodeStart",
|
[LOT_GRAPHNODESTART] = "GraphNodeStart",
|
||||||
[LOT_GRAPHNODESWITCHCASE] = "GraphNodeSwitchCase",
|
[LOT_GRAPHNODESWITCHCASE] = "GraphNodeSwitchCase",
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ enum LuaObjectAutogenType {
|
||||||
LOT_GRAPHNODEROOT,
|
LOT_GRAPHNODEROOT,
|
||||||
LOT_GRAPHNODEROTATION,
|
LOT_GRAPHNODEROTATION,
|
||||||
LOT_GRAPHNODESCALE,
|
LOT_GRAPHNODESCALE,
|
||||||
|
LOT_GRAPHNODESCALEXYZ,
|
||||||
LOT_GRAPHNODESHADOW,
|
LOT_GRAPHNODESHADOW,
|
||||||
LOT_GRAPHNODESTART,
|
LOT_GRAPHNODESTART,
|
||||||
LOT_GRAPHNODESWITCHCASE,
|
LOT_GRAPHNODESWITCHCASE,
|
||||||
|
|
|
||||||
|
|
@ -1561,6 +1561,7 @@ char gSmluaConstants[] = ""
|
||||||
"GRAPH_NODE_TYPE_BILLBOARD=0x01A\n"
|
"GRAPH_NODE_TYPE_BILLBOARD=0x01A\n"
|
||||||
"GRAPH_NODE_TYPE_DISPLAY_LIST=0x01B\n"
|
"GRAPH_NODE_TYPE_DISPLAY_LIST=0x01B\n"
|
||||||
"GRAPH_NODE_TYPE_SCALE=0x01C\n"
|
"GRAPH_NODE_TYPE_SCALE=0x01C\n"
|
||||||
|
"GRAPH_NODE_TYPE_SCALE_XYZ=0x01D\n"
|
||||||
"GRAPH_NODE_TYPE_SHADOW=0x028\n"
|
"GRAPH_NODE_TYPE_SHADOW=0x028\n"
|
||||||
"GRAPH_NODE_TYPE_OBJECT_PARENT=0x029\n"
|
"GRAPH_NODE_TYPE_OBJECT_PARENT=0x029\n"
|
||||||
"GRAPH_NODE_TYPE_GENERATED_LIST=(0x02A | GRAPH_NODE_TYPE_FUNCTIONAL)\n"
|
"GRAPH_NODE_TYPE_GENERATED_LIST=(0x02A | GRAPH_NODE_TYPE_FUNCTIONAL)\n"
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,12 @@ void* smlua_to_cobject(lua_State* L, int index, u16 lot) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cobject->freed) {
|
||||||
|
LOG_LUA_LINE("smlua_to_cobject received freed pointer.");
|
||||||
|
gSmLuaConvertSuccess = false;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gSmLuaConvertSuccess = true;
|
gSmLuaConvertSuccess = true;
|
||||||
return cobject->pointer;
|
return cobject->pointer;
|
||||||
}
|
}
|
||||||
|
|
@ -387,6 +393,10 @@ bool packet_read_lnt(struct Packet* p, struct LSTNetworkType* lnt) {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline static uintptr_t smlua_get_pointer_key(void *ptr, u16 lt) {
|
||||||
|
return (lt * 0x9E3779B97F4A7C15) ^ ((uintptr_t) ptr >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
CObject *smlua_push_object(lua_State* L, u16 lot, void* p, void *extraInfo) {
|
CObject *smlua_push_object(lua_State* L, u16 lot, void* p, void *extraInfo) {
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
|
|
@ -394,7 +404,7 @@ CObject *smlua_push_object(lua_State* L, u16 lot, void* p, void *extraInfo) {
|
||||||
}
|
}
|
||||||
LUA_STACK_CHECK_BEGIN_NUM(L, 1);
|
LUA_STACK_CHECK_BEGIN_NUM(L, 1);
|
||||||
|
|
||||||
uintptr_t key = (lot * 0x9E3779B97F4A7C15) ^ ((uintptr_t)p >> 3);
|
uintptr_t key = smlua_get_pointer_key(p, lot);
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, gSmLuaCObjects);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, gSmLuaCObjects);
|
||||||
lua_pushinteger(L, key);
|
lua_pushinteger(L, key);
|
||||||
lua_gettable(L, -2);
|
lua_gettable(L, -2);
|
||||||
|
|
@ -431,7 +441,7 @@ CPointer *smlua_push_pointer(lua_State* L, u16 lvt, void* p, void *extraInfo) {
|
||||||
}
|
}
|
||||||
LUA_STACK_CHECK_BEGIN_NUM(L, 1);
|
LUA_STACK_CHECK_BEGIN_NUM(L, 1);
|
||||||
|
|
||||||
uintptr_t key = (lvt * 0x9E3779B97F4A7C15) ^ ((uintptr_t)p >> 3);
|
uintptr_t key = smlua_get_pointer_key(p, lvt);
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, gSmLuaCPointers);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, gSmLuaCPointers);
|
||||||
lua_pushinteger(L, key);
|
lua_pushinteger(L, key);
|
||||||
lua_gettable(L, -2);
|
lua_gettable(L, -2);
|
||||||
|
|
@ -840,15 +850,11 @@ void smlua_logline(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an object is freed that Lua has a CObject to,
|
void smlua_free(void *ptr, u16 lot) {
|
||||||
// Lua is able to use-after-free that pointer
|
|
||||||
// todo figure out a better way to do this
|
|
||||||
void smlua_free(void *ptr) {
|
|
||||||
if (ptr && gLuaState) {
|
if (ptr && gLuaState) {
|
||||||
lua_State *L = gLuaState;
|
lua_State *L = gLuaState;
|
||||||
LUA_STACK_CHECK_BEGIN(L);
|
LUA_STACK_CHECK_BEGIN(L);
|
||||||
u16 lot = LOT_SURFACE; // Assuming this is a surface
|
uintptr_t key = smlua_get_pointer_key(ptr, lot);
|
||||||
uintptr_t key = lot ^ (uintptr_t) ptr;
|
|
||||||
lua_rawgeti(L, LUA_REGISTRYINDEX, gSmLuaCObjects);
|
lua_rawgeti(L, LUA_REGISTRYINDEX, gSmLuaCObjects);
|
||||||
lua_pushinteger(L, key);
|
lua_pushinteger(L, key);
|
||||||
lua_gettable(L, -2);
|
lua_gettable(L, -2);
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,11 @@ void smlua_logline(void);
|
||||||
void smlua_dump_stack(void);
|
void smlua_dump_stack(void);
|
||||||
void smlua_dump_globals(void);
|
void smlua_dump_globals(void);
|
||||||
void smlua_dump_table(int index);
|
void smlua_dump_table(int index);
|
||||||
void smlua_free(void *ptr);
|
void smlua_free(void *ptr, u16 lot);
|
||||||
|
|
||||||
|
#define smlua_free_lot(name, lot) \
|
||||||
|
static inline void smlua_free_##name(void *ptr) { smlua_free(ptr, lot); }
|
||||||
|
|
||||||
|
smlua_free_lot(surface, LOT_SURFACE);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Loading…
Add table
Reference in a new issue