![]() |
Super Mario 64 Source
A Super Mario 64 decompilation, brought to you by a bunch of clever folks.
|
This file implements a self-contained subsystem used to draw shadows. More...
#include <ultra64.h>
#include <math.h>
#include "sm64.h"
#include "shadow.h"
#include "area.h"
#include "engine/graph_node.h"
#include "engine/math_util.h"
#include "engine/surface_collision.h"
#include "mario_animation_ids.h"
#include "mario.h"
#include "memory.h"
#include "rendering_graph_node.h"
#include "room.h"
#include "segment2.h"
#include "save_file.h"
#include "geo_misc.h"
Data Structures | |
struct | Shadow |
Encapsulation of information about a shadow. More... | |
struct | shadowRectangle |
A struct containing info about hardcoded rectangle shadows. More... | |
Macros | |
#define | SHADOW_SOLIDITY_NO_SHADOW 0 |
Constant to indicate that a shadow should not be drawn. More... | |
#define | SHADOW_SOILDITY_ALREADY_SET 1 |
Constant to indicate that a shadow's solidity has been pre-set by a previous function and should not be overwritten. More... | |
#define | SHADOW_SOLIDITY_NOT_YET_SET 2 |
Constant to indicate that a shadow's solidity has not yet been set. More... | |
#define | SHADOW_SHAPE_CIRCLE 10 |
Constant to indicate any sort of circular shadow. More... | |
#define | SHADOW_SHAPE_SQUARE 20 |
Constant to indicate any sort of rectangular shadow. More... | |
#define | SHADOW_WITH_9_VERTS 0 |
Constant to indicate a shadow consists of 9 vertices. More... | |
#define | SHADOW_WITH_4_VERTS 1 |
Constant to indicate a shadow consists of 4 vertices. More... | |
Functions | |
void | rotate_rectangle (f32 *newZ, f32 *newX, f32 oldZ, f32 oldX) |
Let (oldZ, oldX) be the relative coordinates of a point on a rectangle, assumed to be centered at the origin on the standard SM64 X-Z plane. More... | |
f32 | atan2_deg (f32 a, f32 b) |
Return atan2(a, b) in degrees. More... | |
f32 | scale_shadow_with_distance (f32 initial, f32 distFromFloor) |
Shrink a shadow when its parent object is further from the floor, given the initial size of the shadow and the current distance. More... | |
f32 | disable_shadow_with_distance (f32 shadowScale, f32 distFromFloor) |
Disable a shadow when its parent object is more than 600 units from the ground. More... | |
u8 | dim_shadow_with_distance (u8 solidity, f32 distFromFloor) |
Dim a shadow when its parent object is further from the ground. More... | |
f32 | get_water_level_below_shadow (struct Shadow *s) |
Return the water level below a shadow, or 0 if the water level is below -10,000. More... | |
s8 | init_shadow (struct Shadow *s, f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 overwriteSolidity) |
Initialize a shadow. More... | |
void | get_texture_coords_9_vertices (s8 vertexNum, s16 *textureX, s16 *textureY) |
Given a vertexNum from a shadow with nine vertices, update the texture coordinates corresponding to that vertex. More... | |
void | get_texture_coords_4_vertices (s8 vertexNum, s16 *textureX, s16 *textureY) |
Given a vertexNum from a shadow with four vertices, update the texture coordinates corresponding to that vertex. More... | |
void | make_shadow_vertex_at_xyz (Vtx *vertices, s8 index, f32 relX, f32 relY, f32 relZ, u8 alpha, s8 shadowVertexType) |
Make a shadow's vertex at a position relative to its parent. More... | |
f32 | extrapolate_vertex_y_position (struct Shadow s, f32 vtxX, f32 vtxZ) |
Given an (x, z)-position close to a shadow, extrapolate the y-position according to the floor's normal vector. More... | |
void | get_vertex_coords (s8 index, s8 shadowVertexType, s8 *xCoord, s8 *zCoord) |
Given a shadow vertex with the given index , return the corresponding texture coordinates ranging in the square with corners at (-1, -1), (1, -1), (-1, 1), and (1, 1) in the x-z plane. More... | |
void | calculate_vertex_xyz (s8 index, struct Shadow s, f32 *xPosVtx, f32 *yPosVtx, f32 *zPosVtx, s8 shadowVertexType) |
Populate xPosVtx , yPosVtx , and zPosVtx with the (x, y, z) position of the shadow vertex with the given index. More... | |
s16 | floor_local_tilt (struct Shadow s, f32 vtxX, f32 vtxY, f32 vtxZ) |
Given a vertex's location, return the dot product of the position of that vertex (relative to the shadow's center) with the floor normal (at the shadow's center). More... | |
void | make_shadow_vertex (Vtx *vertices, s8 index, struct Shadow s, s8 shadowVertexType) |
Make a particular vertex from a shadow, calculating its position and solidity. More... | |
void | add_shadow_to_display_list (Gfx *displayListHead, Vtx *verts, s8 shadowVertexType, s8 shadowShape) |
Add a shadow to the given display list. More... | |
void | linearly_interpolate_solidity_positive (struct Shadow *s, u8 finalSolidity, s16 curr, s16 start, s16 end) |
Linearly interpolate a shadow's solidity between zero and finalSolidity depending on curr's relation to start and end. More... | |
void | linearly_interpolate_solidity_negative (struct Shadow *s, u8 initialSolidity, s16 curr, s16 start, s16 end) |
Linearly interpolate a shadow's solidity between initialSolidity and zero depending on curr's relation to start and end. More... | |
s8 | correct_shadow_solidity_for_animations (s32 isLuigi, u8 initialSolidity, struct Shadow *shadow) |
Change a shadow's solidity based on the player's current animation frame. More... | |
void | correct_lava_shadow_height (struct Shadow *s) |
Slightly change the height of a shadow in levels with lava. More... | |
Gfx * | create_shadow_player (f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 solidity, s32 isLuigi) |
Create a shadow under a player, correcting that shadow's opacity during appropriate animations and other states. More... | |
Gfx * | create_shadow_circle_9_verts (f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 solidity) |
Create a circular shadow composed of 9 vertices. More... | |
Gfx * | create_shadow_circle_4_verts (f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 solidity) |
Create a circular shadow composed of 4 vertices. More... | |
Gfx * | create_shadow_circle_assuming_flat_ground (f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 solidity) |
Create a circular shadow composed of 4 vertices and assume that the ground underneath it is totally flat. More... | |
Gfx * | create_shadow_rectangle (f32 halfWidth, f32 halfLength, f32 relY, u8 solidity) |
Create a rectangular shadow composed of 4 vertices. More... | |
s32 | get_shadow_height_solidity (f32 xPos, f32 yPos, f32 zPos, f32 *shadowHeight, u8 *solidity) |
Populate shadowHeight and solidity appropriately; the default solidity value is 200. More... | |
Gfx * | create_shadow_square (f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 solidity, s8 shadowType) |
Create a square shadow composed of 4 vertices. More... | |
Gfx * | create_shadow_hardcoded_rectangle (f32 xPos, f32 yPos, f32 zPos, UNUSED s16 shadowScale, u8 solidity, s8 shadowType) |
Create a rectangular shadow whose parameters have been hardcoded in the rectangles array. More... | |
Gfx * | create_shadow_below_xyz (f32 xPos, f32 yPos, f32 zPos, s16 shadowScale, u8 shadowSolidity, s8 shadowType) |
Create a shadow at the absolute position given, with the given parameters. More... | |
Variables | |
shadowRectangle | rectangles [2] |
An array consisting of all the hardcoded rectangle shadows in the game. More... | |
s8 | sMarioOnFlyingCarpet |
Flag for if Mario is on a flying carpet. More... | |
s16 | sSurfaceTypeBelowShadow |
The surface type below the current shadow. More... | |
s8 | gShadowAboveWaterOrLava |
Flag for if the current shadow is above water or lava. More... | |
s8 | gMarioOnIceOrCarpet |
Flag for if Mario is on ice or a flying carpet. More... | |
This file implements a self-contained subsystem used to draw shadows.
#define SHADOW_SHAPE_CIRCLE 10 |
Constant to indicate any sort of circular shadow.
#define SHADOW_SHAPE_SQUARE 20 |
Constant to indicate any sort of rectangular shadow.
#define SHADOW_SOILDITY_ALREADY_SET 1 |
Constant to indicate that a shadow's solidity has been pre-set by a previous function and should not be overwritten.
#define SHADOW_SOLIDITY_NO_SHADOW 0 |
Constant to indicate that a shadow should not be drawn.
This is used to disable shadows during specific frames of Mario's animations.
#define SHADOW_SOLIDITY_NOT_YET_SET 2 |
Constant to indicate that a shadow's solidity has not yet been set.
#define SHADOW_WITH_4_VERTS 1 |
Constant to indicate a shadow consists of 4 vertices.
#define SHADOW_WITH_9_VERTS 0 |
Constant to indicate a shadow consists of 9 vertices.
void add_shadow_to_display_list | ( | Gfx * | displayListHead, |
Vtx * | verts, | ||
s8 | shadowVertexType, | ||
s8 | shadowShape | ||
) |
Add a shadow to the given display list.
Return atan2(a, b) in degrees.
Note that the argument order is swapped from the standard atan2.
void calculate_vertex_xyz | ( | s8 | index, |
struct Shadow | s, | ||
f32 * | xPosVtx, | ||
f32 * | yPosVtx, | ||
f32 * | zPosVtx, | ||
s8 | shadowVertexType | ||
) |
Populate xPosVtx
, yPosVtx
, and zPosVtx
with the (x, y, z) position of the shadow vertex with the given index.
If the shadow is to have 9 vertices, then each of those vertices is clamped down to the floor below it. Otherwise, in the 4 vertex case, the vertex positions are extrapolated from the center of the shadow.
In practice, due to the if-statement in make_shadow_vertex()
, the 9 vertex and 4 vertex cases are identical, and the above-described clamping behavior is overwritten.
Note that this dichotomy is later overwritten in make_shadow_vertex().
Slightly change the height of a shadow in levels with lava.
s8 correct_shadow_solidity_for_animations | ( | s32 | isLuigi, |
u8 | initialSolidity, | ||
struct Shadow * | shadow | ||
) |
Change a shadow's solidity based on the player's current animation frame.
This is evidence of a removed second player, likely Luigi. This variable lies in memory just after the gMarioObject and has the same type of shadow that Mario does. The isLuigi
variable is never 1 in the game. Note that since this was a switch-case, not an if-statement, the programmers possibly intended there to be even more than 2 characters.
Gfx* create_shadow_below_xyz | ( | f32 | xPos, |
f32 | yPos, | ||
f32 | zPos, | ||
s16 | shadowScale, | ||
u8 | shadowSolidity, | ||
s8 | shadowType | ||
) |
Create a shadow at the absolute position given, with the given parameters.
Given the (x, y, z) location of an object, create a shadow below that object with the given initial solidity and "shadowType" (described above).
Return a pointer to the display list representing the shadow.
Create a circular shadow composed of 4 vertices.
Create a circular shadow composed of 9 vertices.
Gfx* create_shadow_circle_assuming_flat_ground | ( | f32 | xPos, |
f32 | yPos, | ||
f32 | zPos, | ||
s16 | shadowScale, | ||
u8 | solidity | ||
) |
Create a circular shadow composed of 4 vertices and assume that the ground underneath it is totally flat.
Gfx* create_shadow_hardcoded_rectangle | ( | f32 | xPos, |
f32 | yPos, | ||
f32 | zPos, | ||
UNUSED s16 | shadowScale, | ||
u8 | solidity, | ||
s8 | shadowType | ||
) |
Create a rectangular shadow whose parameters have been hardcoded in the rectangles
array.
Note that idx could be negative or otherwise out of the bounds of the rectangles
array. In practice, it never is, because this was only used twice.
Gfx* create_shadow_player | ( | f32 | xPos, |
f32 | yPos, | ||
f32 | zPos, | ||
s16 | shadowScale, | ||
u8 | solidity, | ||
s32 | isLuigi | ||
) |
Create a shadow under a player, correcting that shadow's opacity during appropriate animations and other states.
Create a rectangular shadow composed of 4 vertices.
This assumes the ground underneath the shadow is totally flat.
Gfx* create_shadow_square | ( | f32 | xPos, |
f32 | yPos, | ||
f32 | zPos, | ||
s16 | shadowScale, | ||
u8 | solidity, | ||
s8 | shadowType | ||
) |
Create a square shadow composed of 4 vertices.
Dim a shadow when its parent object is further from the ground.
Disable a shadow when its parent object is more than 600 units from the ground.
Given an (x, z)-position close to a shadow, extrapolate the y-position according to the floor's normal vector.
Given a vertex's location, return the dot product of the position of that vertex (relative to the shadow's center) with the floor normal (at the shadow's center).
Since it is a dot product, this returns 0 if these two vectors are perpendicular, meaning the ground is locally flat. It returns nonzero in most cases where vtxY
is on a different floor triangle from the center vertex, as in the case with SHADOW_WITH_9_VERTS, which sets the y-value from find_floor_height_and_data
. (See the bottom of calculate_vertex_xyz
.)
Populate shadowHeight
and solidity
appropriately; the default solidity value is 200.
Return 0 if a shadow should be drawn, 1 if not.
Given a vertexNum
from a shadow with four vertices, update the texture coordinates corresponding to that vertex.
That is: 0 = (-15, -15) 1 = (15, -15) 2 = (-15, 15) 3 = (15, 15)
Given a vertexNum
from a shadow with nine vertices, update the texture coordinates corresponding to that vertex.
That is: 0 = (-15, -15) 1 = (0, -15) 2 = (15, -15) 3 = (-15, 0) 4 = (0, 0) 5 = (15, 0) 6 = (-15, 15) 7 = (0, 15) 8 = (15, 15)
Given a shadow vertex with the given index
, return the corresponding texture coordinates ranging in the square with corners at (-1, -1), (1, -1), (-1, 1), and (1, 1) in the x-z plane.
See get_texture_coords_9_vertices()
and get_texture_coords_4_vertices()
, which have similar functionality, but return 15 times these values.
Return the water level below a shadow, or 0 if the water level is below -10,000.
waterLevel
incidentally. s8 init_shadow | ( | struct Shadow * | s, |
f32 | xPos, | ||
f32 | yPos, | ||
f32 | zPos, | ||
s16 | shadowScale, | ||
u8 | overwriteSolidity | ||
) |
Initialize a shadow.
Return 0 on success, 1 on failure.
xPos,yPos,zPos | Position of the parent object (not the shadow) |
shadowScale | Diameter of the shadow |
overwriteSolidity | Flag for whether the existing shadow solidity should be dimmed based on its distance to the floor |
waterLevel
void linearly_interpolate_solidity_negative | ( | struct Shadow * | s, |
u8 | initialSolidity, | ||
s16 | curr, | ||
s16 | start, | ||
s16 | end | ||
) |
Linearly interpolate a shadow's solidity between initialSolidity and zero depending on curr's relation to start and end.
Note that if curr < start, the solidity will be zero.
void linearly_interpolate_solidity_positive | ( | struct Shadow * | s, |
u8 | finalSolidity, | ||
s16 | curr, | ||
s16 | start, | ||
s16 | end | ||
) |
Linearly interpolate a shadow's solidity between zero and finalSolidity depending on curr's relation to start and end.
Make a particular vertex from a shadow, calculating its position and solidity.
This is the hack that makes "SHADOW_WITH_9_VERTS" act identically to "SHADOW_WITH_4_VERTS" in the game; this same hack is disabled by the GameShark code in this video: https://youtu.be/MSIh4rtNGF0. The code in the video makes extrapolate_vertex_y_position
return the same value as the last-called function that returns a float; in this case, that's find_floor_height_and_data
, which this if-statement was designed to overwrite in the first place. Thus, this if-statement is disabled by that code.
The last condition here means the y-position calculated previously was probably on a different floor triangle from the center vertex. The gShadowAboveWaterOrLava check is redundant, since floor_local_tilt
will always be 0 over water or lava (since they are always flat).
void make_shadow_vertex_at_xyz | ( | Vtx * | vertices, |
s8 | index, | ||
f32 | relX, | ||
f32 | relY, | ||
f32 | relZ, | ||
u8 | alpha, | ||
s8 | shadowVertexType | ||
) |
Make a shadow's vertex at a position relative to its parent.
vertices | A preallocated display list for vertices |
index | Index into vertices to insert the vertex |
relX,relY,relZ | Vertex position relative to its parent object |
alpha | Opacity of the vertex |
shadowVertexType | One of SHADOW_WITH_9_VERTS or SHADOW_WITH_4_VERTS |
Let (oldZ, oldX) be the relative coordinates of a point on a rectangle, assumed to be centered at the origin on the standard SM64 X-Z plane.
This function will update (newZ, newX) to equal the new coordinates of that point after a rotation equal to the yaw of the current graph node object.
Shrink a shadow when its parent object is further from the floor, given the initial size of the shadow and the current distance.
s8 gMarioOnIceOrCarpet |
Flag for if Mario is on ice or a flying carpet.
s8 gShadowAboveWaterOrLava |
Flag for if the current shadow is above water or lava.
shadowRectangle rectangles[2] |
s8 sMarioOnFlyingCarpet |
Flag for if Mario is on a flying carpet.
s16 sSurfaceTypeBelowShadow |
The surface type below the current shadow.