Cleaned up surface loading
This commit is contained in:
@@ -3,13 +3,12 @@
|
||||
#include "../shim.h"
|
||||
#include "surface_collision.h"
|
||||
#include "../include/surface_terrains.h"
|
||||
|
||||
struct SurfaceNode *s_surfaceList;
|
||||
#include "../load_surfaces.h"
|
||||
|
||||
/**
|
||||
* 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 s32 x1, z1, x2, z2, x3, z3;
|
||||
struct Surface *ceil = NULL;
|
||||
@@ -17,10 +16,9 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
|
||||
ceil = NULL;
|
||||
|
||||
// Stay in this loop until out of ceilings.
|
||||
while (surfaceNode != NULL) {
|
||||
surf = surfaceNode->surface;
|
||||
surfaceNode = surfaceNode->next;
|
||||
|
||||
int count = loaded_surface_get_count();
|
||||
for( int i = 0; i < count; ++i ) {
|
||||
surf = loaded_surface_get_at_index(i);
|
||||
|
||||
// Do the check normally done in add_surface_to_cell
|
||||
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.
|
||||
*/
|
||||
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 s32 x1, z1, x2, z2, x3, z3;
|
||||
f32 nx, ny, nz;
|
||||
@@ -105,9 +103,9 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
|
||||
struct Surface *floor = NULL;
|
||||
|
||||
// Iterate through the list of floors until there are no more floors.
|
||||
while (surfaceNode != NULL) {
|
||||
surf = surfaceNode->surface;
|
||||
surfaceNode = surfaceNode->next;
|
||||
int count = loaded_surface_get_count();
|
||||
for( int i = 0; i < count; ++i ) {
|
||||
surf = loaded_surface_get_at_index(i);
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
|
||||
struct WallCollisionData *data) {
|
||||
static s32 find_wall_collisions_from_list( struct WallCollisionData *data) {
|
||||
register struct Surface *surf;
|
||||
register f32 offset;
|
||||
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.
|
||||
while (surfaceNode != NULL) {
|
||||
surf = surfaceNode->surface;
|
||||
surfaceNode = surfaceNode->next;
|
||||
int count = loaded_surface_get_count();
|
||||
for( int i = 0; i < count; ++i ) {
|
||||
surf = loaded_surface_get_at_index(i);
|
||||
|
||||
|
||||
// Do the check normally done in add_surface_to_cell
|
||||
@@ -362,14 +359,14 @@ s32 find_wall_collisions(struct WallCollisionData *colData)
|
||||
return numCollisions;
|
||||
}
|
||||
|
||||
numCollisions += find_wall_collisions_from_list(s_surfaceList, colData);
|
||||
numCollisions += find_wall_collisions_from_list(colData);
|
||||
return numCollisions;
|
||||
}
|
||||
|
||||
f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 height = FLOOR_LOWER_LIMIT;
|
||||
find_floor_from_list( s_surfaceList, x, y, z, &height );
|
||||
find_floor_from_list( x, y, z, &height );
|
||||
return height;
|
||||
}
|
||||
|
||||
f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -416,8 +413,3 @@ f32 find_poison_gas_level(f32 x, f32 z)
|
||||
{
|
||||
return -10000.0f;
|
||||
}
|
||||
|
||||
void hack_load_surface_list(struct SurfaceNode *surfaceNode)
|
||||
{
|
||||
s_surfaceList = surfaceNode;
|
||||
}
|
||||
@@ -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_poison_gas_level(f32 x, f32 z);
|
||||
|
||||
void hack_load_surface_list(struct SurfaceNode *surfaceNode);
|
||||
|
||||
#endif // SURFACE_COLLISION_H
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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
@@ -12,7 +12,6 @@
|
||||
#include "shim.h"
|
||||
#include "game/mario.h"
|
||||
#include "game/object_stuff.h"
|
||||
#include "engine/surface_load.h"
|
||||
#include "engine/surface_collision.h"
|
||||
#include "engine/graph_node.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 )
|
||||
{
|
||||
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 )
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ struct SM64SurfaceObject
|
||||
{
|
||||
struct SM64ObjectTransform transform;
|
||||
uint32_t surfaceCount;
|
||||
struct SM64Surface surfaces[];
|
||||
struct SM64Surface *surfaces;
|
||||
};
|
||||
|
||||
struct SM64MarioState
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 );
|
||||
Reference in New Issue
Block a user