diff --git a/include/enums.h b/include/enums.h index 8686c266..9a3dfdf6 100644 --- a/include/enums.h +++ b/include/enums.h @@ -47,7 +47,7 @@ typedef enum Vehicle { VEHICLE_BUBBLER, VEHICLE_WIZPIG, VEHICLE_ROCKET, - + VEHICLE_NO_OVERRIDE = -1, // Only used in Object Maps for the setup point. NUMBER_OF_VEHICLE_TYPES, NUMBER_OF_PLAYER_VEHICLES = 3 @@ -64,12 +64,7 @@ typedef enum CameraMode { CAMERA_FINISH_RACE } CameraMode; -typedef enum Language { - LANGUAGE_ENGLISH, - LANGUAGE_GERMAN, - LANGUAGE_FRENCH, - LANGUAGE_JAPANESE -} Language; +typedef enum Language { LANGUAGE_ENGLISH, LANGUAGE_GERMAN, LANGUAGE_FRENCH, LANGUAGE_JAPANESE } Language; typedef enum World { WORLD_NONE = -1, // This enum starts at -1 instead of 0. @@ -82,17 +77,17 @@ typedef enum World { } World; typedef enum RaceType { - RACETYPE_DEFAULT = 0, - RACETYPE_UNK1 = 1, - RACETYPE_HORSESHOE_GULCH = 3, - RACETYPE_HUBWORLD = 5, - RACETYPE_CUTSCENE_1 = 6, // Not sure what the difference between these two are. - RACETYPE_CUTSCENE_2 = 7, - RACETYPE_BOSS = 8, - RACETYPE_CHALLENGE_BATTLE = 64, + RACETYPE_DEFAULT = 0, + RACETYPE_UNK1 = 1, + RACETYPE_HORSESHOE_GULCH = 3, + RACETYPE_HUBWORLD = 5, + RACETYPE_CUTSCENE_1 = 6, // Not sure what the difference between these two are. + RACETYPE_CUTSCENE_2 = 7, + RACETYPE_BOSS = 8, + RACETYPE_CHALLENGE_BATTLE = 64, RACETYPE_CHALLENGE_BANANAS = 65, - RACETYPE_CHALLENGE_EGGS = 66, - RACETYPE_CHALLENGE = 0x40 // For masking + RACETYPE_CHALLENGE_EGGS = 66, + RACETYPE_CHALLENGE = 0x40 // For masking } RaceType; enum BossSetupTypes { @@ -131,27 +126,27 @@ typedef enum BalloonType { } BalloonType; typedef enum HorizontalAlignmentFlags { - HORZ_ALIGN_LEFT = 0, - HORZ_ALIGN_RIGHT = 1, + HORZ_ALIGN_LEFT = 0, + HORZ_ALIGN_RIGHT = 1, HORZ_ALIGN_CENTER = 4 } HorizontalAlignmentFlags; typedef enum VerticalAlignmentFlags { - VERT_ALIGN_TOP = 0, + VERT_ALIGN_TOP = 0, VERT_ALIGN_BOTTOM = 2, VERT_ALIGN_MIDDLE = 8 } VerticalAlignmentFlags; typedef enum AlignmentFlags { - ALIGN_TOP_LEFT = VERT_ALIGN_TOP | HORZ_ALIGN_LEFT, - ALIGN_TOP_CENTER = VERT_ALIGN_TOP | HORZ_ALIGN_CENTER, - ALIGN_TOP_RIGHT = VERT_ALIGN_TOP | HORZ_ALIGN_RIGHT, - ALIGN_MIDDLE_LEFT = VERT_ALIGN_MIDDLE | HORZ_ALIGN_LEFT, + ALIGN_TOP_LEFT = VERT_ALIGN_TOP | HORZ_ALIGN_LEFT, + ALIGN_TOP_CENTER = VERT_ALIGN_TOP | HORZ_ALIGN_CENTER, + ALIGN_TOP_RIGHT = VERT_ALIGN_TOP | HORZ_ALIGN_RIGHT, + ALIGN_MIDDLE_LEFT = VERT_ALIGN_MIDDLE | HORZ_ALIGN_LEFT, ALIGN_MIDDLE_CENTER = VERT_ALIGN_MIDDLE | HORZ_ALIGN_CENTER, - ALIGN_MIDDLE_RIGHT = VERT_ALIGN_MIDDLE | HORZ_ALIGN_RIGHT, - ALIGN_BOTTOM_LEFT = VERT_ALIGN_BOTTOM | HORZ_ALIGN_LEFT, + ALIGN_MIDDLE_RIGHT = VERT_ALIGN_MIDDLE | HORZ_ALIGN_RIGHT, + ALIGN_BOTTOM_LEFT = VERT_ALIGN_BOTTOM | HORZ_ALIGN_LEFT, ALIGN_BOTTOM_CENTER = VERT_ALIGN_BOTTOM | HORZ_ALIGN_CENTER, - ALIGN_BOTTOM_RIGHT = VERT_ALIGN_BOTTOM | HORZ_ALIGN_RIGHT + ALIGN_BOTTOM_RIGHT = VERT_ALIGN_BOTTOM | HORZ_ALIGN_RIGHT } AlignmentFlags; typedef enum SurfaceType { @@ -166,11 +161,11 @@ typedef enum SurfaceType { SURFACE_EGG_03, SURFACE_EGG_04, SURFACE_FROZEN_WATER, - SURFACE_UNK0B, + SURFACE_WATER_CALM, SURFACE_TAJ_PAD, SURFACE_SNOW, - SURFACE_UNK0E, - SURFACE_UNK0F, + SURFACE_WATER_WAVY, + SURFACE_WATER_UNK_F, SURFACE_UNK10, SURFACE_INVIS_WALL, SURFACE_UNK12, diff --git a/include/structs.h b/include/structs.h index c75a031b..f2c5be5d 100644 --- a/include/structs.h +++ b/include/structs.h @@ -567,7 +567,7 @@ typedef struct TextureInfo { /* 0x04 */ u8 width; /* 0x05 */ u8 height; /* 0x06 */ u8 format; - /* 0x07 */ s8 unk7; + /* 0x07 */ s8 surfaceType; } TextureInfo; /* Size: 10 bytes */ @@ -696,10 +696,10 @@ typedef struct ModelInstance { /* 0x20 */ s8 animUpdateTimer; } ModelInstance; -typedef struct CollisionNode { - u16 triangleIndex; // This triangle index - u16 closestTri[3]; -} CollisionNode; +typedef struct CollisionFacetPlanes { + u16 basePlaneIndex; // Index of the triangle's main collision plane + u16 edgeBisectorPlane[3]; // Indices of edge bisector planes for triangle edges +} CollisionFacetPlanes; /* Size: 0x44 bytes */ typedef struct LevelModelSegment { @@ -708,11 +708,8 @@ typedef struct LevelModelSegment { /* 0x08 */ s32 unk8; /* 0x0C */ TriangleBatchInfo *batches; /* 0x10 */ s16 *unk10; - /* 0x14 */ CollisionNode *unk14; - union { - /* 0x18 */ f32 *unk18; - /* 0x18 */ Vec4f *unk18_vec4f; // Used for objects, not levels. - }; + /* 0x14 */ CollisionFacetPlanes *collisionFacets; + /* 0x18 */ f32 *collisionPlanes; // Array of plane equations (A, B, C, D) used in collision checks /* 0x1C */ s16 numberOfVertices; /* 0x1E */ s16 numberOfTriangles; /* 0x20 */ s16 numberOfBatches; @@ -1210,10 +1207,7 @@ typedef struct Object_Racer { /* 0x0CC */ f32 unkCC; /* 0x0D0 */ f32 unkD0; /* 0x0D4 */ f32 unkD4; - /* 0x0D8 */ Vec3f unkD8; - /* 0x0E4 */ Vec3f unkE4; - /* 0x0F0 */ Vec3f unkF0; - /* 0x0FC */ Vec3f unkFC; + /* 0x0D8 */ f32 unkD8[12]; /* 0x108 */ struct Object *exitObj; /* 0x10C */ s32 unk10C; /* 0x110 */ s32 unk110; diff --git a/src/collision.h b/src/collision.h index 8c8611e6..7ce73ce5 100644 --- a/src/collision.h +++ b/src/collision.h @@ -4,8 +4,12 @@ #include "types.h" #include "structs.h" -void func_80031130(s32, f32 *, f32*, s32); -s32 func_800314DC(LevelModelSegmentBoundingBox *segment, s32 x1, s32 z1, s32 x2, s32 z2); -s32 func_80031600(f32 *pos, f32 *pos2, f32 *radius, s8 *surface, s32, s32 *hasCollision); +#define MAX_COLLISION_CANDIDATES 500 + +enum CollisionModes { COLLISION_MODE_DEFAULT, COLLISION_MODE_1, COLLISION_MODE_NO_WALLS }; + +void generate_collision_candidates(s32, f32 *, f32 *, s32); +s32 compute_grid_overlap_mask(LevelModelSegmentBoundingBox *segment, s32 x1, s32 z1, s32 x2, s32 z2); +s32 resolve_collisions(Vec3f *pos, Vec3f *pos2, f32 *radius, s8 *surface, s32 numEntries, s32 *numCollisions); #endif diff --git a/src/hasm/collision.c b/src/hasm/collision.c index 8ff2d98b..aa4a8fdb 100644 --- a/src/hasm/collision.c +++ b/src/hasm/collision.c @@ -2,95 +2,507 @@ #include "types.h" #include "macros.h" +#include "textures_sprites.h" /*******************************/ +extern LevelModel *gCurrentLevelModel; + +extern f32 gCollisionNormalX; +extern f32 gCollisionNormalY; +extern f32 gCollisionNormalZ; +extern s32 gHitWall; +extern s32 gCollisionMode; + +extern s32 *gCollisionCandidates; +extern s8 *gCollisionSurfaces; +extern s32 gNumCollisionCandidates; + // All handwritten assembly, below. -// Collision for a different segment -GLOBAL_ASM("asm/collision/func_80031130.s") - -// Might be segment related. #ifdef NON_EQUIVALENT -s32 func_800314DC(LevelModelSegmentBoundingBox *segment, s32 x1, s32 z1, s32 x2, s32 z2) { - s32 v0 = 0; +/** + * Populates a list of triangle candidates that will be tested for collision in resolve_collisions. + * Calculates a single bounding rectangle that contains all origin and target points. + * Then, terrain segments overlapping this rectangle are identified, and eligible triangles within them are selected. + * Triangle batches are filtered based on visibility, surface type, and collision flags. + */ +void generate_collision_candidates(s32 numPoints, Vec3f *origins, Vec3f *targets, s32 vehicleID) { + s32 i; + s32 minX, maxX, minZ, maxZ; + s32 counter; + LevelModelSegment *segments[10]; + s16 grid_mask[10]; + s32 i, j, batchIndex, triIndex; + s32 surface; + + minX = 100000; + maxX = -100000; + minZ = 100000; + maxZ = -100000; + + // Calculate a single bounding rectangle containing all origin and target points + for (i = 0; i < numPoints; i++) { + s32 x1 = origins[i].x; + s32 z1 = origins[i].z; + s32 x2 = targets[i].x; + s32 z2 = targets[i].z; + + if (maxX < x1) { + maxX = x1; + } + if (minX > x1) { + minX = x1; + } + + if (maxZ < z1) { + maxZ = z1; + } + if (minZ > z1) { + minZ = z1; + } + + if (maxX < x2) { + maxX = x2; + } + if (minX > x2) { + minX = x2; + } + + if (maxZ < z2) { + maxZ = z2; + } + if (minZ > z2) { + minZ = z2; + } + } + + // Add padding to ensure slight overlap with nearby geometry + minX -= 20; + maxX += 20; + minZ -= 20; + maxZ += 20; + + // Swap values if necessary (should never happen) + if (maxX < minX) { + s32 temp; + + temp = minX; + minX = maxX; + maxX = temp; + } + if (maxZ < minZ) { + s32 temp; + + temp = minZ; + minZ = maxZ; + maxZ = temp; + } + + // Select up to 10 terrain segments whose bounding boxes overlap the search rectangle (with 5 units tolerance) + counter = 0; + for (i = 0; i < gCurrentLevelModel->numberOfSegments; i++) { + if (minX <= gCurrentLevelModel->segmentsBoundingBoxes[i].x2 + 5 && + maxX >= gCurrentLevelModel->segmentsBoundingBoxes[i].x1 - 5 && + minZ <= gCurrentLevelModel->segmentsBoundingBoxes[i].z2 + 5 && + maxZ >= gCurrentLevelModel->segmentsBoundingBoxes[i].z1 - 5) { + + grid_mask[counter] = + compute_grid_overlap_mask(&gCurrentLevelModel->segmentsBoundingBoxes[i], minX, minZ, maxX, maxZ); + segments[counter] = &gCurrentLevelModel->segments[i]; + if (counter == 10) { + break; + } + } + } + + // Populate the list of collision candidates + j = 0; + for (i = 0; i < counter; i++) { + LevelModelSegment *seg = segments[i]; + + // Insert the segment pointer encoded with MSB = 0 to differentiate from collision facets + gCollisionCandidates[j] = (s32) seg & ~0x80000000; + j++; + + for (batchIndex = 0; batchIndex < seg->numberOfBatches; batchIndex++) { + // Skip batches marked as non-collidable + if (seg->batches[batchIndex].flags & RENDER_NO_COLLISION) { + continue; + } + + // Skip hidden surfaces for non-vehicle objects (e.g., projectiles, pickups) + if (vehicleID == -1 && (seg->batches[batchIndex].flags & RENDER_HIDDEN)) { + continue; + } + + // Skip batches with no texture, since the surface type is stored in the texture data + if (seg->batches[batchIndex].textureIndex == 255) { + continue; + } + + // Skip surfaces that are non-solid or selectively passable depending on the vehicle type: + // - SURFACE_WATER_CALM is passable by all objects (treated like water surface). + // - SURFACE_INVIS_WALL can be passed through only by planes. + // - SURFACE_UNK12 is impassable only for cars, but passable by other vehicle types. + surface = gCurrentLevelModel->textures[seg->batches[batchIndex].textureIndex].surfaceType; + if (surface == SURFACE_WATER_CALM || vehicleID == VEHICLE_PLANE && surface == SURFACE_INVIS_WALL || + vehicleID != VEHICLE_CAR && surface == SURFACE_UNK12) { + continue; + } + + // Iterate over triangles in the batch and add eligible ones based on grid mask intersection + for (triIndex = seg->batches[batchIndex].facesOffset; triIndex < seg->batches[batchIndex + 1].facesOffset; + triIndex++) { + CollisionFacetPlanes *facet = &seg->collisionFacets[triIndex]; + + // Check if the triangle's grid mask intersects with the bounding rectangle's grid mask + if (((seg->unk10[triIndex] & grid_mask[i]) & 0x00FF) == 0 || + ((seg->unk10[triIndex] & grid_mask[i]) & 0xFF00) == 0) { + continue; + } + + gCollisionCandidates[j] = (s32) facet; + gCollisionSurfaces[j] = surface; + j++; + + if (j == MAX_COLLISION_CANDIDATES) { + goto out; + } + } + } + } + +out: + gNumCollisionCandidates = j; + return 0; +} +#else +GLOBAL_ASM("asm/collision/generate_collision_candidates.s") +#endif + +#ifdef NON_EQUIVALENT +/** + * Computes the overlap between a rectangle and a segment's bounding box, returning a 16-bit grid mask. + * The bounding box is divided into an 8x8 grid. The function determines which grid columns (X) and rows (Z) + * the input rectangle intersects. + * The resulting 16-bit mask encodes this information: + * - lower 8 bits represent intersections along the X-axis (1 bit per column), + * - upper 8 bits represent intersections along the Z-axis (1 bit per row). + */ +s32 compute_grid_overlap_mask(LevelModelSegmentBoundingBox *bbox, s32 x1, s32 z1, s32 x2, s32 z2) { + s32 mask = 0; s32 v1; - s32 t0, t1, t2, t3, t4; + s32 i; + s32 cell_width; + s32 cell_height; + s32 cell_x, cell_z; + s32 bbox_x1, bbox_z1, bbox_x2, bbox_z2, t4; - if (segment == NULL) { - return v0; + if (bbox == NULL) { + return mask; } - t0 = segment->x1; - t1 = segment->z1; - t2 = segment->x2; - t3 = segment->z2; + bbox_x1 = bbox->x1; + bbox_z1 = bbox->z1; + bbox_x2 = bbox->x2; + bbox_z2 = bbox->z2; - if (x2 < t0) { - x2 = t0; + if (x2 < bbox_x1) { + x2 = bbox_x1; } - if (x1 < t0) { - x1 = t0; + if (x1 < bbox_x1) { + x1 = bbox_x1; } - if (z2 < t1) { - z2 = t1; + if (z2 < bbox_z1) { + z2 = bbox_z1; } - if (z1 < t1) { - z1 = t1; + if (z1 < bbox_z1) { + z1 = bbox_z1; } - if (t2 < x2) { - x2 = t2; + if (x2 > bbox_x2) { + x2 = bbox_x2; } - if (t2 < x1) { - x1 = t2; + if (x1 > bbox_x2) { + x1 = bbox_x2; } - if (t3 < z2) { - z2 = t3; + if (z2 > bbox_z2) { + z2 = bbox_z2; } - if (t3 < z1) { - z1 = t3; + if (z1 > bbox_z2) { + z1 = bbox_z2; } v1 = 1; - t2 = ((t2 - t0) >> 3) + 1; - t4 = t2 + t0; + cell_width = ((bbox_x2 - bbox_x1) >> 3) + 1; + cell_x = bbox_x1; - while (v1 < (1 << 8)) { - if (t4 >= x1 && x2 >= t0) { - v0 |= v1; + for (i = 0; i < 8; i++) { + if (cell_x + cell_width >= x1 && x2 >= cell_x) { + mask |= v1; } v1 <<= 1; - t4 += t2; - t0 += t2; + cell_x += cell_width; } - t2 = ((t3 - t1) >> 3) + 1; - t4 = t2 + t1; + cell_height = ((bbox_z2 - bbox_z1) >> 3) + 1; + cell_z = bbox_z1; - while (v1 < (1 << 16)) { - if (t4 >= z1 && z2 >= t1) { - v0 |= v1; + for (i = 0; i < 8; i++) { + if (cell_z + cell_height >= z1 && z2 >= bbox_z1) { + mask |= v1; } v1 <<= 1; - t4 += t2; - t1 += t2; + cell_z += cell_height; } - return v0; + return mask; } #else -GLOBAL_ASM("asm/collision/func_800314DC.s") +GLOBAL_ASM("asm/collision/compute_grid_overlap_mask.s") #endif -// Player collision for the current segment -GLOBAL_ASM("asm/collision/func_80031600.s") +#ifdef NON_EQUIVALENT +/** + * Resolves collisions for a list of moving objects against previously identified collision candidates. + * For each object, the function checks whether the path from `origin` to `target` intersects any collision plane. + * If so, it adjusts the `target` position to resolve the collision, updates surface type, and sets output flags. + * Returns a bitmask indicating which objects experienced a collision. + */ +s32 resolve_collisions(Vec3f *origin, Vec3f *target, f32 *radius, s8 *surface, s32 numEntries, s32 *numCollisions) { + s32 i, j; + f32 *collisionPlanes; + f32 A, B, C, D; + f32 A1, B1, C1, D1; + CollisionFacetPlanes *facet; + f32 targetDist; + f32 originDist; + f32 diffX, diffY, diffZ; + f32 outX, outY, outZ; + f32 intersectionFactor; + f32 intersectionPointX, intersectionPointY, intersectionPointZ; + s32 insideTriangle; + u8 bitMask; + s8 collisionMask; + + bitMask = 1; + collisionMask = 0; + gHitWall = FALSE; + + if (gNumCollisionCandidates == 0) { + return 0; + } + + // Step 1: forward collision resolution + while (numEntries > 0) { + s32 numCollidedSurfaces = 0; + s32 continueSearch; + + do { + continueSearch = FALSE; + + for (i = 0; i < gNumCollisionCandidates; i++) { + if (gCollisionCandidates[i] >= 0) { + collisionPlanes = ((LevelModelSegment *) (gCollisionCandidates[i] | 0x80000000))->collisionPlanes; + } else { + facet = (CollisionFacetPlanes *) gCollisionCandidates[i]; + A = collisionPlanes[facet->basePlaneIndex * 4 + 0]; + B = collisionPlanes[facet->basePlaneIndex * 4 + 1]; + C = collisionPlanes[facet->basePlaneIndex * 4 + 2]; + D = collisionPlanes[facet->basePlaneIndex * 4 + 3]; + + targetDist = (target->x * A + target->y * B + target->z * C + D) - *radius; + originDist = (origin->x * A + origin->y * B + origin->z * C + D) - *radius; + + // Process only one-sided collisions (above -> below plane), with tolerance + if (targetDist < -0.1 && originDist >= -0.1) { + diffX = target->x - origin->x; + diffY = target->y - origin->y; + diffZ = target->z - origin->z; + + if (targetDist != originDist) { + intersectionFactor = originDist / (originDist - targetDist); + } else { + intersectionFactor = 0.0f; + } + + intersectionPointX = origin->x + diffX * intersectionFactor; + intersectionPointY = origin->y + diffY * intersectionFactor; + intersectionPointZ = origin->z + diffZ * intersectionFactor; + + // Check if intersection point lies within triangle bounds + insideTriangle = TRUE; + for (j = 0; j < 3 && insideTriangle; j++) { + s32 flipSide = FALSE; + s32 edgeBisectorPlane = facet->edgeBisectorPlane[j]; + f32 dist; + + if (edgeBisectorPlane & 0x8000) { + flipSide = TRUE; + edgeBisectorPlane &= 0x7FFF; + } + + A1 = collisionPlanes[edgeBisectorPlane * 4 + 0]; + B1 = collisionPlanes[edgeBisectorPlane * 4 + 1]; + C1 = collisionPlanes[edgeBisectorPlane * 4 + 2]; + D1 = collisionPlanes[edgeBisectorPlane * 4 + 3]; + + dist = intersectionPointX * A1 + intersectionPointY * B1 + intersectionPointX * C1 + D1; + if (flipSide) { + dist = -dist; + } + + if (dist >= 4.0f) { + insideTriangle = FALSE; + } + } + + if (insideTriangle) { + if (B >= 0.707 && gCollisionSurfaces[i] != SURFACE_STONE && + gCollisionMode == COLLISION_MODE_DEFAULT) { + // Push up vertically if slope is gentle and not stone + outX = target->x; + outY = (*radius - (target->x * A + target->z * C + D)) / B; + outZ = target->z; + } else { + if (B < 0.45 && gCollisionMode != COLLISION_MODE_NO_WALLS) { + // Wall-like surface: store collision normal + gHitWall = TRUE; + gCollisionNormalX = A; + gCollisionNormalY = B; + gCollisionNormalZ = C; + } + + // Push out along surface normal + outX = target->x - A * targetDist; + outY = target->y - B * targetDist; + outZ = target->z - C * targetDist; + } + + if (!gHitWall) { + gCollisionNormalX = A; + gCollisionNormalY = B; + gCollisionNormalZ = C; + } + + // Store surface type with highest priority (higher ID wins) + if (*surface < gCollisionSurfaces[i]) { + *surface = gCollisionSurfaces[i]; + } + + continueSearch = TRUE; + numCollidedSurfaces++; + if (numCollidedSurfaces > 10) { + continueSearch = FALSE; + outX = origin->x; + outY = origin->y; + outZ = origin->z; + } + + // Update target and recheck collisions + target->x = outX; + target->y = outY; + target->z = outZ; + break; + } + } + } + } + } while (continueSearch); + + if (numCollidedSurfaces != 0) { + (*numCollisions)++; + collisionMask |= bitMask; + } + bitMask <<= 1; + + // Step 2: ensure object is fully pushed out from underneath + numCollidedSurfaces = 0; + do { + continueSearch = FALSE; + + for (i = 0; i < gNumCollisionCandidates; i++) { + if (gCollisionCandidates[i] >= 0) { + collisionPlanes = ((LevelModelSegment *) (gCollisionCandidates[i] | 0x80000000))->collisionPlanes; + } else { + facet = (CollisionFacetPlanes *) gCollisionCandidates[i]; + A = collisionPlanes[facet->basePlaneIndex * 4 + 0]; + B = collisionPlanes[facet->basePlaneIndex * 4 + 1]; + C = collisionPlanes[facet->basePlaneIndex * 4 + 2]; + D = collisionPlanes[facet->basePlaneIndex * 4 + 3]; + + targetDist = (target->x * A + target->y * B + target->z * C + D) - *radius; + if (targetDist < -0.1 && targetDist > -(*radius + 3.0f)) { + insideTriangle = TRUE; + for (j = 0; j < 3 && insideTriangle; j++) { + s32 flipSide = FALSE; + s32 edgePlaneIndex = facet->edgeBisectorPlane[j]; + f32 dist; + + if (edgePlaneIndex & 0x8000) { + flipSide = TRUE; + edgePlaneIndex &= 0x7FFF; + } + + A1 = collisionPlanes[edgePlaneIndex * 4 + 0]; + B1 = collisionPlanes[edgePlaneIndex * 4 + 1]; + C1 = collisionPlanes[edgePlaneIndex * 4 + 2]; + D1 = collisionPlanes[edgePlaneIndex * 4 + 3]; + + dist = target->x * A1 + target->y * B1 + target->z * C1 + D1; + if (flipSide) { + dist = -dist; + } + + if (dist >= 4.0f) { + insideTriangle = FALSE; + } + } + + if (insideTriangle) { + outX = target->x - A * targetDist; + outY = target->y - B * targetDist; + outZ = target->z - C * targetDist; + + continueSearch = TRUE; + numCollidedSurfaces++; + if (numCollidedSurfaces > 10) { + continueSearch = FALSE; + outX = origin->x; + outY = origin->y; + outZ = origin->z; + } + + target->x = outX; + target->y = outY; + target->z = outZ; + break; + } + } + } + } + } while (continueSearch); + + // Advance to next entry + numEntries--; + origin++; + target++; + radius++; + surface++; + } + + return collisionMask; +} +#else +GLOBAL_ASM("asm/collision/resolve_collisions.s") +#endif diff --git a/src/hasm/collision.s b/src/hasm/collision.s index 8726a11c..9bec8464 100644 --- a/src/hasm/collision.s +++ b/src/hasm/collision.s @@ -22,7 +22,7 @@ glabel D_800E5F70 /* Generated by spimdisasm 1.30.2 */ -leaf func_80031130 +leaf generate_collision_candidates /* 31D30 80031130 27BDFF90 */ addiu $sp, $sp, -0x70 /* 31D34 80031134 3C080001 */ lui $t0, (0x186A0 >> 16) /* 31D38 80031138 3C09FFFE */ lui $t1, (0xFFFE7960 >> 16) @@ -152,7 +152,7 @@ leaf func_80031130 /* 31EF4 800312F4 02A02825 */ or $a1, $s5, $zero /* 31EF8 800312F8 02603025 */ or $a2, $s3, $zero /* 31EFC 800312FC 02803825 */ or $a3, $s4, $zero - /* 31F00 80031300 0C00C537 */ jal func_800314DC + /* 31F00 80031300 0C00C537 */ jal compute_grid_overlap_mask /* 31F04 80031304 AFB20010 */ sw $s2, 0x10($sp) /* 31F08 80031308 A6220000 */ sh $v0, 0x0($s1) /* 31F0C 8003130C 27180001 */ addiu $t8, $t8, 0x1 @@ -172,12 +172,12 @@ leaf func_80031130 /* 31F38 80031338 00009825 */ or $s3, $zero, $zero /* 31F3C 8003133C 3C04800E */ lui $a0, %hi(gCurrentLevelModel) /* 31F40 80031340 8C84C918 */ lw $a0, %lo(gCurrentLevelModel)($a0) - /* 31F44 80031344 3C128012 */ lui $s2, %hi(D_8011D370) - /* 31F48 80031348 3C198012 */ lui $t9, %hi(D_8011D374) + /* 31F44 80031344 3C128012 */ lui $s2, %hi(gCollisionCandidates) + /* 31F48 80031348 3C198012 */ lui $t9, %hi(gCollisionSurfaces) /* 31F4C 8003134C 23B10034 */ addi $s1, $sp, 0x34 /* handwritten instruction */ /* 31F50 80031350 0018C040 */ sll $t8, $t8, 1 - /* 31F54 80031354 8E52D370 */ lw $s2, %lo(D_8011D370)($s2) - /* 31F58 80031358 8F39D374 */ lw $t9, %lo(D_8011D374)($t9) + /* 31F54 80031354 8E52D370 */ lw $s2, %lo(gCollisionCandidates)($s2) + /* 31F58 80031358 8F39D374 */ lw $t9, %lo(gCollisionSurfaces)($t9) /* 31F5C 8003135C 23B00048 */ addi $s0, $sp, 0x48 /* handwritten instruction */ /* 31F60 80031360 0238C020 */ add $t8, $s1, $t8 /* handwritten instruction */ /* 31F64 80031364 8C840000 */ lw $a0, 0x0($a0) @@ -274,8 +274,8 @@ leaf func_80031130 /* 320A4 800314A4 26100004 */ addiu $s0, $s0, 0x4 .L800314A8: /* 320A8 800314A8 8FBF0030 */ lw $ra, 0x30($sp) - /* 320AC 800314AC 3C018012 */ lui $at, %hi(D_8011D378) - /* 320B0 800314B0 AC33D378 */ sw $s3, %lo(D_8011D378)($at) + /* 320AC 800314AC 3C018012 */ lui $at, %hi(gNumCollisionCandidates) + /* 320B0 800314B0 AC33D378 */ sw $s3, %lo(gNumCollisionCandidates)($at) /* 320B4 800314B4 8FB6002C */ lw $s6, 0x2C($sp) /* 320B8 800314B8 8FB50028 */ lw $s5, 0x28($sp) /* 320BC 800314BC 8FB40024 */ lw $s4, 0x24($sp) @@ -286,9 +286,9 @@ leaf func_80031130 /* 320D0 800314D0 00001025 */ or $v0, $zero, $zero /* 320D4 800314D4 03E00008 */ jr $ra /* 320D8 800314D8 27BD0070 */ addiu $sp, $sp, 0x70 -.end func_80031130 +.end generate_collision_candidates -leaf func_800314DC +leaf compute_grid_overlap_mask /* 320DC 800314DC 10800046 */ beqz $a0, .L800315F8 /* 320E0 800314E0 00001025 */ or $v0, $zero, $zero /* 320E4 800314E4 84880000 */ lh $t0, 0x0($a0) @@ -377,27 +377,27 @@ leaf func_800314DC .L800315F8: /* 321F8 800315F8 03E00008 */ jr $ra /* 321FC 800315FC 00000000 */ nop -.end func_800314DC +.end compute_grid_overlap_mask -leaf func_80031600 +leaf resolve_collisions /* 32200 80031600 24080001 */ addiu $t0, $zero, 0x1 /* 32204 80031604 A3A80001 */ sb $t0, 0x1($sp) - /* 32208 80031608 3C088012 */ lui $t0, %hi(D_8011D378) - /* 3220C 8003160C 8D08D378 */ lw $t0, %lo(D_8011D378)($t0) - /* 32210 80031610 3C018012 */ lui $at, %hi(D_8011B0F0) + /* 32208 80031608 3C088012 */ lui $t0, %hi(gNumCollisionCandidates) + /* 3220C 8003160C 8D08D378 */ lw $t0, %lo(gNumCollisionCandidates)($t0) + /* 32210 80031610 3C018012 */ lui $at, %hi(gHitWall) /* 32214 80031614 A3A00000 */ sb $zero, 0x0($sp) /* 32218 80031618 1100014C */ beqz $t0, .L80031B4C - /* 3221C 8003161C AC20B0F0 */ sw $zero, %lo(D_8011B0F0)($at) + /* 3221C 8003161C AC20B0F0 */ sw $zero, %lo(gHitWall)($at) .L80031620: /* 32220 80031620 00007025 */ or $t6, $zero, $zero .L80031624: - /* 32224 80031624 3C0D8012 */ lui $t5, %hi(D_8011D374) - /* 32228 80031628 3C098012 */ lui $t1, %hi(D_8011D370) - /* 3222C 8003162C 3C088012 */ lui $t0, %hi(D_8011D378) + /* 32224 80031624 3C0D8012 */ lui $t5, %hi(gCollisionSurfaces) + /* 32228 80031628 3C098012 */ lui $t1, %hi(gCollisionCandidates) + /* 3222C 8003162C 3C088012 */ lui $t0, %hi(gNumCollisionCandidates) /* 32230 80031630 00007825 */ or $t7, $zero, $zero - /* 32234 80031634 8DADD374 */ lw $t5, %lo(D_8011D374)($t5) - /* 32238 80031638 8D29D370 */ lw $t1, %lo(D_8011D370)($t1) - /* 3223C 8003163C 8D08D378 */ lw $t0, %lo(D_8011D378)($t0) + /* 32234 80031634 8DADD374 */ lw $t5, %lo(gCollisionSurfaces)($t5) + /* 32238 80031638 8D29D370 */ lw $t1, %lo(gCollisionCandidates)($t1) + /* 3223C 8003163C 8D08D378 */ lw $t0, %lo(gNumCollisionCandidates)($t0) .L80031640: /* 32240 80031640 8D2A0000 */ lw $t2, 0x0($t1) /* 32244 80031644 59400006 */ blezl $t2, .L80031660 @@ -517,8 +517,8 @@ leaf func_80031600 /* 323F8 800317F8 24010004 */ addiu $at, $zero, 0x4 /* 323FC 800317FC 10610012 */ beq $v1, $at, .L80031848 /* 32400 80031800 00000000 */ nop - /* 32404 80031804 3C038012 */ lui $v1, %hi(D_8011B0F4) - /* 32408 80031808 8C63B0F4 */ lw $v1, %lo(D_8011B0F4)($v1) + /* 32404 80031804 3C038012 */ lui $v1, %hi(gCollisionMode) + /* 32408 80031808 8C63B0F4 */ lw $v1, %lo(gCollisionMode)($v1) /* 3240C 8003180C 1460000E */ bnez $v1, .L80031848 /* 32410 80031810 00000000 */ nop /* 32414 80031814 C4A60000 */ lwc1 $f6, 0x0($a1) @@ -540,23 +540,23 @@ leaf func_80031600 /* 32450 80031850 460A1034 */ c.olt.s $f2, $f10 /* 32454 80031854 45000012 */ bc1f .L800318A0 /* 32458 80031858 00000000 */ nop - /* 3245C 8003185C 3C038012 */ lui $v1, %hi(D_8011B0F4) - /* 32460 80031860 8C63B0F4 */ lw $v1, %lo(D_8011B0F4)($v1) + /* 3245C 8003185C 3C038012 */ lui $v1, %hi(gCollisionMode) + /* 32460 80031860 8C63B0F4 */ lw $v1, %lo(gCollisionMode)($v1) /* 32464 80031864 24010002 */ addiu $at, $zero, 0x2 /* 32468 80031868 1061000D */ beq $v1, $at, .L800318A0 /* 3246C 8003186C 00000000 */ nop /* 32470 80031870 24030001 */ addiu $v1, $zero, 0x1 - /* 32474 80031874 3C018012 */ lui $at, %hi(D_8011B0F0) - /* 32478 80031878 AC23B0F0 */ sw $v1, %lo(D_8011B0F0)($at) + /* 32474 80031874 3C018012 */ lui $at, %hi(gHitWall) + /* 32478 80031878 AC23B0F0 */ sw $v1, %lo(gHitWall)($at) /* 3247C 8003187C C4460000 */ lwc1 $f6, 0x0($v0) - /* 32480 80031880 3C018012 */ lui $at, %hi(D_8011B0E4) - /* 32484 80031884 E426B0E4 */ swc1 $f6, %lo(D_8011B0E4)($at) + /* 32480 80031880 3C018012 */ lui $at, %hi(gCollisionNormalX) + /* 32484 80031884 E426B0E4 */ swc1 $f6, %lo(gCollisionNormalX)($at) /* 32488 80031888 C4460004 */ lwc1 $f6, 0x4($v0) - /* 3248C 8003188C 3C018012 */ lui $at, %hi(D_8011B0E8) - /* 32490 80031890 E426B0E8 */ swc1 $f6, %lo(D_8011B0E8)($at) + /* 3248C 8003188C 3C018012 */ lui $at, %hi(gCollisionNormalY) + /* 32490 80031890 E426B0E8 */ swc1 $f6, %lo(gCollisionNormalY)($at) /* 32494 80031894 C4460008 */ lwc1 $f6, 0x8($v0) - /* 32498 80031898 3C018012 */ lui $at, %hi(D_8011B0EC) - /* 3249C 8003189C E426B0EC */ swc1 $f6, %lo(D_8011B0EC)($at) + /* 32498 80031898 3C018012 */ lui $at, %hi(gCollisionNormalZ) + /* 3249C 8003189C E426B0EC */ swc1 $f6, %lo(gCollisionNormalZ)($at) .L800318A0: /* 324A0 800318A0 46120002 */ mul.s $f0, $f0, $f18 /* 324A4 800318A4 C4A60000 */ lwc1 $f6, 0x0($a1) @@ -569,19 +569,19 @@ leaf func_80031600 /* 324C0 800318C0 C4A60008 */ lwc1 $f6, 0x8($a1) /* 324C4 800318C4 46043101 */ sub.s $f4, $f6, $f4 .L800318C8: - /* 324C8 800318C8 3C038012 */ lui $v1, %hi(D_8011B0F0) - /* 324CC 800318CC 8C63B0F0 */ lw $v1, %lo(D_8011B0F0)($v1) + /* 324C8 800318C8 3C038012 */ lui $v1, %hi(gHitWall) + /* 324CC 800318CC 8C63B0F0 */ lw $v1, %lo(gHitWall)($v1) /* 324D0 800318D0 5460000B */ bnel $v1, $zero, .L80031900 /* 324D4 800318D4 81AC0000 */ lb $t4, 0x0($t5) /* 324D8 800318D8 C4460000 */ lwc1 $f6, 0x0($v0) - /* 324DC 800318DC 3C018012 */ lui $at, %hi(D_8011B0E4) - /* 324E0 800318E0 E426B0E4 */ swc1 $f6, %lo(D_8011B0E4)($at) + /* 324DC 800318DC 3C018012 */ lui $at, %hi(gCollisionNormalX) + /* 324E0 800318E0 E426B0E4 */ swc1 $f6, %lo(gCollisionNormalX)($at) /* 324E4 800318E4 C4460004 */ lwc1 $f6, 0x4($v0) - /* 324E8 800318E8 3C018012 */ lui $at, %hi(D_8011B0E8) - /* 324EC 800318EC E426B0E8 */ swc1 $f6, %lo(D_8011B0E8)($at) + /* 324E8 800318E8 3C018012 */ lui $at, %hi(gCollisionNormalY) + /* 324EC 800318EC E426B0E8 */ swc1 $f6, %lo(gCollisionNormalY)($at) /* 324F0 800318F0 C4460008 */ lwc1 $f6, 0x8($v0) - /* 324F4 800318F4 3C018012 */ lui $at, %hi(D_8011B0EC) - /* 324F8 800318F8 E426B0EC */ swc1 $f6, %lo(D_8011B0EC)($at) + /* 324F4 800318F4 3C018012 */ lui $at, %hi(gCollisionNormalZ) + /* 324F8 800318F8 E426B0EC */ swc1 $f6, %lo(gCollisionNormalZ)($at) /* 324FC 800318FC 81AC0000 */ lb $t4, 0x0($t5) .L80031900: /* 32500 80031900 80E20000 */ lb $v0, 0x0($a3) @@ -626,11 +626,11 @@ leaf func_80031600 /* 32584 80031984 A3AA0001 */ sb $t2, 0x1($sp) /* 32588 80031988 00007025 */ or $t6, $zero, $zero .L8003198C: - /* 3258C 8003198C 3C098012 */ lui $t1, %hi(D_8011D370) - /* 32590 80031990 3C088012 */ lui $t0, %hi(D_8011D378) + /* 3258C 8003198C 3C098012 */ lui $t1, %hi(gCollisionCandidates) + /* 32590 80031990 3C088012 */ lui $t0, %hi(gNumCollisionCandidates) /* 32594 80031994 00007825 */ or $t7, $zero, $zero - /* 32598 80031998 8D29D370 */ lw $t1, %lo(D_8011D370)($t1) - /* 3259C 8003199C 8D08D378 */ lw $t0, %lo(D_8011D378)($t0) + /* 32598 80031998 8D29D370 */ lw $t1, %lo(gCollisionCandidates)($t1) + /* 3259C 8003199C 8D08D378 */ lw $t0, %lo(gNumCollisionCandidates)($t0) .L800319A0: /* 325A0 800319A0 8D2A0000 */ lw $t2, 0x0($t1) /* 325A4 800319A4 59400006 */ blezl $t2, .L800319C0 @@ -750,4 +750,4 @@ leaf func_80031600 .L80031B4C: /* 3274C 80031B4C 03E00008 */ jr $ra /* 32750 80031B50 83A20000 */ lb $v0, 0x0($sp) -.end func_80031600 +.end resolve_collisions diff --git a/src/object_functions.c b/src/object_functions.c index a549b6fd..28ecd016 100644 --- a/src/object_functions.c +++ b/src/object_functions.c @@ -440,9 +440,9 @@ void obj_loop_laserbolt(Object *obj, s32 updateRate) { dir.z = obj->trans.z_position + (obj->z_velocity * updateRateF); radius = 9.0f; - func_80031130(1, &obj->trans.x_position, &dir.x, -1); + generate_collision_candidates(1, &obj->trans.x_position, &dir.x, -1); hasCollision = FALSE; - func_80031600(&obj->trans.x_position, (f32 *) &dir, &radius, &surface, TRUE, &hasCollision); + resolve_collisions((Vec3f *) &obj->trans.x_position, &dir, &radius, &surface, 1, &hasCollision); if (hasCollision) { obj->x_velocity = (dir.x - obj->trans.x_position) / updateRateF; obj->y_velocity = (dir.y - obj->trans.y_position) / updateRateF; @@ -707,7 +707,7 @@ void obj_loop_collectegg(Object *obj, s32 updateRate) { Object_CollectEgg *egg; Object *racerObj; Object_Racer *racer; - f32 dir[3]; + f32 targetPos[3]; f32 radius; f32 updateRateF; s32 hasCollision; @@ -724,20 +724,21 @@ void obj_loop_collectegg(Object *obj, s32 updateRate) { break; case EGG_MOVING: obj->trans.flags &= ~OBJ_FLAGS_INVISIBLE; - dir[0] = obj->trans.x_position + (obj->x_velocity * updateRateF); - dir[1] = obj->trans.y_position + (obj->y_velocity * updateRateF); - dir[2] = obj->trans.z_position + (obj->z_velocity * updateRateF); + targetPos[0] = obj->trans.x_position + (obj->x_velocity * updateRateF); + targetPos[1] = obj->trans.y_position + (obj->y_velocity * updateRateF); + targetPos[2] = obj->trans.z_position + (obj->z_velocity * updateRateF); radius = 9.0f; - func_80031130(1, &obj->trans.x_position, dir, -1); + generate_collision_candidates(1, &obj->trans.x_position, targetPos, -1); hasCollision = FALSE; surface = SURFACE_DEFAULT; - func_80031600(&obj->trans.x_position, dir, &radius, &surface, TRUE, &hasCollision); - obj->x_velocity = (dir[0] - obj->trans.x_position) / updateRateF; - obj->y_velocity = (dir[1] - obj->trans.y_position) / updateRateF; - obj->z_velocity = (dir[2] - obj->trans.z_position) / updateRateF; - obj->trans.x_position = dir[0]; - obj->trans.y_position = dir[1]; - obj->trans.z_position = dir[2]; + resolve_collisions((Vec3f *) &obj->trans.x_position, (Vec3f *) targetPos, &radius, &surface, 1, + &hasCollision); + obj->x_velocity = (targetPos[0] - obj->trans.x_position) / updateRateF; + obj->y_velocity = (targetPos[1] - obj->trans.y_position) / updateRateF; + obj->z_velocity = (targetPos[2] - obj->trans.z_position) / updateRateF; + obj->trans.x_position = targetPos[0]; + obj->trans.y_position = targetPos[1]; + obj->trans.z_position = targetPos[2]; obj->y_velocity -= 0.5; obj->x_velocity *= 0.98; obj->z_velocity *= 0.98; @@ -1377,7 +1378,7 @@ void obj_loop_stopwatchman(Object *obj, s32 updateRate) { if (index != 0) { index--; while (index >= 0) { - if ((water[index]->type != WATER_CALM) && (water[index]->type != WATER_WAVY) && + if ((water[index]->type != SURFACE_WATER_CALM) && (water[index]->type != SURFACE_WATER_WAVY) && (water[index]->rot.y > 0.0)) { obj->trans.y_position = water[index]->waveHeight; } @@ -3098,7 +3099,7 @@ void obj_loop_parkwarden(Object *obj, s32 updateRate) { if (var_a2 != 0) { var_a2--; while (var_a2 >= 0) { - if ((water[var_a2]->type != WATER_CALM) && (water[var_a2]->type != WATER_WAVY) && + if ((water[var_a2]->type != SURFACE_WATER_CALM) && (water[var_a2]->type != SURFACE_WATER_WAVY) && (water[var_a2]->rot.y > 0.0)) { obj->trans.y_position = water[var_a2]->waveHeight; } @@ -4304,14 +4305,14 @@ void obj_init_banana(Object *obj, UNUSED LevelObjectEntry_Banana *entry) { void obj_loop_banana(Object *obj, s32 updateRate) { Object *racerObj; Object_Racer *racer; - f32 tempPos[3]; + f32 targetPos[3]; f32 radius; f32 updateRateF; f32 velX; f32 velZ; - s32 sp48; + s32 hasCollision; s32 hitDist; - s8 sp43; + s8 surface; Object_Banana *banana; ObjPropertyBanana *properties; AudioPoint *prevSoundMask; @@ -4339,19 +4340,20 @@ void obj_loop_banana(Object *obj, s32 updateRate) { banana->unk0 = 0; } if (properties->status == BANANA_DROPPED) { - tempPos[0] = obj->trans.x_position + (obj->x_velocity * updateRateF); - tempPos[1] = obj->trans.y_position + (obj->y_velocity * updateRateF); - tempPos[2] = obj->trans.z_position + (obj->z_velocity * updateRateF); + targetPos[0] = obj->trans.x_position + (obj->x_velocity * updateRateF); + targetPos[1] = obj->trans.y_position + (obj->y_velocity * updateRateF); + targetPos[2] = obj->trans.z_position + (obj->z_velocity * updateRateF); radius = 8.0f; - func_80031130(1, &obj->trans.x_position, tempPos, -1); - sp48 = 0; - func_80031600(&obj->trans.x_position, tempPos, &radius, &sp43, TRUE, &sp48); - obj->x_velocity = (tempPos[0] - obj->trans.x_position) / updateRateF; - obj->y_velocity = (tempPos[1] - obj->trans.y_position) / updateRateF; - obj->z_velocity = (tempPos[2] - obj->trans.z_position) / updateRateF; - obj->trans.x_position = tempPos[0]; - obj->trans.y_position = tempPos[1]; - obj->trans.z_position = tempPos[2]; + generate_collision_candidates(1, &obj->trans.x_position, targetPos, -1); + hasCollision = 0; + resolve_collisions((Vec3f *) &obj->trans.x_position, (Vec3f *) targetPos, &radius, &surface, 1, + &hasCollision); + obj->x_velocity = (targetPos[0] - obj->trans.x_position) / updateRateF; + obj->y_velocity = (targetPos[1] - obj->trans.y_position) / updateRateF; + obj->z_velocity = (targetPos[2] - obj->trans.z_position) / updateRateF; + obj->trans.x_position = targetPos[0]; + obj->trans.y_position = targetPos[1]; + obj->trans.z_position = targetPos[2]; // Bananas dropped by planes will not have gravity. if (banana->droppedVehicleID != VEHICLE_PLANE) { obj->y_velocity -= 1.0; //!@Delta @@ -4370,7 +4372,7 @@ void obj_loop_banana(Object *obj, s32 updateRate) { if (velZ < 0.0) { velZ = -velZ; } - if (sp48 > 0 && velX < 0.5 && velZ < 0.5) { + if (hasCollision > 0 && velX < 0.5 && velZ < 0.5) { properties->status = BANANA_IDLE; } radius = -10000.0f; @@ -4849,12 +4851,12 @@ void weapon_projectile(Object *obj, s32 updateRate) { offset.z = obj->trans.z_position + (obj->z_velocity * updateRateF); if (weapon->weaponID != WEAPON_MAGNET_LEVEL_3) { radius = 16.0f; - func_80031130(1, &obj->trans.x_position, (f32 *) &offset, -1); + generate_collision_candidates(1, &obj->trans.x_position, (f32 *) &offset, -1); hasCollision = FALSE; surface = SURFACE_NONE; - func_80031600(&obj->trans.x_position, (f32 *) &offset, &radius, &surface, TRUE, &hasCollision); + resolve_collisions((Vec3f *) &obj->trans.x_position, &offset, &radius, &surface, 1, &hasCollision); if (hasCollision > 0) { - if (func_8002ACD4(&diffX, &diffY, &diffZ)) { + if (get_collision_normal(&diffX, &diffY, &diffZ)) { obj->properties.projectile.timer = 0; } } @@ -5153,10 +5155,10 @@ void weapon_trap(Object *weaponObj, s32 updateRate) { intendedPos.y = weaponObj->trans.y_position + (weaponObj->y_velocity * updateRateF); intendedPos.z = weaponObj->trans.z_position + (weaponObj->z_velocity * updateRateF); radius = 9.0f; - func_80031130(1, &weaponObj->trans.x_position, &intendedPos.x, -1); + generate_collision_candidates(1, &weaponObj->trans.x_position, &intendedPos.x, -1); hasCollision = FALSE; - surface = -1; - func_80031600(&weaponObj->trans.x_position, &intendedPos.x, &radius, &surface, 1, &hasCollision); + surface = SURFACE_NONE; + resolve_collisions((Vec3f *) &weaponObj->trans.x_position, &intendedPos, &radius, &surface, 1, &hasCollision); weaponObj->x_velocity = (intendedPos.x - weaponObj->trans.x_position) / updateRateF; weaponObj->y_velocity = (intendedPos.y - weaponObj->trans.y_position) / updateRateF; weaponObj->z_velocity = (intendedPos.z - weaponObj->trans.z_position) / updateRateF; @@ -5500,7 +5502,7 @@ void obj_loop_texscroll(Object *obj, s32 updateRate) { if (curBatch[j].textureIndex == texScroll->textureIndex) { for (tri = curBatch[j].facesOffset; tri < curBatch[j + 1].facesOffset; tri++) { curTriangle = &curBlock[i].triangles[tri]; - if (!(curTriangle->flags & 0x80)) { + if (!(curTriangle->flags & TRI_FLAG_80)) { if (vShift < curTriangle->uv0.v) { curTriangle->uv0.v -= vShift; curTriangle->uv1.v -= vShift; diff --git a/src/object_models.c b/src/object_models.c index 5b0e6540..43842527 100644 --- a/src/object_models.c +++ b/src/object_models.c @@ -413,7 +413,7 @@ void func_8006017C(ObjectModel *arg0) { for (i = 0; i < arg0->numberOfBatches; i++) { facesOffset = arg0->batches[i].facesOffset; nextFacesOffset = arg0->batches[i + 1].facesOffset; - if (arg0->batches[i].flags & 0x200) { + if (arg0->batches[i].flags & RENDER_NO_COLLISION) { continue; } s4 += nextFacesOffset - facesOffset; @@ -437,7 +437,7 @@ void func_8006017C(ObjectModel *arg0) { facesOffset = arg0->batches[i].facesOffset; verticesOffset = arg0->batches[i].verticesOffset; nextFacesOffset = arg0->batches[i + 1].facesOffset; - if (arg0->batches[i].flags & 0x200) { + if (arg0->batches[i].flags & RENDER_NO_COLLISION) { nextFacesOffset = facesOffset - 1; } @@ -491,7 +491,7 @@ void func_8006017C(ObjectModel *arg0) { facesOffset = arg0->batches[i].facesOffset; verticesOffset = arg0->batches[i].verticesOffset; nextFacesOffset = arg0->batches[i + 1].facesOffset; - if (arg0->batches[i].flags & 0x200) { + if (arg0->batches[i].flags & RENDER_NO_COLLISION) { nextFacesOffset = facesOffset - 1; } @@ -574,7 +574,7 @@ void func_80060910(ObjectModel *mdl) { startTri = mdl->batches[i].facesOffset; vertOffset = mdl->batches[i].verticesOffset; endTri = mdl->batches[i + 1].facesOffset; - if (mdl->batches[i].flags & RENDER_UNK_200) { + if (mdl->batches[i].flags & RENDER_NO_COLLISION) { endTri = startTri - 1; } @@ -619,7 +619,7 @@ s32 func_80060AC8(ObjectModel *mdl, s32 arg1, s32 arg2, s32 arg3, s32 *outBatchI startTri = mdl->batches[i].facesOffset; vertOffset = mdl->batches[i].verticesOffset; endTri = mdl->batches[i + 1].facesOffset; - if (mdl->batches[i].flags & RENDER_UNK_200) { + if (mdl->batches[i].flags & RENDER_NO_COLLISION) { endTri = startTri - 1; } for (triIndex = startTri; triIndex < endTri; triIndex++, count++) { diff --git a/src/objects.c b/src/objects.c index 01ae9942..6ce3307a 100644 --- a/src/objects.c +++ b/src/objects.c @@ -10052,18 +10052,18 @@ CheckpointNode *func_800230D0(Object *obj, Object_Racer *racer) { racer->checkpoint = 0; racer->courseCheckpoint = racer->lap * gNumberOfCheckpoints; obj->trans.rotation.y_rotation = racer->steerVisualRotation; - racer->unkD8.x = obj->trans.x_position; - racer->unkD8.y = obj->trans.y_position + 15.0f; - racer->unkD8.z = obj->trans.z_position; - racer->unkE4.x = obj->trans.x_position; - racer->unkE4.y = obj->trans.y_position + 15.0f; - racer->unkE4.z = obj->trans.z_position; - racer->unkF0.x = obj->trans.x_position; - racer->unkF0.y = obj->trans.y_position + 15.0f; - racer->unkF0.z = obj->trans.z_position; - racer->unkFC.x = obj->trans.x_position; - racer->unkFC.y = obj->trans.y_position + 15.0f; - racer->unkFC.z = obj->trans.z_position; + racer->unkD8[0] = obj->trans.x_position; + racer->unkD8[1] = obj->trans.y_position + 15.0f; + racer->unkD8[2] = obj->trans.z_position; + racer->unkD8[3] = obj->trans.x_position; + racer->unkD8[4] = obj->trans.y_position + 15.0f; + racer->unkD8[5] = obj->trans.z_position; + racer->unkD8[6] = obj->trans.x_position; + racer->unkD8[7] = obj->trans.y_position + 15.0f; + racer->unkD8[8] = obj->trans.z_position; + racer->unkD8[9] = obj->trans.x_position; + racer->unkD8[10] = obj->trans.y_position + 15.0f; + racer->unkD8[11] = obj->trans.z_position; obj->interactObj->x_position = obj->trans.x_position; obj->interactObj->y_position = obj->trans.y_position; obj->interactObj->z_position = obj->trans.z_position; diff --git a/src/racer.c b/src/racer.c index 41a392f6..4132aa5e 100644 --- a/src/racer.c +++ b/src/racer.c @@ -2084,7 +2084,7 @@ void func_80046524(s32 updateRate, f32 updateRateF, Object *obj, Object_Racer *r // clang-format off // the backslash here is relevant for the match wave_properties = get_wave_properties(obj->trans.y_position, &waterHeight, &water_rotation); \ - if (wave_properties != 0) { + if (wave_properties != SURFACE_DEFAULT) { // clang-format on velocity = racer->velocity; if (velocity < 0.0f) { @@ -2480,7 +2480,7 @@ f32 rotate_racer_in_water(Object *obj, Object_Racer *racer, Vec3f *pos, s8 arg3, f32 updateRateF; updateRateF = updateRate; - if (arg3 == 14) { + if (arg3 == SURFACE_WATER_WAVY) { velocity = racer->velocity; if (velocity < 0.0f) { velocity = -velocity; @@ -3700,7 +3700,7 @@ void func_8004CC20(s32 updateRate, f32 updateRateF, Object *racerObj, Object_Rac racer->boostTimer = 4; } racer->boostType = BOOST_NONE; - func_8002ACC8(2); + set_collision_mode(COLLISION_MODE_NO_WALLS); D_8011D550 = 0; gCurrentCarSteerVel = 0; D_8011D558 = 0; @@ -4046,18 +4046,18 @@ void obj_init_racer(Object *obj, LevelObjectEntry_Racer *racer) { tempRacer->unkC4 = 0.5f; if (1) {} // Fakematch tempRacer->cameraYaw = tempRacer->steerVisualRotation; - tempRacer->unkD8.x = obj->trans.x_position; - tempRacer->unkD8.y = obj->trans.y_position + 30.0f; - tempRacer->unkD8.z = obj->trans.z_position; - tempRacer->unkE4.x = obj->trans.x_position; - tempRacer->unkE4.y = obj->trans.y_position + 30.0f; - tempRacer->unkE4.z = obj->trans.z_position; - tempRacer->unkF0.x = obj->trans.x_position; - tempRacer->unkF0.y = obj->trans.y_position + 30.0f; - tempRacer->unkF0.z = obj->trans.z_position; - tempRacer->unkFC.x = obj->trans.x_position; - tempRacer->unkFC.y = obj->trans.y_position + 30.0f; - tempRacer->unkFC.z = obj->trans.z_position; + tempRacer->unkD8[0] = obj->trans.x_position; + tempRacer->unkD8[1] = obj->trans.y_position + 30.0f; + tempRacer->unkD8[2] = obj->trans.z_position; + tempRacer->unkD8[3] = obj->trans.x_position; + tempRacer->unkD8[4] = obj->trans.y_position + 30.0f; + tempRacer->unkD8[5] = obj->trans.z_position; + tempRacer->unkD8[6] = obj->trans.x_position; + tempRacer->unkD8[7] = obj->trans.y_position + 30.0f; + tempRacer->unkD8[8] = obj->trans.z_position; + tempRacer->unkD8[9] = obj->trans.x_position; + tempRacer->unkD8[10] = obj->trans.y_position + 30.0f; + tempRacer->unkD8[11] = obj->trans.z_position; tempRacer->prev_x_position = obj->trans.x_position; tempRacer->prev_y_position = obj->trans.y_position; tempRacer->prev_z_position = obj->trans.z_position; @@ -4373,7 +4373,7 @@ void update_player_racer(Object *obj, s32 updateRate) { func_8002B0F4(obj->segmentID, obj->trans.x_position, obj->trans.z_position, &gRacerCurrentWave); if (gRacerWaveCount) { for (i = 0; i < gRacerWaveCount; i++) { - if (gRacerCurrentWave[i]->type == WATER_UNK_F) { + if (gRacerCurrentWave[i]->type == SURFACE_WATER_UNK_F) { if (gRacerCurrentWave[i]->waveHeight < gCurrentCourseHeight) { gCurrentCourseHeight = gRacerCurrentWave[i]->waveHeight; } @@ -4383,7 +4383,7 @@ void update_player_racer(Object *obj, s32 updateRate) { if (tempRacer->vehicleID != VEHICLE_HOVERCRAFT) { waterHeight = -10000.0f; gRacerWaveType = get_wave_properties(obj->trans.y_position, &waterHeight, &gCurrentRacerWaterPos); - if (gRacerWaveType) { + if (gRacerWaveType != SURFACE_DEFAULT) { if (obj->trans.y_position - 5.0f < waterHeight) { tempRacer->waterTimer = 5; tempRacer->buoyancy = waterHeight - (obj->trans.y_position - 5.0f); @@ -4403,7 +4403,7 @@ void update_player_racer(Object *obj, s32 updateRate) { obj->interactObj->flags &= ~INTERACT_FLAGS_UNK_0010; } } - func_8002ACC8(0); + set_collision_mode(COLLISION_MODE_DEFAULT); switch (tempRacer->vehicleID) { case VEHICLE_CAR: func_8004F7F4(updateRate, updateRateF, obj, tempRacer); @@ -6606,7 +6606,7 @@ void update_car_velocity_ground(Object *obj, Object_Racer *racer, s32 updateRate // Related to ground collision? void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { s32 pad[3]; - s32 sp190; + s32 numCollisions; s32 flags; s32 mask; s32 sp184; @@ -6632,7 +6632,7 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { if (gCurrentCourseHeight < racerObj->trans.y_position) { racerObj->trans.y_position = gCurrentCourseHeight; - func_8002ACC8(1); + set_collision_mode(COLLISION_MODE_1); } sp130 = FALSE; gCurrentRacerTransform.rotation.y_rotation = racerObj->trans.rotation.y_rotation; @@ -6651,12 +6651,12 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { sp58[i] = -1; } - sp190 = 0; + numCollisions = 0; D_8011D548 = 0; D_8011D54C = 0; flags = 0; if (racer->playerIndex != PLAYER_COMPUTER || racer->vehicleIDPrev < VEHICLE_BOSSES) { - flags = func_80017248(racerObj, 4, &sp190, &racer->unkD8, sp134, spE0, sp58); + flags = func_80017248(racerObj, 4, &numCollisions, (Vec3f *) racer->unkD8, sp134, spE0, sp58); } if (flags & 0x80) { for (i = 0; i < 4; i++) { @@ -6681,10 +6681,10 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { sp5C = 1; } } - func_80031130(4, (f32 *) &racer->unkD8, sp134, racer->vehicleID); - sp190 = 0; - racer->unk1E3 = func_80031600((f32 *) &racer->unkD8, sp134, spE0, sp58, 4, &sp190); - sp184 = func_8002ACD4(&sp180, &sp178, &sp17C); + generate_collision_candidates(4, racer->unkD8, sp134, racer->vehicleID); + numCollisions = 0; + racer->unk1E3 = resolve_collisions((Vec3f *) racer->unkD8, (Vec3f *) sp134, spE0, sp58, 4, &numCollisions); + sp184 = get_collision_normal(&sp180, &sp178, &sp17C); if (sp184 != 0) { temp_s16 = (u16) arctan2_f(sp180 * 255.0f, sp17C * 255.0f); temp_s16 -= racerObj->trans.rotation.y_rotation; @@ -6717,7 +6717,7 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { } } } - if (sp5C && sp190 >= 3) { + if (sp5C && numCollisions >= 3) { if (racer->playerIndex != PLAYER_COMPUTER && racer->unk20 == 0 && racer->shieldTimer <= 0) { sound_play(SOUND_SPLAT, &racer->unk20); } @@ -6740,7 +6740,7 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { } for (i = 0; i < 12; i++) { - ((f32 *) &racer->unkD8)[i] = sp134[i]; + racer->unkD8[i] = sp134[i]; } for (i = 0; i < 4; i++) { racer->wheel_surfaces[i] = sp58[i]; @@ -6749,9 +6749,9 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { racerObj->trans.y_position = 0; racerObj->trans.z_position = 0; for (i = 0; i < 12; i += 3) { - racerObj->trans.x_position = racerObj->trans.x_position + ((f32 *) &racer->unkD8)[i + 0]; - racerObj->trans.y_position = racerObj->trans.y_position + ((f32 *) &racer->unkD8)[i + 1]; - racerObj->trans.z_position = racerObj->trans.z_position + ((f32 *) &racer->unkD8)[i + 2]; + racerObj->trans.x_position = racerObj->trans.x_position + racer->unkD8[i + 0]; + racerObj->trans.y_position = racerObj->trans.y_position + racer->unkD8[i + 1]; + racerObj->trans.z_position = racerObj->trans.z_position + racer->unkD8[i + 2]; } racerObj->trans.x_position /= 4; racerObj->trans.y_position /= 4; @@ -6766,8 +6766,8 @@ void func_80054FD0(Object *racerObj, Object_Racer *racer, s32 updateRate) { gCurrentRacerTransform.z_position = -racerObj->trans.z_position; mtxf_from_inverse_transform(&sp60, &gCurrentRacerTransform); for (i = 0; i < 4; i++) { - mtxf_transform_point(&sp60, ((f32 *) &racer->unkD8)[i * 3 + 0], ((f32 *) &racer->unkD8)[i * 3 + 1], - ((f32 *) &racer->unkD8)[i * 3 + 2], &sp11C[i], &sp108[i], &spF4[i]); + mtxf_transform_point(&sp60, racer->unkD8[3 * i], racer->unkD8[3 * i + 1], racer->unkD8[3 * i + 2], &sp11C[i], + &sp108[i], &spF4[i]); } if (racer->vehicleID != VEHICLE_LOOPDELOOP) { sp180 = sp11C[0] + sp11C[1]; @@ -6854,7 +6854,7 @@ void onscreen_ai_racer_physics(Object *obj, Object_Racer *racer, UNUSED s32 upda hasCollision = FALSE; flags = 0; if (racer->playerIndex != PLAYER_COMPUTER || racer->vehicleIDPrev < VEHICLE_BOSSES) { - flags = func_80017248(obj, 1, &hasCollision, &racer->unkD8, &tempPos.x, &radius, &surface); + flags = func_80017248(obj, 1, &hasCollision, (Vec3f *) racer->unkD8, &tempPos.x, &radius, &surface); } if (flags & 0x80) { D_8011D548 = tempPos.x - obj->trans.x_position; @@ -6865,9 +6865,9 @@ void onscreen_ai_racer_physics(Object *obj, Object_Racer *racer, UNUSED s32 upda if (flags && tempPos.y < obj->trans.y_position - 4.0) { shouldSquish = TRUE; } - func_80031130(1, &racer->unkD8.x, &tempPos.x, racer->vehicleID); + generate_collision_candidates(1, racer->unkD8, &tempPos.x, racer->vehicleID); hasCollision = FALSE; - racer->unk1E3 = func_80031600(&racer->unkD8.x, &tempPos.x, &radius, &surface, TRUE, &hasCollision); + racer->unk1E3 = resolve_collisions((Vec3f *) racer->unkD8, &tempPos, &radius, &surface, 1, &hasCollision); racer->unk1E4 = flags; racer->unk1E3 |= flags; racer->groundedWheels = 0; @@ -6883,18 +6883,18 @@ void onscreen_ai_racer_physics(Object *obj, Object_Racer *racer, UNUSED s32 upda } } for (i = 0; i < 3; i++) { - racer->unkD8.f[i] = tempPos.f[i]; + racer->unkD8[i] = tempPos.f[i]; } i = 1; // Fakematch racer->wheel_surfaces[0] = surface; racer->wheel_surfaces[1] = surface; racer->wheel_surfaces[2] = surface; racer->wheel_surfaces[3] = surface; - obj->trans.x_position = racer->unkD8.x; - obj->trans.y_position = racer->unkD8.y; - obj->trans.z_position = racer->unkD8.z; + obj->trans.x_position = racer->unkD8[0]; + obj->trans.y_position = racer->unkD8[1]; + obj->trans.z_position = racer->unkD8[2]; if (racer->groundedWheels) { - func_8002ACD4(&xTemp, &yTemp, &zTemp); + get_collision_normal(&xTemp, &yTemp, &zTemp); angleX = sins_f(-obj->trans.rotation.y_rotation); angleZ = coss_f(-obj->trans.rotation.y_rotation); distance = (xTemp * angleZ) + (zTemp * angleX); @@ -8787,7 +8787,7 @@ void update_AI_racer(Object *obj, Object_Racer *racer, s32 updateRate, f32 updat gRacerWaveCount = func_8002B0F4(obj->segmentID, obj->trans.x_position, obj->trans.z_position, &gRacerCurrentWave); } - func_8002ACC8(0); + set_collision_mode(COLLISION_MODE_DEFAULT); if (racer->approachTarget != NULL || gRaceStartTimer != 0 || racer->bubbleTrapTimer > 0) { gCurrentStickX = 0; gCurrentStickY = 0; @@ -9212,18 +9212,18 @@ void func_8005B818(Object *obj, Object_Racer *racer, s32 updateRate, f32 updateR racer->carBobY = 0.0f; racer->carBobZ = 0.0f; obj->y_velocity = 0.0f; - racer->unkD8.x = obj->trans.x_position; - racer->unkD8.y = obj->trans.y_position; - racer->unkD8.z = obj->trans.z_position; - racer->unkE4.x = obj->trans.x_position; - racer->unkE4.y = obj->trans.y_position; - racer->unkE4.z = obj->trans.z_position; - racer->unkF0.x = obj->trans.x_position; - racer->unkF0.y = obj->trans.y_position; - racer->unkF0.z = obj->trans.z_position; - racer->unkFC.x = obj->trans.x_position; - racer->unkFC.y = obj->trans.y_position; - racer->unkFC.z = obj->trans.z_position; + racer->unkD8[0] = obj->trans.x_position; + racer->unkD8[1] = obj->trans.y_position; + racer->unkD8[2] = obj->trans.z_position; + racer->unkD8[3] = obj->trans.x_position; + racer->unkD8[4] = obj->trans.y_position; + racer->unkD8[5] = obj->trans.z_position; + racer->unkD8[6] = obj->trans.x_position; + racer->unkD8[7] = obj->trans.y_position; + racer->unkD8[8] = obj->trans.z_position; + racer->unkD8[9] = obj->trans.x_position; + racer->unkD8[10] = obj->trans.y_position; + racer->unkD8[11] = obj->trans.z_position; obj->particleEmittersEnabled = OBJ_EMIT_NONE; update_vehicle_particles(obj, updateRate); } diff --git a/src/textures_sprites.h b/src/textures_sprites.h index e6eeef1c..556af38d 100644 --- a/src/textures_sprites.h +++ b/src/textures_sprites.h @@ -56,7 +56,7 @@ enum RenderFlags { RENDER_Z_UPDATE = (1 << 8), // Updates the depth buffer when rendering. RENDER_HIDDEN = (1 << 8), // Shares a spot with Z update, as that's generally a given with level geometry. RENDER_PRESERVE_COVERAGE = (1 << 9), // Coverage is used to help smooth the image. This won't write over existing coverage values. - RENDER_UNK_200 = (1 << 9), // Shares a slot with coverage, being normal geometry doesn't care about coverage. + RENDER_NO_COLLISION = (1 << 9), // Shares a slot with coverage, being normal geometry doesn't care about coverage. RENDER_LINE_SWAP = (1 << 10), // Texture has swapped lines, for speed. Makes the load process slightly different. RENDER_DECAL = (1 << 11), // Projects a surface on existing geometry, taking precedent to not zfight. RENDER_UNK_0001000 = (1 << 12), diff --git a/src/tracks.c b/src/tracks.c index 5c7bd879..babb6f1e 100644 --- a/src/tracks.c +++ b/src/tracks.c @@ -86,11 +86,11 @@ s8 gDrawLevelSegments; u8 gVoidColourR; // R of RGB u8 gVoidColourG; // G of RGB u8 gVoidColourB; // B of RGB -f32 D_8011B0E4; -f32 D_8011B0E8; -f32 D_8011B0EC; -s32 D_8011B0F0; -s32 D_8011B0F4; +f32 gCollisionNormalX; +f32 gCollisionNormalY; +f32 gCollisionNormalZ; +s32 gHitWall; +s32 gCollisionMode; s32 D_8011B0F8; // gIsInCutscene? s32 gAntiAliasing; s32 D_8011B100; @@ -143,12 +143,12 @@ Vertex *gCurrShadowVerts; UNUSED s32 D_8011D34C; ShadowHeapProperties *gShadowHeapData[2 + 2]; // General data for shadows. Texture and geometry size. ShadowHeapProperties *gCurrShadowHeapData; -s32 gShadowTail; // Position in the heap the shadow data ends at. -s32 gNewShadowTriCount; // xOffset? -s32 gNewShadowVtxCount; // yOffset? -u16 **D_8011D370; // Allocated 0x7D0 -s32 *D_8011D374; -s32 D_8011D378; +s32 gShadowTail; // Position in the heap the shadow data ends at. +s32 gNewShadowTriCount; // xOffset? +s32 gNewShadowVtxCount; // yOffset? +s32 *gCollisionCandidates; // Allocated 0x7D0 +s8 *gCollisionSurfaces; +s32 gNumCollisionCandidates; s32 gScenePlayerViewports; UNUSED f32 gCurrBBoxDistanceToCamera; // Used in a comparison check, but functionally unused. u32 gWaveBlockCount; @@ -767,7 +767,7 @@ void func_80026430(LevelModelSegment *segment, f32 arg1, f32 arg2, f32 arg3) { currFaceOffset = segment->batches[i].facesOffset; verticesOffset = segment->batches[i].verticesOffset; nextFaceOffset = segment->batches[i + 1].facesOffset; - if (segment->batches[i].flags & (RENDER_HIDDEN | RENDER_UNK_200)) { + if (segment->batches[i].flags & (RENDER_HIDDEN | RENDER_NO_COLLISION)) { currFaceOffset = nextFaceOffset; } for (j = currFaceOffset; j < nextFaceOffset; j++) { @@ -840,13 +840,13 @@ void func_80026430(LevelModelSegment *segment, f32 arg1, f32 arg2, f32 arg3) { var_s0 = 1; } if (var_s0 != 0) { - var_t0 = (segment->unk14[j].triangleIndex << 2); - temp = (spB0[0] + D_8011D4A0) * segment->unk18[var_t0]; - temp += spB8[0] * segment->unk18[var_t0 + 1]; - temp += (spA8[0] + D_8011D4A4) * segment->unk18[var_t0 + 2]; - temp += segment->unk18[var_t0 + 3]; + var_t0 = (segment->collisionFacets[j].basePlaneIndex << 2); + temp = (spB0[0] + D_8011D4A0) * segment->collisionPlanes[var_t0]; + temp += spB8[0] * segment->collisionPlanes[var_t0 + 1]; + temp += (spA8[0] + D_8011D4A4) * segment->collisionPlanes[var_t0 + 2]; + temp += segment->collisionPlanes[var_t0 + 3]; var_s0 = (temp > 0.0) << 2; - if (segment->unk18[var_t0 + 1] < 0.0f) { + if (segment->collisionPlanes[var_t0 + 1] < 0.0f) { var_s0 |= 1; } if (spC4[0] == spC4[1]) { @@ -1128,14 +1128,14 @@ s32 func_80027568(void) { if (currentObjRacer == NULL) { return FALSE; } - func_80031130(1, ¤tObjRacer->trans.x_position, &gSceneActiveCamera->trans.x_position, -1); + generate_collision_candidates(1, ¤tObjRacer->trans.x_position, &gSceneActiveCamera->trans.x_position, -1); ret = FALSE; // bug? var_ra can be undefined? - for (var_t4 = 0; var_t4 < D_8011D378 && ret == FALSE; var_t4++) { - if ((s32) D_8011D370[var_t4] > 0) { - var_ra = (Unk80027568_1 *) PHYS_TO_K0(D_8011D370[var_t4]); + for (var_t4 = 0; var_t4 < gNumCollisionCandidates && ret == FALSE; var_t4++) { + if ((s32) gCollisionCandidates[var_t4] > 0) { + var_ra = (Unk80027568_1 *) PHYS_TO_K0(gCollisionCandidates[var_t4]); } else { - var_t2 = D_8011D370[var_t4]; + var_t2 = gCollisionCandidates[var_t4]; vector = var_ra->unk18; vector += var_t2[0]; new_var = vector->x; @@ -2419,22 +2419,22 @@ UNUSED void func_8002AC00(s32 arg0, s32 arg1, s32 arg2) { } } -// These types are probably wrong because the vars are likely still unidentified structs, but the code matches still. -UNUSED void dayGetTrackFade(s32 *arg0, s32 *arg1, s32 *arg2) { - *arg0 = (unsigned) D_8011D378; - *arg1 = (unsigned) D_8011D370; - *arg2 = (unsigned) D_8011D374; +UNUSED void get_collision_candidate_data(s32 *numCollsionCandidates, s32 **collisionCandidates, + s8 **collisionSurfaces) { + *numCollsionCandidates = gNumCollisionCandidates; + *collisionCandidates = gCollisionCandidates; + *collisionSurfaces = gCollisionSurfaces; } -void func_8002ACC8(s32 arg0) { - D_8011B0F4 = arg0; +void set_collision_mode(s32 mode) { + gCollisionMode = mode; } -s32 func_8002ACD4(f32 *arg0, f32 *arg1, f32 *arg2) { - *arg0 = D_8011B0E4; - *arg1 = D_8011B0E8; - *arg2 = D_8011B0EC; - return D_8011B0F0; +s32 get_collision_normal(f32 *outX, f32 *outY, f32 *outZ) { + *outX = gCollisionNormalX; + *outY = gCollisionNormalY; + *outZ = gCollisionNormalZ; + return gHitWall; } /** @@ -2458,18 +2458,18 @@ s32 get_wave_properties(f32 yPos, f32 *waterHeight, Vec3f *rotation) { } wave = gTrackWaves; for (var_a0 = i = 0; i < len; i++) { - if (wave[i]->type == WATER_CALM || wave[i]->type == WATER_WAVY) { + if (wave[i]->type == SURFACE_WATER_CALM || wave[i]->type == SURFACE_WATER_WAVY) { var_a0++; } } if (var_a0 == 0) { - return 0; + return SURFACE_DEFAULT; } wave = gTrackWaves; index = -1; for (i = 0; i < len; i++) { height = wave[i]->waveHeight; - if (wave[i]->type == WATER_CALM || wave[i]->type == WATER_WAVY) { + if (wave[i]->type == SURFACE_WATER_CALM || wave[i]->type == SURFACE_WATER_WAVY) { if (yPos < height + 25.0 && (wave[i]->rot.y > 0.5 || var_a0 == 1)) { index = i; } @@ -2478,7 +2478,7 @@ s32 get_wave_properties(f32 yPos, f32 *waterHeight, Vec3f *rotation) { } } if (index < 0) { - return 0; + return SURFACE_DEFAULT; } *waterHeight = gTrackWaves[index]->waveHeight; if (rotation != NULL) { @@ -2529,7 +2529,7 @@ s32 func_8002B0F4(s32 levelSegmentIndex, f32 xIn, f32 zIn, WaterProperties ***ar s32 sp108; s32 spB0[8]; - s32 temp_s2; + s32 surface; s32 var_fp; D_8011D308 = 0; @@ -2578,12 +2578,13 @@ s32 func_8002B0F4(s32 levelSegmentIndex, f32 xIn, f32 zIn, WaterProperties ***ar for (batchNum = 0; batchNum < currentSegment->numberOfBatches; batchNum++) { currentBatch = ¤tSegment->batches[batchNum]; - temp_s2 = gCurrentLevelModel->textures[currentBatch->textureIndex].unk7; + surface = gCurrentLevelModel->textures[currentBatch->textureIndex].surfaceType; currentFaceOffset = currentBatch->facesOffset; nextFaceOffset = currentBatch[1].facesOffset; currentVerticesOffset = currentBatch->verticesOffset; - if (temp_s2 != 11 && temp_s2 != 15 && (currentBatch->flags & (RENDER_HIDDEN | RENDER_UNK_200))) { + if (surface != SURFACE_WATER_CALM && surface != SURFACE_WATER_UNK_F && + (currentBatch->flags & (RENDER_HIDDEN | RENDER_NO_COLLISION))) { currentFaceOffset = nextFaceOffset; } @@ -2606,14 +2607,14 @@ s32 func_8002B0F4(s32 levelSegmentIndex, f32 xIn, f32 zIn, WaterProperties ***ar temp_ra_3 = ((((XInInt - vert1X) * (vert3Z - vert1Z)) - ((vert3X - vert1X) * (ZInInt - vert1Z))) >= 0); if (temp_ra_1 == temp_ra_2 && temp_ra_2 != temp_ra_3) { - temp = currentSegment->unk14[faceNum].triangleIndex; - temp_v1_4 = (f32 *) ¤tSegment->unk18[temp * 4]; + temp = currentSegment->collisionFacets[faceNum].basePlaneIndex; + temp_v1_4 = (f32 *) ¤tSegment->collisionPlanes[temp * 4]; tempVec4f.x = temp_v1_4[0]; tempVec4f.y = temp_v1_4[1]; tempVec4f.z = temp_v1_4[2]; tempVec4f.w = temp_v1_4[3]; if (tempVec4f.y != 0.0) { - D_8011D128[yOutCount].type = temp_s2; + D_8011D128[yOutCount].type = surface; D_8011D128[yOutCount].waveHeight = -(((tempVec4f.x * xIn) + (tempVec4f.z * zIn) + tempVec4f.w) / tempVec4f.y); D_8011D128[yOutCount].rot.x = tempVec4f.x; @@ -2634,7 +2635,7 @@ s32 func_8002B0F4(s32 levelSegmentIndex, f32 xIn, f32 zIn, WaterProperties ***ar } if (levelSegmentIndex >= 0 && levelSegmentIndex < gCurrentLevelModel->numberOfSegments) { - D_8011D128[yOutCount].type = WATER_WAVY; + D_8011D128[yOutCount].type = SURFACE_WATER_WAVY; if (gCurrentLevelModel->segments[levelSegmentIndex].hasWaves && gWaveBlockCount != 0) { D_8011D128[yOutCount].waveHeight = func_800BB2F4(levelSegmentIndex, xIn, zIn, &D_8011D128[yOutCount].rot); } else { @@ -2796,11 +2797,11 @@ s32 func_8002BAB0(s32 levelSegmentIndex, f32 xIn, f32 zIn, f32 *yOut) { temp_ra_3 = (((XInInt - vert1X) * (vert3Z - vert1Z)) - ((vert3X - vert1X) * (ZInInt - vert1Z))) >= 0; var_v0 = faceNum; // fake? if (temp_ra_1 == temp_ra_2 && temp_ra_2 != temp_ra_3) { - temp = currentSegment->unk14[faceNum].triangleIndex; - tempVec4f.x = currentSegment->unk18[4 * temp + 0]; - tempVec4f.y = currentSegment->unk18[4 * temp + 1]; - tempVec4f.z = currentSegment->unk18[4 * temp + 2]; - tempVec4f.w = currentSegment->unk18[4 * temp + 3]; + temp = currentSegment->collisionFacets[faceNum].basePlaneIndex; + tempVec4f.x = currentSegment->collisionPlanes[4 * temp + 0]; + tempVec4f.y = currentSegment->collisionPlanes[4 * temp + 1]; + tempVec4f.z = currentSegment->collisionPlanes[4 * temp + 2]; + tempVec4f.w = currentSegment->collisionPlanes[4 * temp + 3]; if (tempVec4f.y != 0.0) { yOut[yOutCount] = -(((tempVec4f.x * xIn) + (tempVec4f.z * zIn) + tempVec4f.w) / tempVec4f.y); yOutCount++; @@ -2835,9 +2836,9 @@ void generate_track(s32 modelId) { set_texture_colour_tag(COLOUR_TAG_GREEN); gTrackModelHeap = mempool_alloc_safe(LEVEL_MODEL_MAX_SIZE, COLOUR_TAG_YELLOW); gCurrentLevelModel = gTrackModelHeap; - D_8011D370 = mempool_alloc_safe(0x7D0, COLOUR_TAG_YELLOW); - D_8011D374 = mempool_alloc_safe(0x1F4, COLOUR_TAG_YELLOW); - D_8011D378 = 0; + gCollisionCandidates = mempool_alloc_safe(MAX_COLLISION_CANDIDATES * 4, COLOUR_TAG_YELLOW); + gCollisionSurfaces = mempool_alloc_safe(MAX_COLLISION_CANDIDATES, COLOUR_TAG_YELLOW); + gNumCollisionCandidates = 0; gLevelModelTable = (s32 *) load_asset_section_from_rom(ASSET_LEVEL_MODELS_TABLE); for (i = 0; gLevelModelTable[i] != -1; i++) {} @@ -2870,7 +2871,7 @@ void generate_track(s32 modelId) { LOCAL_OFFSET_TO_RAM_ADDRESS(Vertex *, gCurrentLevelModel->segments[k].vertices); LOCAL_OFFSET_TO_RAM_ADDRESS(Triangle *, gCurrentLevelModel->segments[k].triangles); LOCAL_OFFSET_TO_RAM_ADDRESS(TriangleBatchInfo *, gCurrentLevelModel->segments[k].batches); - LOCAL_OFFSET_TO_RAM_ADDRESS(CollisionNode *, gCurrentLevelModel->segments[k].unk14); + LOCAL_OFFSET_TO_RAM_ADDRESS(CollisionFacetPlanes *, gCurrentLevelModel->segments[k].collisionFacets); } for (k = 0; k < gCurrentLevelModel->numberOfTextures; k++) { gCurrentLevelModel->textures[k].texture = @@ -2880,7 +2881,7 @@ void generate_track(s32 modelId) { for (k = 0; k < gCurrentLevelModel->numberOfSegments; k++) { gCurrentLevelModel->segments[k].unk10 = (s16 *) j; j = (s32) align16(((u8 *) (gCurrentLevelModel->segments[k].numberOfTriangles * 2)) + j); - gCurrentLevelModel->segments[k].unk18 = (f32 *) j; + gCurrentLevelModel->segments[k].collisionPlanes = (f32 *) j; j = (s32) & ((u8 *) j)[func_8002CC30(&gCurrentLevelModel->segments[k])]; func_8002C954(&gCurrentLevelModel->segments[k], &gCurrentLevelModel->segmentsBoundingBoxes[k], k); gCurrentLevelModel->segments[k].unk30 = 0; @@ -2958,8 +2959,8 @@ void free_track(void) { tex_free(gCurrentLevelModel->textures[i].texture); } mempool_free(gTrackModelHeap); - mempool_free(D_8011D370); - mempool_free(D_8011D374); + mempool_free(gCollisionCandidates); + mempool_free(gCollisionSurfaces); sprite_free((Sprite *) gCurrentLevelModel->minimapSpriteIndex); for (i = 0; i < ARRAY_COUNT(gShadowHeapData); i++) { mempool_free(gShadowHeapData[i]); @@ -3001,7 +3002,7 @@ void func_8002C954(LevelModelSegment *segment, LevelModelSegmentBoundingBox *bbo endTri = segment->batches[i + 1].facesOffset; vertsOffset = segment->batches[i].verticesOffset; for (j = startTri; j < endTri; j++) { - if (segment->triangles[j].flags & 0x80) { + if (segment->triangles[j].flags & TRI_FLAG_80) { segment->unk10[j] = 0; } else { maxX = -32000; @@ -3066,11 +3067,11 @@ s32 func_8002CC30(LevelModelSegment *arg0) { s32 triIndex; s32 i; f32 mag; - s32 s4; - s32 s1; - s32 s0; - s32 t1; - s32 v1, v2; + s32 counter; + s32 colPlaneIndex; + s32 next; + s32 numColPlanes; + s32 vertIndex, nextVertIndex; f32 x1, y1, z1; f32 x2, y2, z2; f32 x3, y3, z3; @@ -3078,7 +3079,7 @@ s32 func_8002CC30(LevelModelSegment *arg0) { f32 x5, y5, z5; s32 j; - s4 = 0; + counter = 0; for (batchIndex = 0; batchIndex < arg0->numberOfBatches; batchIndex++) { facesOffset = arg0->batches[batchIndex].facesOffset; @@ -3118,26 +3119,27 @@ s32 func_8002CC30(LevelModelSegment *arg0) { // looks like a macro { - s32 temp = s4++; - arg0->unk18[4 * temp + 0] = nx; - arg0->unk18[4 * temp + 1] = ny; - arg0->unk18[4 * temp + 2] = nz; - arg0->unk18[4 * temp + 3] = -(x1 * nx + y1 * ny + z1 * nz); + s32 temp = counter++; + arg0->collisionPlanes[4 * temp + 0] = nx; + arg0->collisionPlanes[4 * temp + 1] = ny; + arg0->collisionPlanes[4 * temp + 2] = nz; + arg0->collisionPlanes[4 * temp + 3] = -(x1 * nx + y1 * ny + z1 * nz); } } } - t1 = s4; + numColPlanes = counter; if (D_8011B0F8) { - return s4 * 0x10; + return counter * 0x10; } for (batchIndex = 0; batchIndex < arg0->numberOfBatches; batchIndex++) { facesOffset = arg0->batches[batchIndex].facesOffset; verticesOffset = arg0->batches[batchIndex].verticesOffset; nextFacesOffset = arg0->batches[batchIndex + 1].facesOffset; - if (arg0->batches[batchIndex].flags & RENDER_UNK_200) { + + if (arg0->batches[batchIndex].flags & RENDER_NO_COLLISION) { facesOffset = nextFacesOffset; } @@ -3146,35 +3148,35 @@ s32 func_8002CC30(LevelModelSegment *arg0) { continue; } - s1 = arg0->unk14[triIndex].triangleIndex; - nx = arg0->unk18[4 * s1 + 0]; - ny = arg0->unk18[4 * s1 + 1]; - nz = arg0->unk18[4 * s1 + 2]; + colPlaneIndex = arg0->collisionFacets[triIndex].basePlaneIndex; + nx = arg0->collisionPlanes[4 * colPlaneIndex + 0]; + ny = arg0->collisionPlanes[4 * colPlaneIndex + 1]; + nz = arg0->collisionPlanes[4 * colPlaneIndex + 2]; for (i = 0; i < 3; i++) { - s0 = i + 1; - if (s0 > 2) { - s0 = 0; + next = i + 1; + if (next > 2) { + next = 0; } - v1 = arg0->triangles[triIndex].verticesArray[1 + i] + verticesOffset; - v2 = arg0->triangles[triIndex].verticesArray[1 + s0] + verticesOffset; - s0 = arg0->unk14[triIndex].closestTri[i]; + vertIndex = arg0->triangles[triIndex].verticesArray[1 + i] + verticesOffset; + nextVertIndex = arg0->triangles[triIndex].verticesArray[1 + next] + verticesOffset; - if (s0 < t1) { + next = arg0->collisionFacets[triIndex].edgeBisectorPlane[i]; + if (next < numColPlanes) { { - s32 temp = s0; - x5 = nx + arg0->unk18[4 * temp + 0]; - y5 = ny + arg0->unk18[4 * temp + 1]; - z5 = nz + arg0->unk18[4 * temp + 2]; + s32 temp = next; + x5 = nx + arg0->collisionPlanes[4 * temp + 0]; + y5 = ny + arg0->collisionPlanes[4 * temp + 1]; + z5 = nz + arg0->collisionPlanes[4 * temp + 2]; } - v = &arg0->vertices[v1]; + v = &arg0->vertices[vertIndex]; x1 = v->x; y1 = v->y; z1 = v->z; - v = &arg0->vertices[v2]; + v = &arg0->vertices[nextVertIndex]; x2 = v->x; y2 = v->y; z2 = v->z; @@ -3194,28 +3196,28 @@ s32 func_8002CC30(LevelModelSegment *arg0) { z5 /= mag; } - if (s0 != s1) { + if (next != colPlaneIndex) { for (j = 0; j < 3; j++) { - if (s1 == arg0->unk14[s0].closestTri[j]) { - arg0->unk14[s0].closestTri[j] = s4 | 0x8000; + if (colPlaneIndex == arg0->collisionFacets[next].edgeBisectorPlane[j]) { + arg0->collisionFacets[next].edgeBisectorPlane[j] = counter | 0x8000; } } } - arg0->unk14[triIndex].closestTri[i] = s4; + arg0->collisionFacets[triIndex].edgeBisectorPlane[i] = counter; { - s32 temp = s4++; - arg0->unk18[4 * temp + 0] = x5; - arg0->unk18[4 * temp + 1] = y5; - arg0->unk18[4 * temp + 2] = z5; - arg0->unk18[4 * temp + 3] = -(x1 * x5 + y1 * y5 + z1 * z5); + s32 temp = counter++; + arg0->collisionPlanes[4 * temp + 0] = x5; + arg0->collisionPlanes[4 * temp + 1] = y5; + arg0->collisionPlanes[4 * temp + 2] = z5; + arg0->collisionPlanes[4 * temp + 3] = -(x1 * x5 + y1 * y5 + z1 * z5); } } } } } - return s4 * 0x10; + return counter * 0x10; } typedef struct unk8002D30C_a0 { @@ -3485,14 +3487,13 @@ void func_8002DE30(Object *obj) { blockId = obj->segmentID; foundResult = FALSE; if (blockId != -1) { - var_t3 = - func_800314DC(&gCurrentLevelModel->segmentsBoundingBoxes[blockId], obj->trans.x_position - 16.0f, - obj->trans.z_position - 16.0f, obj->trans.x_position + 16.0f, obj->trans.z_position + 16.0f); + var_t3 = compute_grid_overlap_mask(&gCurrentLevelModel->segmentsBoundingBoxes[blockId], + obj->trans.x_position - 16.0f, obj->trans.z_position - 16.0f, + obj->trans.x_position + 16.0f, obj->trans.z_position + 16.0f); block = &gCurrentLevelModel->segments[blockId]; for (i = 0; i < block->numberOfBatches && !foundResult; i++) { if (!(block->batches[i].flags & (RENDER_HIDDEN | RENDER_DECAL | RENDER_WATER | RENDER_NO_SHADOW))) { - batchFlags = (block->batches[i].flags >> 19) & - (RENDER_ANTI_ALIASING | RENDER_Z_COMPARE | RENDER_SEMI_TRANSPARENT); + batchFlags = (block->batches[i].flags >> 19) & 7; vertices = &block->vertices[block->batches[i].verticesOffset]; for (j = block->batches[i].facesOffset; j < block->batches[i + 1].facesOffset && !foundResult; j++) { blockId = block->unk10[j] & var_t3; @@ -3615,11 +3616,11 @@ void shadow_generate(Object *obj, s32 isWater) { if (isWater && (gCurrentLevelModel->segments[inSegs[i]].hasWaves != 0) && (gWaveBlockCount != 0)) { func_8002EEEC(inSegs[i]); } else { - test = func_800314DC(&gCurrentLevelModel->segmentsBoundingBoxes[inSegs[i]], - (obj->trans.x_position - gNewShadowWidth), // x1 - (obj->trans.z_position - gNewShadowLength), // z1 - (obj->trans.x_position + gNewShadowWidth), // x2 - (obj->trans.z_position + gNewShadowLength) // z2 + test = compute_grid_overlap_mask(&gCurrentLevelModel->segmentsBoundingBoxes[inSegs[i]], + (obj->trans.x_position - gNewShadowWidth), // x1 + (obj->trans.z_position - gNewShadowLength), // z1 + (obj->trans.x_position + gNewShadowWidth), // x2 + (obj->trans.z_position + gNewShadowLength) // z2 ); func_8002E904(&gCurrentLevelModel->segments[inSegs[i]], test, isWater); } @@ -3695,9 +3696,9 @@ void func_8002E904(LevelModelSegment *arg0, s32 arg1, s32 arg2) { // @note while the cast to Vec4f is incorrect, func_8002FD74 x uses unk0 and z which // are both floats so this is fine as the size is the same if (func_8002FD74(spD0[2].x, spD0[2].y, spD0[0].x, spD0[0].y, 3, (Vec4f *) sp100) != 0) { - temp_t6 = arg0->unk14[curFacesOffset].triangleIndex * 4; - D_8011D0BC = (unk8011C8B8 *) &(arg0->unk18)[temp_t6]; - if (arg0->unk18[temp_t6 + 1] != 0) { + temp_t6 = arg0->collisionFacets[curFacesOffset].basePlaneIndex * 4; + D_8011D0BC = (unk8011C8B8 *) &(arg0->collisionPlanes)[temp_t6]; + if (arg0->collisionPlanes[temp_t6 + 1] != 0) { if (D_8011D0F0 > 0.0f) { func_800304C8(sp100); } diff --git a/src/tracks.h b/src/tracks.h index 00aa270a..f7dab05d 100644 --- a/src/tracks.h +++ b/src/tracks.h @@ -7,14 +7,9 @@ #include "racer.h" #include "fade_transition.h" -#define LOCAL_OFFSET_TO_RAM_ADDRESS(type, ptr) \ - ptr = (type)((s32)((u8*)ptr) + (s32)((u8*)mdl)) +#define LOCAL_OFFSET_TO_RAM_ADDRESS(type, ptr) ptr = (type) ((s32) ((u8 *) ptr) + (s32) ((u8 *) mdl)) -enum ShadowUpdate { - SHADOW_NONE, - SHADOW_SCENERY, - SHADOW_ACTORS -}; +enum ShadowUpdate { SHADOW_NONE, SHADOW_SCENERY, SHADOW_ACTORS }; /* Size: 0x10 bytes */ typedef struct unk8011C8B8 { @@ -57,10 +52,10 @@ typedef struct VoidMesh { } VoidMesh; typedef struct unk8011C238 { - u8 unk0; - u8 unk1; - u8 unk2[8]; - s16 unkA; + u8 unk0; + u8 unk1; + u8 unk2[8]; + s16 unkA; } unk8011C238; /* Size: 0x8 bytes */ @@ -74,16 +69,16 @@ typedef struct unk8011D478 { /* Size: 0x14 bytes */ typedef struct unk8011C3B8 { - /* 0x00 */ s16 x1; - /* 0x02 */ s16 y1; - /* 0x04 */ s16 z1; - /* 0x06 */ s16 x2; - /* 0x08 */ s16 y2; - /* 0x0A */ s16 z2; - /* 0x0C */ s16 x3; - /* 0x0E */ s16 y3; - /* 0x10 */ s16 z3; - /* 0x12 */ s16 unk12; + /* 0x00 */ s16 x1; + /* 0x02 */ s16 y1; + /* 0x04 */ s16 z1; + /* 0x06 */ s16 x2; + /* 0x08 */ s16 y2; + /* 0x0A */ s16 z2; + /* 0x0C */ s16 x3; + /* 0x0E */ s16 y3; + /* 0x10 */ s16 z3; + /* 0x12 */ s16 unk12; } unk8011C3B8; // In this struct, data is rightshifted 16 bytes, so make the smooth transition more precise. @@ -105,9 +100,9 @@ typedef struct EnvironmentFogCompact { /* Size: 0x38 bytes */ typedef struct FogData { - EnvironmentFog fog; // Current fog properties. What you'll actually see ingame. - EnvironmentFog addFog; // Fog override. This will apply over the current fog to give a smooth transition effect. - EnvironmentFogCompact intendedFog; // Fog properties the game will try to be if the switch timer is 0. + EnvironmentFog fog; // Current fog properties. What you'll actually see ingame. + EnvironmentFog addFog; // Fog override. This will apply over the current fog to give a smooth transition effect. + EnvironmentFogCompact intendedFog; // Fog properties the game will try to be if the switch timer is 0. s32 switchTimer; Object *fogChanger; } FogData; @@ -119,12 +114,6 @@ typedef struct WaterProperties { /* 0x10 */ s8 type; } WaterProperties; -enum WaveTypes { - WATER_CALM = 11, - WATER_WAVY = 14, - WATER_UNK_F = 15 -}; - s32 set_scene_viewport_num(s32 numPorts); void void_free(void); void spawn_skydome(s32 objectID); @@ -136,8 +125,8 @@ s32 get_inside_segment_count_xz(s32 x, s32 z, s32 *arg2); s32 get_inside_segment_count_xyz(s32 *arg0, s16 xPos1, s16 yPos1, s16 zPos1, s16 xPos2, s16 yPos2, s16 zPos2); LevelModelSegment *get_segment(s32 segmentID); LevelModelSegmentBoundingBox *get_segment_bounding_box(s32 segmentID); -void func_8002ACC8(s32 arg0); -s32 func_8002ACD4(f32 *arg0, f32 *arg1, f32 *arg2); +void set_collision_mode(s32 arg0); +s32 get_collision_normal(f32 *arg0, f32 *arg1, f32 *arg2); s32 func_8002B9BC(Object *obj, f32 *arg1, Vec3f *arg2, s32 arg3); void func_8002C71C(LevelModelSegment *segment); LevelModel *get_current_level_model(void); @@ -149,7 +138,8 @@ void compute_scene_camera_transform_matrix(void); void animate_level_textures(s32 updateRate); s32 check_if_inside_segment(Object *obj, s32 segmentIndex); s32 get_level_segment_index_from_position(f32 xPos, f32 yPos, f32 zPos); -void traverse_segments_bsp_tree(s32 nodeIndex, s32 segmentIndex, s32 segmentIndex2, u8 *segmentsOrder, s32 *segmentsOrderIndex); +void traverse_segments_bsp_tree(s32 nodeIndex, s32 segmentIndex, s32 segmentIndex2, u8 *segmentsOrder, + s32 *segmentsOrderIndex); void render_level_geometry_and_objects(void); void watereffect_render(Object *obj, WaterEffect *effect); void shadow_render(Object *obj, ShadowData *shadow); @@ -158,11 +148,11 @@ s32 check_if_in_draw_range(Object *obj); void func_8002C954(LevelModelSegment *segment, LevelModelSegmentBoundingBox *bbox, s32 arg2); void draw_gradient_background(void); void shadow_update(s32 group, s32 waterGroup, s32 updateRate); -void obj_loop_fogchanger(Object* obj); +void obj_loop_fogchanger(Object *obj); void initialise_player_viewport_vars(s32 updateRate); s32 get_wave_properties(f32 yPos, f32 *waterHeight, Vec3f *rotation); void render_level_segment(s32 segmentId, s32 nonOpaque); -void render_scene(Gfx** dList, Mtx** mtx, Vertex** vtx, Triangle** tris, s32 updateRate); +void render_scene(Gfx **dList, Mtx **mtx, Vertex **vtx, Triangle **tris, s32 updateRate); void set_fog(s32 fogIdx, s16 near, s16 far, u8 red, u8 green, u8 blue); void slowly_change_fog(s32 fogIdx, s32 red, s32 green, s32 blue, s32 near, s32 far, s32 switchTimer); s32 func_8002FD74(f32 x0, f32 z0, f32 x1, f32 x2, s32 count, Vec4f *arg5); @@ -174,24 +164,26 @@ void func_80026430(LevelModelSegment *segment, f32 arg1, f32 arg2, f32 arg3); void free_track(void); void void_check(u8 *segmentIds, s32 numberOfSegments, s32 viewportIndex); s32 func_80027568(void); -s32 func_8002CC30(LevelModelSegment*); -s32 func_8002B0F4(s32, f32 xIn, f32 zIn, WaterProperties***); // Definitely not triple pointer, but easiest way to fix warns. +s32 func_8002CC30(LevelModelSegment *); +s32 func_8002B0F4(s32, f32 xIn, f32 zIn, + WaterProperties ***); // Definitely not triple pointer, but easiest way to fix warns. void func_800278E8(s32); void func_80028050(void); void initialise_player_viewport_vars(s32); void func_8002A31C(void); void update_colour_cycle(LevelHeader_70 *arg0, s32 updateRate); void waves_update(s32); -void waves_render(Gfx**, Mtx**, s32); -void func_8002DE30(Object*); -void shadow_generate(Object*, s32); +void waves_render(Gfx **, Mtx **, s32); +void func_8002DE30(Object *); +void shadow_generate(Object *, s32); void func_8002E904(LevelModelSegment *, s32, s32 arg2); void func_8002EEEC(s32 arg0); void func_8002F2AC(void); void func_8002F440(void); f32 func_8002FA64(void); s32 func_8002BAB0(s32 levelSegmentIndex, f32 xIn, f32 zIn, f32 *yOut); -void init_track(u32 geometry, u32 skybox, s32 numberOfPlayers, Vehicle vehicle, u32 entranceId, u32 collectables, u32 arg6); +void init_track(u32 geometry, u32 skybox, s32 numberOfPlayers, Vehicle vehicle, u32 entranceId, u32 collectables, + u32 arg6); void waves_init(LevelModel *, LevelHeader *, s32); void void_init(s32); void generate_track(s32 modelId); diff --git a/ver/symbols/symbol_addrs.jpn.v79.txt b/ver/symbols/symbol_addrs.jpn.v79.txt index 06c0e2f4..cbd9cbd5 100644 --- a/ver/symbols/symbol_addrs.jpn.v79.txt +++ b/ver/symbols/symbol_addrs.jpn.v79.txt @@ -436,9 +436,9 @@ func_8002A31C = 0x8002A31C; should_segment_be_visible = 0x8002A5F8; check_if_in_draw_range = 0x8002A900; func_8002AC00 = 0x8002AC00; -dayGetTrackFade = 0x8002ACA0; -func_8002ACC8 = 0x8002ACC8; -func_8002ACD4 = 0x8002ACD4; +get_collision_candidate_data = 0x8002ACA0; +set_collision_mode = 0x8002ACC8; +get_collision_normal = 0x8002ACD4; get_wave_properties = 0x8002AD08; func_8002B0F4 = 0x8002B0F4; func_8002B9BC = 0x8002B9BC; @@ -474,9 +474,9 @@ update_perspective_and_envmap = 0x80030FA0; compute_scene_camera_transform_matrix = 0x80031018; // collision.c .text -func_80031130 = 0x80031130; -func_800314DC = 0x800314DC; -func_80031600 = 0x80031600; +generate_collision_candidates = 0x80031130; +compute_grid_overlap_mask = 0x800314DC; +resolve_collisions = 0x80031600; // lights.c .text free_lights = 0x80031B60; @@ -3733,11 +3733,11 @@ gDrawLevelSegments = 0x8011CB50; gVoidColourR = 0x8011CB51; gVoidColourG = 0x8011CB52; gVoidColourB = 0x8011CB53; -D_8011B0E4 = 0x8011CB54; -D_8011B0E8 = 0x8011CB58; -D_8011B0EC = 0x8011CB5C; -D_8011B0F0 = 0x8011CB60; -D_8011B0F4 = 0x8011CB64; +gCollisionNormalX = 0x8011CB54; +gCollisionNormalY = 0x8011CB58; +gCollisionNormalZ = 0x8011CB5C; +gHitWall = 0x8011CB60; +gCollisionMode = 0x8011CB64; D_8011B0F8 = 0x8011CB68; gAntiAliasing = 0x8011CB6C; D_8011B100 = 0x8011CB70; @@ -3793,9 +3793,9 @@ gCurrShadowHeapData = 0x8011EDD0; gShadowTail = 0x8011EDD4; gNewShadowTriCount = 0x8011EDD8; gNewShadowVtxCount = 0x8011EDDC; -D_8011D370 = 0x8011EDE0; -D_8011D374 = 0x8011EDE4; -D_8011D378 = 0x8011EDE8; +gCollisionCandidates = 0x8011EDE0; +gCollisionSurfaces = 0x8011EDE4; +gNumCollisionCandidates = 0x8011EDE8; gScenePlayerViewports = 0x8011EDEC; gCurrBBoxDistanceToCamera = 0x8011EDF0; gWaveBlockCount = 0x8011EDF4; diff --git a/ver/symbols/symbol_addrs.pal.v77.txt b/ver/symbols/symbol_addrs.pal.v77.txt index 269106ad..c73ab097 100644 --- a/ver/symbols/symbol_addrs.pal.v77.txt +++ b/ver/symbols/symbol_addrs.pal.v77.txt @@ -436,9 +436,9 @@ func_8002A31C = 0x8002A31C; should_segment_be_visible = 0x8002A5F8; check_if_in_draw_range = 0x8002A900; func_8002AC00 = 0x8002AC00; -dayGetTrackFade = 0x8002ACA0; -func_8002ACC8 = 0x8002ACC8; -func_8002ACD4 = 0x8002ACD4; +get_collision_candidate_data = 0x8002ACA0; +set_collision_mode = 0x8002ACC8; +get_collision_normal = 0x8002ACD4; get_wave_properties = 0x8002AD08; func_8002B0F4 = 0x8002B0F4; func_8002B9BC = 0x8002B9BC; @@ -474,9 +474,9 @@ update_perspective_and_envmap = 0x80030FA0; compute_scene_camera_transform_matrix = 0x80031018; // collision.c .text -func_80031130 = 0x80031130; -func_800314DC = 0x800314DC; -func_80031600 = 0x80031600; +generate_collision_candidates = 0x80031130; +compute_grid_overlap_mask = 0x800314DC; +resolve_collisions = 0x80031600; // lights.c .text free_lights = 0x80031B60; @@ -3469,11 +3469,11 @@ gDrawLevelSegments = 0x8011B170; gVoidColourR = 0x8011B171; gVoidColourG = 0x8011B172; gVoidColourB = 0x8011B173; -D_8011B0E4 = 0x8011B174; -D_8011B0E8 = 0x8011B178; -D_8011B0EC = 0x8011B17C; -D_8011B0F0 = 0x8011B180; -D_8011B0F4 = 0x8011B184; +gCollisionNormalX = 0x8011B174; +gCollisionNormalY = 0x8011B178; +gCollisionNormalZ = 0x8011B17C; +gHitWall = 0x8011B180; +gCollisionMode = 0x8011B184; D_8011B0F8 = 0x8011B188; gAntiAliasing = 0x8011B18C; D_8011B100 = 0x8011B190; @@ -3529,9 +3529,9 @@ gCurrShadowHeapData = 0x8011D3F0; gShadowTail = 0x8011D3F4; gNewShadowTriCount = 0x8011D3F8; gNewShadowVtxCount = 0x8011D3FC; -D_8011D370 = 0x8011D400; -D_8011D374 = 0x8011D404; -D_8011D378 = 0x8011D408; +gCollisionCandidates = 0x8011D400; +gCollisionSurfaces = 0x8011D404; +gNumCollisionCandidates = 0x8011D408; gScenePlayerViewports = 0x8011D40C; gCurrBBoxDistanceToCamera = 0x8011D410; gWaveBlockCount = 0x8011D414; diff --git a/ver/symbols/symbol_addrs.pal.v80.txt b/ver/symbols/symbol_addrs.pal.v80.txt index 8c8530c5..59e507e0 100644 --- a/ver/symbols/symbol_addrs.pal.v80.txt +++ b/ver/symbols/symbol_addrs.pal.v80.txt @@ -432,9 +432,9 @@ func_8002A31C = 0x8002A35C; should_segment_be_visible = 0x8002A638; check_if_in_draw_range = 0x8002A940; func_8002AC00 = 0x8002AC40; -dayGetTrackFade = 0x8002ACE0; -func_8002ACC8 = 0x8002AD08; -func_8002ACD4 = 0x8002AD14; +get_collision_candidate_data = 0x8002ACE0; +set_collision_mode = 0x8002AD08; +get_collision_normal = 0x8002AD14; get_wave_properties = 0x8002AD48; func_8002B0F4 = 0x8002B134; func_8002B9BC = 0x8002B9FC; @@ -468,9 +468,9 @@ obj_loop_fogchanger = 0x80030AB4; slowly_change_fog = 0x80030E20; update_perspective_and_envmap = 0x80030FE0; compute_scene_camera_transform_matrix = 0x80031058; -func_80031130 = 0x80031170; -func_800314DC = 0x8003151C; -func_80031600 = 0x80031640; +generate_collision_candidates = 0x80031170; +compute_grid_overlap_mask = 0x8003151C; +resolve_collisions = 0x80031640; free_lights = 0x80031BA0; setup_lights = 0x80031BF8; func_80031CAC = 0x80031CEC; @@ -3399,11 +3399,11 @@ gDrawLevelSegments = 0x8011B6F0; gVoidColourR = 0x8011B6F1; gVoidColourG = 0x8011B6F2; gVoidColourB = 0x8011B6F3; -D_8011B0E4 = 0x8011B6F4; -D_8011B0E8 = 0x8011B6F8; -D_8011B0EC = 0x8011B6FC; -D_8011B0F0 = 0x8011B700; -D_8011B0F4 = 0x8011B704; +gCollisionNormalX = 0x8011B6F4; +gCollisionNormalY = 0x8011B6F8; +gCollisionNormalZ = 0x8011B6FC; +gHitWall = 0x8011B700; +gCollisionMode = 0x8011B704; D_8011B0F8 = 0x8011B708; gAntiAliasing = 0x8011B70C; D_8011B100 = 0x8011B710; @@ -3459,9 +3459,9 @@ gCurrShadowHeapData = 0x8011D970; gShadowTail = 0x8011D974; gNewShadowTriCount = 0x8011D978; gNewShadowVtxCount = 0x8011D97C; -D_8011D370 = 0x8011D980; -D_8011D374 = 0x8011D984; -D_8011D378 = 0x8011D988; +gCollisionCandidates = 0x8011D980; +gCollisionSurfaces = 0x8011D984; +gNumCollisionCandidates = 0x8011D988; gScenePlayerViewports = 0x8011D98C; gCurrBBoxDistanceToCamera = 0x8011D990; gWaveBlockCount = 0x8011D994; diff --git a/ver/symbols/symbol_addrs.us.v77.txt b/ver/symbols/symbol_addrs.us.v77.txt index 75bcbbc9..935e071f 100644 --- a/ver/symbols/symbol_addrs.us.v77.txt +++ b/ver/symbols/symbol_addrs.us.v77.txt @@ -436,9 +436,9 @@ func_8002A31C = 0x8002A31C; should_segment_be_visible = 0x8002A5F8; check_if_in_draw_range = 0x8002A900; func_8002AC00 = 0x8002AC00; -dayGetTrackFade = 0x8002ACA0; -func_8002ACC8 = 0x8002ACC8; -func_8002ACD4 = 0x8002ACD4; +get_collision_candidate_data = 0x8002ACA0; +set_collision_mode = 0x8002ACC8; +get_collision_normal = 0x8002ACD4; get_wave_properties = 0x8002AD08; func_8002B0F4 = 0x8002B0F4; func_8002B9BC = 0x8002B9BC; @@ -474,9 +474,9 @@ update_perspective_and_envmap = 0x80030FA0; compute_scene_camera_transform_matrix = 0x80031018; // collision.c .text -func_80031130 = 0x80031130; -func_800314DC = 0x800314DC; -func_80031600 = 0x80031600; +generate_collision_candidates = 0x80031130; +compute_grid_overlap_mask = 0x800314DC; +resolve_collisions = 0x80031600; // lights.c .text free_lights = 0x80031B60; @@ -3848,11 +3848,11 @@ gDrawLevelSegments = 0x8011B0E0; gVoidColourR = 0x8011B0E1; gVoidColourG = 0x8011B0E2; gVoidColourB = 0x8011B0E3; -D_8011B0E4 = 0x8011B0E4; -D_8011B0E8 = 0x8011B0E8; -D_8011B0EC = 0x8011B0EC; -D_8011B0F0 = 0x8011B0F0; -D_8011B0F4 = 0x8011B0F4; +gCollisionNormalX = 0x8011B0E4; +gCollisionNormalY = 0x8011B0E8; +gCollisionNormalZ = 0x8011B0EC; +gHitWall = 0x8011B0F0; +gCollisionMode = 0x8011B0F4; D_8011B0F8 = 0x8011B0F8; gAntiAliasing = 0x8011B0FC; D_8011B100 = 0x8011B100; @@ -3908,9 +3908,9 @@ gCurrShadowHeapData = 0x8011D360; gShadowTail = 0x8011D364; gNewShadowTriCount = 0x8011D368; gNewShadowVtxCount = 0x8011D36C; -D_8011D370 = 0x8011D370; -D_8011D374 = 0x8011D374; -D_8011D378 = 0x8011D378; +gCollisionCandidates = 0x8011D370; +gCollisionSurfaces = 0x8011D374; +gNumCollisionCandidates = 0x8011D378; gScenePlayerViewports = 0x8011D37C; gCurrBBoxDistanceToCamera = 0x8011D380; gWaveBlockCount = 0x8011D384; diff --git a/ver/symbols/symbol_addrs.us.v80.txt b/ver/symbols/symbol_addrs.us.v80.txt index 4db6d1e3..9736c740 100644 --- a/ver/symbols/symbol_addrs.us.v80.txt +++ b/ver/symbols/symbol_addrs.us.v80.txt @@ -432,9 +432,9 @@ func_8002A31C = 0x8002A35C; should_segment_be_visible = 0x8002A638; check_if_in_draw_range = 0x8002A940; func_8002AC00 = 0x8002AC40; -dayGetTrackFade = 0x8002ACE0; -func_8002ACC8 = 0x8002AD08; -func_8002ACD4 = 0x8002AD14; +get_collision_candidate_data = 0x8002ACE0; +set_collision_mode = 0x8002AD08; +get_collision_normal = 0x8002AD14; get_wave_properties = 0x8002AD48; func_8002B0F4 = 0x8002B134; func_8002B9BC = 0x8002B9FC; @@ -468,9 +468,9 @@ obj_loop_fogchanger = 0x80030AB4; slowly_change_fog = 0x80030E20; update_perspective_and_envmap = 0x80030FE0; compute_scene_camera_transform_matrix = 0x80031058; -func_80031130 = 0x80031170; -func_800314DC = 0x8003151C; -func_80031600 = 0x80031640; +generate_collision_candidates = 0x80031170; +compute_grid_overlap_mask = 0x8003151C; +resolve_collisions = 0x80031640; free_lights = 0x80031BA0; setup_lights = 0x80031BF8; func_80031CAC = 0x80031CEC; @@ -3395,11 +3395,11 @@ gDrawLevelSegments = 0x8011B660; gVoidColourR = 0x8011B661; gVoidColourG = 0x8011B662; gVoidColourB = 0x8011B663; -D_8011B0E4 = 0x8011B664; -D_8011B0E8 = 0x8011B668; -D_8011B0EC = 0x8011B66C; -D_8011B0F0 = 0x8011B670; -D_8011B0F4 = 0x8011B674; +gCollisionNormalX = 0x8011B664; +gCollisionNormalY = 0x8011B668; +gCollisionNormalZ = 0x8011B66C; +gHitWall = 0x8011B670; +gCollisionMode = 0x8011B674; D_8011B0F8 = 0x8011B678; gAntiAliasing = 0x8011B67C; D_8011B100 = 0x8011B680; @@ -3455,9 +3455,9 @@ gCurrShadowHeapData = 0x8011D8E0; gShadowTail = 0x8011D8E4; gNewShadowTriCount = 0x8011D8E8; gNewShadowVtxCount = 0x8011D8EC; -D_8011D370 = 0x8011D8F0; -D_8011D374 = 0x8011D8F4; -D_8011D378 = 0x8011D8F8; +gCollisionCandidates = 0x8011D8F0; +gCollisionSurfaces = 0x8011D8F4; +gNumCollisionCandidates = 0x8011D8F8; gScenePlayerViewports = 0x8011D8FC; gCurrBBoxDistanceToCamera = 0x8011D900; gWaveBlockCount = 0x8011D904;