Cleaned up surface loading

This commit is contained in:
jaburns
2020-10-17 12:31:21 -06:00
parent 3256cc50c1
commit 735d227928
8 changed files with 176 additions and 415 deletions
+17 -25
View File
@@ -3,13 +3,12 @@
#include "../shim.h" #include "../shim.h"
#include "surface_collision.h" #include "surface_collision.h"
#include "../include/surface_terrains.h" #include "../include/surface_terrains.h"
#include "../load_surfaces.h"
struct SurfaceNode *s_surfaceList;
/** /**
* Iterate through the list of ceilings and find the first ceiling over a given point. * Iterate through the list of ceilings and find the first ceiling over a given point.
*/ */
static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32 x, s32 y, s32 z, f32 *pheight) { static struct Surface *find_ceil_from_list( s32 x, s32 y, s32 z, f32 *pheight) {
register struct Surface *surf; register struct Surface *surf;
register s32 x1, z1, x2, z2, x3, z3; register s32 x1, z1, x2, z2, x3, z3;
struct Surface *ceil = NULL; struct Surface *ceil = NULL;
@@ -17,10 +16,9 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
ceil = NULL; ceil = NULL;
// Stay in this loop until out of ceilings. // Stay in this loop until out of ceilings.
while (surfaceNode != NULL) { int count = loaded_surface_get_count();
surf = surfaceNode->surface; for( int i = 0; i < count; ++i ) {
surfaceNode = surfaceNode->next; surf = loaded_surface_get_at_index(i);
// Do the check normally done in add_surface_to_cell // Do the check normally done in add_surface_to_cell
if( surf->normal.y >= -0.01f ) continue; if( surf->normal.y >= -0.01f ) continue;
@@ -96,7 +94,7 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
/** /**
* Iterate through the list of floors and find the first floor under a given point. * Iterate through the list of floors and find the first floor under a given point.
*/ */
static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32 x, s32 y, s32 z, f32 *pheight) { static struct Surface *find_floor_from_list( s32 x, s32 y, s32 z, f32 *pheight) {
register struct Surface *surf; register struct Surface *surf;
register s32 x1, z1, x2, z2, x3, z3; register s32 x1, z1, x2, z2, x3, z3;
f32 nx, ny, nz; f32 nx, ny, nz;
@@ -105,9 +103,9 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
struct Surface *floor = NULL; struct Surface *floor = NULL;
// Iterate through the list of floors until there are no more floors. // Iterate through the list of floors until there are no more floors.
while (surfaceNode != NULL) { int count = loaded_surface_get_count();
surf = surfaceNode->surface; for( int i = 0; i < count; ++i ) {
surfaceNode = surfaceNode->next; surf = loaded_surface_get_at_index(i);
// Do the check normally done in add_surface_to_cell // Do the check normally done in add_surface_to_cell
@@ -175,8 +173,7 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
return floor; return floor;
} }
static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode, static s32 find_wall_collisions_from_list( struct WallCollisionData *data) {
struct WallCollisionData *data) {
register struct Surface *surf; register struct Surface *surf;
register f32 offset; register f32 offset;
register f32 radius = data->radius; register f32 radius = data->radius;
@@ -194,9 +191,9 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
} }
// Stay in this loop until out of walls. // Stay in this loop until out of walls.
while (surfaceNode != NULL) { int count = loaded_surface_get_count();
surf = surfaceNode->surface; for( int i = 0; i < count; ++i ) {
surfaceNode = surfaceNode->next; surf = loaded_surface_get_at_index(i);
// Do the check normally done in add_surface_to_cell // Do the check normally done in add_surface_to_cell
@@ -362,14 +359,14 @@ s32 find_wall_collisions(struct WallCollisionData *colData)
return numCollisions; return numCollisions;
} }
numCollisions += find_wall_collisions_from_list(s_surfaceList, colData); numCollisions += find_wall_collisions_from_list(colData);
return numCollisions; return numCollisions;
} }
f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil) f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil)
{ {
f32 height = CELL_HEIGHT_LIMIT; f32 height = CELL_HEIGHT_LIMIT;
*pceil = find_ceil_from_list( s_surfaceList, posX, posY, posZ, &height ); *pceil = find_ceil_from_list( posX, posY, posZ, &height );
return height; return height;
} }
@@ -396,14 +393,14 @@ f32 find_floor_height_and_data(f32 xPos, f32 yPos, f32 zPos, struct FloorGeometr
f32 find_floor_height(f32 x, f32 y, f32 z) f32 find_floor_height(f32 x, f32 y, f32 z)
{ {
f32 height = FLOOR_LOWER_LIMIT; f32 height = FLOOR_LOWER_LIMIT;
find_floor_from_list( s_surfaceList, x, y, z, &height ); find_floor_from_list( x, y, z, &height );
return height; return height;
} }
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor)
{ {
f32 height = FLOOR_LOWER_LIMIT; f32 height = FLOOR_LOWER_LIMIT;
*pfloor = find_floor_from_list( s_surfaceList, xPos, yPos, zPos, &height ); *pfloor = find_floor_from_list( xPos, yPos, zPos, &height );
return height; return height;
} }
@@ -415,9 +412,4 @@ f32 find_water_level(f32 x, f32 z)
f32 find_poison_gas_level(f32 x, f32 z) f32 find_poison_gas_level(f32 x, f32 z)
{ {
return -10000.0f; return -10000.0f;
}
void hack_load_surface_list(struct SurfaceNode *surfaceNode)
{
s_surfaceList = surfaceNode;
} }
-2
View File
@@ -39,6 +39,4 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor);
f32 find_water_level(f32 x, f32 z); f32 find_water_level(f32 x, f32 z);
f32 find_poison_gas_level(f32 x, f32 z); f32 find_poison_gas_level(f32 x, f32 z);
void hack_load_surface_list(struct SurfaceNode *surfaceNode);
#endif // SURFACE_COLLISION_H #endif // SURFACE_COLLISION_H
-378
View File
@@ -1,378 +0,0 @@
#include <stdlib.h>
#include <math.h>
#include "../include/surface_terrains.h"
#include "../include/surface_terrains.h"
#include "../shim.h"
#include "surface_load.h"
#include "surface_collision.h"
struct Surface **s_surface_list = NULL;
size_t s_surface_list_count = 0;
struct SurfaceNode *s_surface_node_list = NULL;
static void add_surface_ex(struct Surface *surface, s32 dynamic)
{
s_surface_list_count++;
if( s_surface_list == NULL )
s_surface_list = malloc( s_surface_list_count * sizeof( struct Surface * ));
else
s_surface_list = realloc( s_surface_list, s_surface_list_count * sizeof( struct Surface * ));
s_surface_list[s_surface_list_count - 1] = surface;
}
static struct Surface *alloc_surface(void) {
struct Surface *surface = malloc(sizeof(struct Surface)); // PATCH - just use malloc instead of pool
// struct Surface *surface = &sSurfacePool[gSurfacesAllocated];
// gSurfacesAllocated++;
//! A bounds check! If there's more surfaces than the 2300 allowed,
// we, um...
// Perhaps originally just debug feedback?
// if (gSurfacesAllocated >= sSurfacePoolSize) {
// }
surface->type = 0;
surface->force = 0;
surface->flags = 0;
surface->room = 0;
surface->object = NULL;
return surface;
}
/**
* Returns whether a surface has exertion/moves Mario
* based on the surface type.
*/
static s32 surface_has_force(s16 surfaceType) {
s32 hasForce = FALSE;
switch (surfaceType) {
case SURFACE_0004: // Unused
case SURFACE_FLOWING_WATER:
case SURFACE_DEEP_MOVING_QUICKSAND:
case SURFACE_SHALLOW_MOVING_QUICKSAND:
case SURFACE_MOVING_QUICKSAND:
case SURFACE_HORIZONTAL_WIND:
case SURFACE_INSTANT_MOVING_QUICKSAND:
hasForce = TRUE;
break;
default:
break;
}
return hasForce;
}
/**
* Returns whether a surface should have the
* SURFACE_FLAG_NO_CAM_COLLISION flag.
*/
static s32 surf_has_no_cam_collision(s16 surfaceType) {
s32 flags = 0;
switch (surfaceType) {
case SURFACE_NO_CAM_COLLISION:
case SURFACE_NO_CAM_COLLISION_77: // Unused
case SURFACE_NO_CAM_COL_VERY_SLIPPERY:
case SURFACE_SWITCH:
flags = SURFACE_FLAG_NO_CAM_COLLISION;
break;
default:
break;
}
return flags;
}
static struct Surface *read_surface_data_ex( s32 x1, s32 y1, s32 z1, s32 x2, s32 y2, s32 z2, s32 x3, s32 y3, s32 z3) {
struct Surface *surface;
s32 maxY, minY;
f32 nx, ny, nz;
f32 mag;
// (v2 - v1) x (v3 - v2)
nx = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2);
ny = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2);
nz = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);
mag = sqrtf(nx * nx + ny * ny + nz * nz);
// Could have used min_3 and max_3 for this...
minY = y1;
if (y2 < minY) {
minY = y2;
}
if (y3 < minY) {
minY = y3;
}
maxY = y1;
if (y2 > maxY) {
maxY = y2;
}
if (y3 > maxY) {
maxY = y3;
}
// Checking to make sure no DIV/0
if (mag < 0.0001) {
return NULL;
}
mag = (f32)(1.0 / mag);
nx *= mag;
ny *= mag;
nz *= mag;
surface = alloc_surface();
surface->vertex1[0] = x1;
surface->vertex2[0] = x2;
surface->vertex3[0] = x3;
surface->vertex1[1] = y1;
surface->vertex2[1] = y2;
surface->vertex3[1] = y3;
surface->vertex1[2] = z1;
surface->vertex2[2] = z2;
surface->vertex3[2] = z3;
surface->normal.x = nx;
surface->normal.y = ny;
surface->normal.z = nz;
surface->originOffset = -(nx * x1 + ny * y1 + nz * z1);
surface->lowerY = minY - 5;
surface->upperY = maxY + 5;
return surface;
}
/**
* Initializes a Surface struct using the given vertex data
* @param vertexData The raw data containing vertex positions
* @param vertexIndices Helper which tells positions in vertexData to start reading vertices
*/
static struct Surface *read_surface_data(s16 *vertexData, s16 **vertexIndices) {
register s32 x1, y1, z1;
register s32 x2, y2, z2;
register s32 x3, y3, z3;
s16 offset1, offset2, offset3;
offset1 = 3 * (*vertexIndices)[0];
offset2 = 3 * (*vertexIndices)[1];
offset3 = 3 * (*vertexIndices)[2];
x1 = *(vertexData + offset1 + 0);
y1 = *(vertexData + offset1 + 1);
z1 = *(vertexData + offset1 + 2);
x2 = *(vertexData + offset2 + 0);
y2 = *(vertexData + offset2 + 1);
z2 = *(vertexData + offset2 + 2);
x3 = *(vertexData + offset3 + 0);
y3 = *(vertexData + offset3 + 1);
z3 = *(vertexData + offset3 + 2);
return read_surface_data_ex( x1, y1, z1, x2, y2, z2, x3, y3, z3 );
}
/**
* Read the data for vertices for reference by triangles.
*/
static s16 *read_vertex_data(s16 **data) {
s32 numVertices;
UNUSED s16 unused1[3];
UNUSED s16 unused2[3];
s16 *vertexData;
numVertices = *(*data);
(*data)++;
vertexData = *data;
*data += 3 * numVertices;
return vertexData;
}
/**
* Load in the surfaces for a given surface type. This includes setting the flags,
* exertion, and room.
*/
static void load_static_surfaces(s16 **data, s16 *vertexData, s16 surfaceType, s8 **surfaceRooms) {
s32 i;
s32 numSurfaces;
struct Surface *surface;
s8 room = 0;
s16 hasForce = surface_has_force(surfaceType);
s16 flags = surf_has_no_cam_collision(surfaceType);
numSurfaces = *(*data);
*data += 1;
for (i = 0; i < numSurfaces; i++) {
if (*surfaceRooms != NULL) {
room = *(*surfaceRooms);
*surfaceRooms += 1;
}
surface = read_surface_data(vertexData, data);
if (surface != NULL) {
surface->room = room;
surface->type = surfaceType;
surface->flags = (s8) flags;
if (hasForce) {
surface->force = *(*data + 3);
} else {
surface->force = 0;
}
add_surface_ex(surface, FALSE);
}
*data += 3;
if (hasForce) {
*data += 1;
}
}
}
static void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects) {
s16 terrainLoadType;
s16 *vertexData;
UNUSED s32 unused;
// Initialize the data for this.
// gEnvironmentRegions = NULL;
// unused8038BE90 = 0;
// gSurfaceNodesAllocated = 0;
// gSurfacesAllocated = 0;
// clear_static_surfaces();
// A while loop iterating through each section of the level data. Sections of data
// are prefixed by a terrain "type." This type is reused for surfaces as the surface
// type.
while (TRUE) {
terrainLoadType = *data;
data++;
if (TERRAIN_LOAD_IS_SURFACE_TYPE_LOW(terrainLoadType)) {
load_static_surfaces(&data, vertexData, terrainLoadType, &surfaceRooms);
} else if (terrainLoadType == TERRAIN_LOAD_VERTICES) {
vertexData = read_vertex_data(&data);
// } else if (terrainLoadType == TERRAIN_LOAD_OBJECTS) {
// spawn_special_objects(index, &data);
// } else if (terrainLoadType == TERRAIN_LOAD_ENVIRONMENT) {
// load_environmental_regions(&data);
} else if (terrainLoadType == TERRAIN_LOAD_CONTINUE) {
// continue;
break; // PATCH
} else if (terrainLoadType == TERRAIN_LOAD_END) {
break;
} else if (TERRAIN_LOAD_IS_SURFACE_TYPE_HIGH(terrainLoadType)) {
load_static_surfaces(&data, vertexData, terrainLoadType, &surfaceRooms);
continue;
}
}
// if (macroObjects != NULL && *macroObjects != -1) {
// // If the first macro object presetID is within the range [0, 29].
// // Generally an early spawning method, every object is in BBH (the first level).
// if (0 <= *macroObjects && *macroObjects < 30) {
// spawn_macro_objects_hardcoded(index, macroObjects);
// }
// // A more general version that can spawn more objects.
// else {
// spawn_macro_objects(index, macroObjects);
// }
// }
// gNumStaticSurfaceNodes = gSurfaceNodesAllocated;
// gNumStaticSurfaces = gSurfacesAllocated;
}
// Unused, loads from raw sm64 collision data
// struct Surface **surface_load_from_collision_data( const s16 *data, size_t *numSurfaces )
// {
// s8 *rooms = NULL;
// s16 *macroObjects = NULL;
// load_area_terrain( 0, (s16*)data, rooms, macroObjects );
// *numSurfaces = s_surface_list_count;
// return s_surface_list;
// }
void surface_load_for_libsm64( const struct SM64Surface *surfaceArray, uint32_t numSurfaces )
{
while( s_surface_node_list )
{
struct SurfaceNode *node = s_surface_node_list;
s_surface_node_list = node->next;
free( node );
}
if( s_surface_list )
{
for( int i = 0; i < s_surface_list_count; ++i )
free( s_surface_list[i] );
free( s_surface_list );
s_surface_list = NULL;
s_surface_list_count = 0;
}
for( int i = 0; i < numSurfaces; ++i )
{
struct Surface *surface = read_surface_data_ex(
surfaceArray[i].vertices[0][0], surfaceArray[i].vertices[0][1], surfaceArray[i].vertices[0][2],
surfaceArray[i].vertices[1][0], surfaceArray[i].vertices[1][1], surfaceArray[i].vertices[1][2],
surfaceArray[i].vertices[2][0], surfaceArray[i].vertices[2][1], surfaceArray[i].vertices[2][2]
);
if (surface != NULL) {
s16 hasForce = surface_has_force(surfaceArray[i].type);
s16 flags = surf_has_no_cam_collision(surfaceArray[i].type);
surface->room = 0;
surface->type = surfaceArray[i].type;
surface->flags = (s8) flags;
if (hasForce) {
surface->force = surfaceArray[i].force;
} else {
surface->force = 0;
}
add_surface_ex(surface, FALSE);
}
}
struct Surface **ptr = s_surface_list;
struct SurfaceNode *node = malloc( sizeof( struct SurfaceNode ));
node->surface = *ptr;
s_surface_node_list = node;
for( int i = 1; i < s_surface_list_count; ++i )
{
ptr++;
struct SurfaceNode *next = malloc( sizeof( struct SurfaceNode ));
next->surface = *ptr;
next->next = NULL;
node->next = next;
node = next;
}
hack_load_surface_list( s_surface_node_list );
}
-8
View File
@@ -1,8 +0,0 @@
#pragma once
#include "../libsm64.h"
#include "../include/types.h"
struct Surface **surface_load_from_collision_data( const s16 *data, size_t *numSurfaces );
void surface_load_for_libsm64( const struct SM64Surface *surfaceArray, size_t numSurfaces );
+10 -1
View File
@@ -12,7 +12,6 @@
#include "shim.h" #include "shim.h"
#include "game/mario.h" #include "game/mario.h"
#include "game/object_stuff.h" #include "game/object_stuff.h"
#include "engine/surface_load.h"
#include "engine/surface_collision.h" #include "engine/surface_collision.h"
#include "engine/graph_node.h" #include "engine/graph_node.h"
#include "engine/geo_layout.h" #include "engine/geo_layout.h"
@@ -174,6 +173,16 @@ void sm64_global_terminate( void )
uint32_t sm64_load_surface_object( const struct SM64SurfaceObject *surfaceObject ) uint32_t sm64_load_surface_object( const struct SM64SurfaceObject *surfaceObject )
{ {
DEBUG_LOG(
"sm64_load_surface_object : %f %f %f : %f %f %f : %d",
surfaceObject->transform.position[0],
surfaceObject->transform.position[1],
surfaceObject->transform.position[2],
surfaceObject->transform.eulerRotation[0],
surfaceObject->transform.eulerRotation[1],
surfaceObject->transform.eulerRotation[2],
surfaceObject->surfaceCount
);
} }
void sm64_move_object( uint32_t id, const struct SM64ObjectTransform *transform ) void sm64_move_object( uint32_t id, const struct SM64ObjectTransform *transform )
+1 -1
View File
@@ -29,7 +29,7 @@ struct SM64SurfaceObject
{ {
struct SM64ObjectTransform transform; struct SM64ObjectTransform transform;
uint32_t surfaceCount; uint32_t surfaceCount;
struct SM64Surface surfaces[]; struct SM64Surface *surfaces;
}; };
struct SM64MarioState struct SM64MarioState
+139
View File
@@ -0,0 +1,139 @@
#include "load_surfaces.h"
#include "include/types.h"
#include "include/surface_terrains.h"
static struct Surface *s_loaded_static_surface_list = NULL;
static size_t s_loaded_static_surface_count = 0;
/**
* Returns whether a surface has exertion/moves Mario
* based on the surface type.
*/
static s32 surface_has_force(s16 surfaceType) {
s32 hasForce = FALSE;
switch (surfaceType) {
case SURFACE_0004: // Unused
case SURFACE_FLOWING_WATER:
case SURFACE_DEEP_MOVING_QUICKSAND:
case SURFACE_SHALLOW_MOVING_QUICKSAND:
case SURFACE_MOVING_QUICKSAND:
case SURFACE_HORIZONTAL_WIND:
case SURFACE_INSTANT_MOVING_QUICKSAND:
hasForce = TRUE;
break;
default:
break;
}
return hasForce;
}
static void read_surface_data( struct Surface *surface, int16_t type, int16_t force, s32 x1, s32 y1, s32 z1, s32 x2, s32 y2, s32 z2, s32 x3, s32 y3, s32 z3)
{
s32 maxY, minY;
f32 nx, ny, nz;
f32 mag;
// (v2 - v1) x (v3 - v2)
nx = (y2 - y1) * (z3 - z2) - (z2 - z1) * (y3 - y2);
ny = (z2 - z1) * (x3 - x2) - (x2 - x1) * (z3 - z2);
nz = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);
mag = sqrtf(nx * nx + ny * ny + nz * nz);
// Could have used min_3 and max_3 for this...
minY = y1;
if (y2 < minY) {
minY = y2;
}
if (y3 < minY) {
minY = y3;
}
maxY = y1;
if (y2 > maxY) {
maxY = y2;
}
if (y3 > maxY) {
maxY = y3;
}
if (mag < 0.0001)
DEBUG_LOG("ERROR: normal magnitude is very close to zero");
mag = (f32)(1.0 / mag);
nx *= mag;
ny *= mag;
nz *= mag;
surface = malloc(sizeof(struct Surface));
surface->vertex1[0] = x1;
surface->vertex2[0] = x2;
surface->vertex3[0] = x3;
surface->vertex1[1] = y1;
surface->vertex2[1] = y2;
surface->vertex3[1] = y3;
surface->vertex1[2] = z1;
surface->vertex2[2] = z2;
surface->vertex3[2] = z3;
surface->normal.x = nx;
surface->normal.y = ny;
surface->normal.z = nz;
surface->originOffset = -(nx * x1 + ny * y1 + nz * z1);
surface->lowerY = minY - 5;
surface->upperY = maxY + 5;
s16 hasForce = surface_has_force(type);
s16 flags = 0; // surf_has_no_cam_collision(type);
surface->room = 0;
surface->type = type;
surface->flags = (s8) flags;
if (hasForce) {
surface->force = force;
} else {
surface->force = 0;
}
return surface;
}
struct Surface *loaded_surface_get_at_index( uint32_t index )
{
return &s_loaded_static_surface_list[ index ];
}
uint32_t loaded_surface_get_count()
{
return s_loaded_static_surface_count;
}
void surfaces_load_static_libsm64( const struct SM64Surface *surfaceArray, uint32_t numSurfaces )
{
s_loaded_static_surface_count = numSurfaces;
s_loaded_static_surface_list = malloc( sizeof( struct Surface ) * numSurfaces );
for( int i = 0; i < numSurfaces; ++i )
read_surface_data(
&s_loaded_static_surface_list[i], surfaceArray[i].type, surfaceArray[i].force,
surfaceArray[i].vertices[0][0], surfaceArray[i].vertices[0][1], surfaceArray[i].vertices[0][2],
surfaceArray[i].vertices[1][0], surfaceArray[i].vertices[1][1], surfaceArray[i].vertices[1][2],
surfaceArray[i].vertices[2][0], surfaceArray[i].vertices[2][1], surfaceArray[i].vertices[2][2]
);
}
uint32_t surfaces_load_object( const struct SM64SurfaceObject *surfaceObject )
{
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "libsm64.h"
extern struct Surface *loaded_surface_get_at_index( uint32_t index );
extern uint32_t loaded_surface_get_count();
extern void surfaces_load_static_libsm64( const struct SM64Surface *surfaceArray, uint32_t numSurfaces );
extern uint32_t surfaces_load_object( const struct SM64SurfaceObject *surfaceObject );