Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document BDHC util #363

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/overlay005/bdhc.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
typedef struct BDHCPlate {
u16 firstPointIndex;
u16 secondPointIndex;
u16 normalIndex;
u16 slopeIndex;
u16 heightIndex;
} BDHCPlate;

Expand Down
11 changes: 11 additions & 0 deletions include/overlay005/bdhc_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef POKEPLATINUM_BDHC_UTIL_H
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Given how small this is, how would we feel combining this with bdhc_loader?

#define POKEPLATINUM_BDHC_UTIL_H

#include <nitro/fx/fx.h>
#include <nitro/types.h>

#include "overlay005/bdhc.h"

BOOL BDHCUtil_CalculateObjectHeight(const fx32 objectY, const fx32 objectX, const fx32 objectZ, const BDHC *bdhc, fx32 *newObjectY);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: I'm definitely more in favor of objectHeight or objectH for clarity.


#endif // POKEPLATINUM_BDHC_UTIL_H
8 changes: 0 additions & 8 deletions include/overlay005/ov5_021EEC68.h

This file was deleted.

10 changes: 0 additions & 10 deletions include/overlay005/struct_ov5_021EED20.h

This file was deleted.

2 changes: 1 addition & 1 deletion platinum.us/main.lsf
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ Overlay overlay5
Object main.nef.p/src_overlay005_ov5_021EE75C.c.o
Object main.nef.p/src_overlay005_ov5_021EE7D4.c.o
Object main.nef.p/src_overlay005_ov5_021EEAC8.c.o
Object main.nef.p/src_overlay005_ov5_021EEC68.c.o
Object main.nef.p/src_overlay005_bdhc_util.c.o
Object main.nef.p/src_overlay005_bdhc_loader.c.o
Object main.nef.p/src_overlay005_ov5_021EF250.c.o
Object main.nef.p/src_overlay005_hblank_system.c.o
Expand Down
2 changes: 1 addition & 1 deletion src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ pokeplatinum_c = files(
'overlay005/ov5_021EE75C.c',
'overlay005/ov5_021EE7D4.c',
'overlay005/ov5_021EEAC8.c',
'overlay005/ov5_021EEC68.c',
'overlay005/bdhc_util.c',
'overlay005/bdhc_loader.c',
'overlay005/ov5_021EF250.c',
'overlay005/hblank_system.c',
Expand Down
205 changes: 205 additions & 0 deletions src/overlay005/bdhc_util.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
#include "overlay005/bdhc_util.h"

#include <nitro.h>
#include <string.h>

#include "overlay005/bdhc.h"

#include "fx_util.h"

#define BDHC_NEW_OBJECT_Y_CANDIDATES_ARRAY_SIZE 10

typedef struct {
fx32 y;
int unk_04;
int unk_08;
} BDHCCandidateObjectY;

static BOOL BDHCUtil_FindStripIndexByLowerBound(const BDHCStrip *strips, const u16 stripsSize, const fx32 targetLowerBound, u16 *stripIndex);

static BOOL BDHCUtil_IsPointInBoundingBox(const BDHCPoint *boundingBoxFirstPoint, const BDHCPoint *boundingBoxSecondPoint, const BDHCPoint *point)
{
const fx32 *boundingBoxLeft, *boundingBoxRight, *boundingBoxUp, *boundingBoxDown;

if (boundingBoxFirstPoint->x <= boundingBoxSecondPoint->x) {
boundingBoxLeft = &boundingBoxFirstPoint->x;
boundingBoxRight = &boundingBoxSecondPoint->x;
} else {
boundingBoxLeft = &boundingBoxSecondPoint->x;
boundingBoxRight = &boundingBoxFirstPoint->x;
}

if (boundingBoxFirstPoint->y <= boundingBoxSecondPoint->y) {
boundingBoxUp = &boundingBoxFirstPoint->y;
boundingBoxDown = &boundingBoxSecondPoint->y;
} else {
boundingBoxUp = &boundingBoxSecondPoint->y;
boundingBoxDown = &boundingBoxFirstPoint->y;
}

if (((*boundingBoxLeft <= point->x) && (point->x <= *boundingBoxRight)) && ((*boundingBoxUp <= point->y) && (point->y <= *boundingBoxDown))) {
return TRUE;
}

return FALSE;
}

static void BDHCUtil_GetPointsFromPlate(const BDHC *bdhc, u16 plateIndex, BDHCPoint *platePoints)
{
platePoints[0] = bdhc->points[bdhc->plates[plateIndex].firstPointIndex];
platePoints[1] = bdhc->points[bdhc->plates[plateIndex].secondPointIndex];
}

static void BDHCUtil_GetSlopeFromPlate(const BDHC *bdhc, u16 plateIndex, VecFx32 *slope)
{
*slope = bdhc->slopes[bdhc->plates[plateIndex].slopeIndex];
}

static void BDHCUtil_GetHeightFromPlate(const BDHC *bdhc, u16 plateIndex, fx32 *height)
{
*height = bdhc->heights[bdhc->plates[plateIndex].heightIndex];
}

static void BDHCCandidateObjectY_Init(BDHCCandidateObjectY *BDHCCandidateObjectY)
{
for (int i = 0; i < BDHC_NEW_OBJECT_Y_CANDIDATES_ARRAY_SIZE; i++) {
BDHCCandidateObjectY[i].y = 0;
BDHCCandidateObjectY[i].unk_04 = -1;
BDHCCandidateObjectY[i].unk_08 = -1;
}
}

static BOOL BDHCUtil_FindStripIndexByLowerBound(const BDHCStrip *strips, const u16 stripsSize, const fx32 targetLowerBound, u16 *stripIndex)
{
int low, high;
u32 mid;
fx32 stripLowerBound;

if (stripsSize == 0) {
return FALSE;
} else if (stripsSize == 1) {
*stripIndex = 0;
return TRUE;
}

// Simple binary search.
low = 0;
high = stripsSize - 1;
mid = high / 2;

do {
stripLowerBound = strips[mid].lowerBound;

if (stripLowerBound > targetLowerBound) {
Comment on lines +91 to +93
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Does this match as:

Suggested change
stripLowerBound = strips[mid].lowerBound;
if (stripLowerBound > targetLowerBound) {
if (strips[mid].lowerBound > targetLowerBound) {

after removing the stripLowerBound declaration?

if (high - 1 > low) {
high = mid;
mid = (low + high) / 2;
} else {
*stripIndex = mid;
return TRUE;
}
} else {
if (low + 1 < high) {
low = mid;
mid = (low + high) / 2;
} else {
*stripIndex = mid + 1;
return TRUE;
}
}
} while (TRUE);

return FALSE;
}

BOOL BDHCUtil_CalculateObjectHeight(const fx32 objectY, const fx32 objectX, const fx32 objectZ, const BDHC *bdhc, fx32 *newObjectY)
{
BDHCPoint platePoints[2];
BDHCPoint objectPosition;
VecFx32 slope;
fx32 minObjectYDiff, objectYDiff;
BOOL isPointInBoundingBox;
u16 i, plateIndex;
fx32 height, calculatedObjectY;
int newObjectYCandidateCount;
u32 stripsSize;
BDHCCandidateObjectY newObjectYCandidates[BDHC_NEW_OBJECT_Y_CANDIDATES_ARRAY_SIZE];
u32 accessListStartIndex;
u16 stripIndex;
u16 accessListElementCount;
const BDHCStrip *strips;

if (bdhc->loaded == FALSE) {
return FALSE;
}

isPointInBoundingBox = FALSE;

objectPosition.x = objectX;
objectPosition.y = objectZ;

newObjectYCandidateCount = 0;
BDHCCandidateObjectY_Init(newObjectYCandidates);

stripsSize = bdhc->stripsSize;
strips = bdhc->strips;

if (BDHCUtil_FindStripIndexByLowerBound(strips, stripsSize, objectPosition.y, &stripIndex) == FALSE) {
return FALSE;
}

accessListElementCount = strips[stripIndex].accessListElementCount;
accessListStartIndex = strips[stripIndex].accessListStartIndex;

for (i = 0; i < accessListElementCount; i++) {
plateIndex = bdhc->accessList[accessListStartIndex + i];
BDHCUtil_GetPointsFromPlate(bdhc, plateIndex, platePoints);
isPointInBoundingBox = BDHCUtil_IsPointInBoundingBox(&platePoints[0], &platePoints[1], &objectPosition);

if (isPointInBoundingBox == TRUE) {
BDHCUtil_GetSlopeFromPlate(bdhc, plateIndex, &slope);
BDHCUtil_GetHeightFromPlate(bdhc, plateIndex, &height);

// On the next line, `slope.z` and `objectPosition.y` represent the same axis.
// Remember that `objectPosition.y` is, in fact, `objectZ`.
// Also, remember that `slope` is a normal vector, pointing upwards for a flat surface.
calculatedObjectY = -(FX_Mul(slope.x, objectPosition.x) + FX_Mul(slope.z, objectPosition.y) + height);
calculatedObjectY = FX_Div(calculatedObjectY, slope.y);

newObjectYCandidates[newObjectYCandidateCount].y = calculatedObjectY;
newObjectYCandidateCount++;

if (newObjectYCandidateCount >= BDHC_NEW_OBJECT_Y_CANDIDATES_ARRAY_SIZE) {
break;
}
}
}

if (newObjectYCandidateCount > 1) {
// Find the candidate with the smallest difference between the object's current Y and the calculated Y.
plateIndex = 0;
minObjectYDiff = FX_Max(objectY, newObjectYCandidates[0].y) - FX_Min(objectY, newObjectYCandidates[0].y);

for (i = 1; i < newObjectYCandidateCount; i++) {
objectYDiff = FX_Max(objectY, newObjectYCandidates[i].y) - FX_Min(objectY, newObjectYCandidates[i].y);

if (minObjectYDiff > objectYDiff) {
minObjectYDiff = objectYDiff;
plateIndex = i;
}
}

*newObjectY = newObjectYCandidates[plateIndex].y;
return TRUE;
} else if (newObjectYCandidateCount == 1) {
*newObjectY = newObjectYCandidates[0].y;
return TRUE;
}

if (newObjectYCandidateCount != 0) {
*newObjectY = newObjectYCandidates[0].y;
return TRUE;
}

return FALSE;
}
Loading