Skip to content

Commit

Permalink
#368 GBA use sphere culling instead of box (boxIsVisible)
Browse files Browse the repository at this point in the history
  • Loading branch information
XProger committed Apr 30, 2022
1 parent d5f6139 commit dba6a54
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 547 deletions.
37 changes: 16 additions & 21 deletions src/fixed/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

#define USE_FMT (LVL_FMT_PKD)

#include <tonc.h>
#include <tonc.h>
#elif defined(__NDS__)
#define USE_DIV_TABLE

Expand All @@ -73,7 +73,7 @@

#define USE_FMT (LVL_FMT_PSX)

#include <nds.h>
#include <nds.h>
#include <fat.h>
#include <filesystem.h>
#elif defined(__TNS__)
Expand Down Expand Up @@ -279,6 +279,8 @@ typedef uint16 divTableInt;
typedef uint8 ColorIndex;
#endif

#define ADDR_ALIGN4(x) ((uint8*)x += ((intptr_t(x) + 3) & ~3) - intptr_t(x))

//#include <new>
inline void* operator new(size_t, void *ptr)
{
Expand Down Expand Up @@ -319,15 +321,7 @@ X_INLINE int32 abs(int32 x) {
#define ASSERT(x)
#endif

#if defined(__GBA__)
#define IME_DISABLE() u16 origIME = REG_IME; REG_IME = 0
#define IME_ENABLE() REG_IME = origIME;
#else
#define IME_DISABLE()
#define IME_ENABLE()
#endif

#if defined(__GBA__WIN__)
#if defined(__GBA_WIN__)
extern uint16 fb[VRAM_WIDTH * FRAME_HEIGHT];
#elif defined(__GBA__)
extern uint32 fb;
Expand Down Expand Up @@ -895,11 +889,10 @@ struct RoomVertex
{
#if defined(__3DO__)
uint16 xyz565;
#elif defined(__GBA__) || defined(__32X__)
#elif defined(__GBA__) || defined(__GBA_WIN__) || defined(__32X__)
uint8 x, y, z, g;
#else
uint8 x, y, z;
uint8 cR, cG, cB;
uint8 x, y, z, g;
#endif
};

Expand Down Expand Up @@ -2653,6 +2646,15 @@ X_INLINE void swap(T &a, T &b) {
b = tmp;
}

X_INLINE uint16 swap16(uint16 x) {
return ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
}

X_INLINE uint32 swap32(uint32 x) {
return ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24);
}


extern int32 gRandSeedLogic;
extern int32 gRandSeedDraw;

Expand Down Expand Up @@ -2731,7 +2733,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
void matrixRotateYXZ_asm(int32 angleX, int32 angleY, int32 angleZ);
void boxTranslate_asm(AABBi &box, int32 x, int32 y, int32 z);
void boxRotateYQ_asm(AABBi &box, int32 quadrant);
int32 boxIsVisible_asm(const AABBs* box);
int32 sphereIsVisible_asm(int32 x, int32 y, int32 z, int32 r);
void flush_asm();
}
Expand All @@ -2750,7 +2751,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
#define matrixRotateYQ matrixRotateYQ_asm
#define boxTranslate boxTranslate_asm
#define boxRotateYQ boxRotateYQ_asm
#define boxIsVisible boxIsVisible_asm
#define sphereIsVisible sphereIsVisible_asm
#define flush flush_asm
#else
Expand All @@ -2768,7 +2768,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
#define matrixRotateYQ matrixRotateYQ_c
#define boxTranslate boxTranslate_c
#define boxRotateYQ boxRotateYQ_c
#define boxIsVisible boxIsVisible_c
#define sphereIsVisible sphereIsVisible_c
#define flush flush_c

Expand All @@ -2787,7 +2786,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);

void boxTranslate_c(AABBi &box, int32 x, int32 y, int32 z);
void boxRotateYQ_c(AABBi &box, int32 quadrant);
int32 boxIsVisible_c(const AABBs* box);
int32 sphereIsVisible_c(int32 x, int32 y, int32 z, int32 r);
void flush_c();
#endif
Expand All @@ -2807,7 +2805,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
#undef matrixRotateYQ
//#undef boxTranslate
//#undef boxRotateYQ
//#undef boxIsVisible
//#undef sphereIsVisible
//#undef flush

Expand All @@ -2825,7 +2822,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
#define matrixRotateYQ matrixRotateYQ_asm
//#define boxTranslate boxTranslate_asm
//#define boxRotateYQ boxRotateYQ_asm
//#define boxIsVisible boxIsVisible_asm
//#define sphereIsVisible sphereIsVisible_asm
//#define flush flush_asm

Expand All @@ -2845,7 +2841,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
void matrixRotateYXZ_asm(int32 angleX, int32 angleY, int32 angleZ);
void boxTranslate_asm(AABBi &box, int32 x, int32 y, int32 z);
void boxRotateYQ_asm(AABBi &box, int32 quadrant);
int32 boxIsVisible_asm(const AABBs* box);
int32 sphereIsVisible_asm(int32 x, int32 y, int32 z, int32 r);
void flush_asm();
}
Expand Down
113 changes: 78 additions & 35 deletions src/fixed/draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

#ifdef TEST_ROOM_CACHE
RoomVertex roomVert[512];
RoomQuad roomQuads[512];
RoomTriangle roomTri[64];
EWRAM_DATA RoomQuad roomQuads[512];
EWRAM_DATA RoomTriangle roomTri[64];
#endif

void drawInit()
Expand All @@ -26,6 +26,16 @@ void drawInit()
int16 rot = i * (ANGLE_90 * 4) / MAX_CAUSTICS;
gCaustics[i] = sin(rot) * 768 >> FIXED_SHIFT;
}
}

void drawFree()
{
renderFree();
}

void drawLevelInit()
{
renderLevelInit();

#ifdef TEST_ROOM_CACHE
Room &room = rooms[14];
Expand All @@ -40,16 +50,6 @@ void drawInit()
#endif
}

void drawFree()
{
renderFree();
}

void drawLevelInit()
{
renderLevelInit();
}

void drawLevelFree()
{
renderLevelFree();
Expand Down Expand Up @@ -622,35 +622,81 @@ void drawModel(const ItemObj* item)
frameDelta = 0;
#endif

matrixPush();
matrixTranslateAbs(item->pos.x, item->pos.y, item->pos.z);
matrixRotateYXZ(item->angle.x, item->angle.y, item->angle.z);
int32 sx, sy, sz, sr, smin, smax;
smin = frameA->box.minX;
smax = frameA->box.maxX;
sx = (smax + smin) >> 1;
sr = (smax - smin);

smin = frameA->box.minY;
smax = frameA->box.maxY;
sy = (smax + smin) >> 1;
sr = X_MAX(sr, (smax - smin));

smin = frameA->box.minZ;
smax = frameA->box.maxZ;
sz = (smax + smin) >> 1;
sr = X_MAX(sr, (smax - smin));

int32 vis = boxIsVisible(&frameA->box);
// approx. radius (TODO more precise)
sr = (sr >> 1) + (sr >> 2);

if (vis)
// rotate sphere center by quadrant
uint16 quadrant = uint16(item->angle.y + ANGLE_45) >> ANGLE_SHIFT_90;

if (quadrant != 0)
{
int32 intensity = item->intensity << 5;
int32 ix = sx;
int32 iz = sz;

if (intensity == 0) {
vec3i point = item->getRelative(frameA->box.getCenter());
calcLightingDynamic(item->room, point);
} else {
calcLightingStatic(intensity);
switch (quadrant)
{
case 1:
sx = iz;
sz = -ix;
break;
case 2:
sx = -ix;
sz = -iz;
break;
case 3:
sx = -iz;
sz = ix;
break;
}
}

// skip rooms portal clipping for objects
if (item->type == ITEM_LARA) {
drawLaraNodesLerp(item, frameA, frameB, frameDelta, frameRate);
} else {
drawNodesLerp(item, frameA, frameB, frameDelta, frameRate);
}
sx += item->pos.x - gCameraViewPos.x;
sy += item->pos.y - gCameraViewPos.y;
sz += item->pos.z - gCameraViewPos.z;

if (!sphereIsVisible(sx, sy, sz, sr))
return;

matrixPush();
matrixTranslateAbs(item->pos.x, item->pos.y, item->pos.z);
matrixRotateYXZ(item->angle.x, item->angle.y, item->angle.z);

int32 intensity = item->intensity << 5;

if (intensity == 0) {
vec3i point = item->getRelative(frameA->box.getCenter());
calcLightingDynamic(item->room, point);
} else {
calcLightingStatic(intensity);
}

// skip rooms portal clipping for objects
if (item->type == ITEM_LARA) {
drawLaraNodesLerp(item, frameA, frameB, frameDelta, frameRate);
} else {
drawNodesLerp(item, frameA, frameB, frameDelta, frameRate);
}

matrixPop();

// shadow
if (vis && (item->flags & ITEM_FLAG_SHADOW)) {
if (item->flags & ITEM_FLAG_SHADOW) {
drawShadow(item, 160); // TODO per item shadow size
}
}
Expand Down Expand Up @@ -741,11 +787,8 @@ void drawRoom(const Room* room)
matrixTranslateSet(px, py, pz);
matrixRotateYQ(q);

int32 vis = boxIsVisible(&staticMesh->vbox);
if (vis) {
calcLightingStatic(STATIC_MESH_INTENSITY(mesh->zf));
drawMesh(staticMesh->meshIndex);
}
calcLightingStatic(STATIC_MESH_INTENSITY(mesh->zf));
drawMesh(staticMesh->meshIndex);

matrixPop();
}
Expand Down
73 changes: 0 additions & 73 deletions src/platform/32x/render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,79 +529,6 @@ void faceAddMeshTriangles_c(const MeshTriangle* polys, int32 count)
}
}

bool transformBoxRect(const AABBs* box, RectMinMax* rect)
{
const Matrix &m = matrixGet();

if ((m.e23 < (VIEW_MIN_F >> MATRIX_FIXED_SHIFT)) || (m.e23 >= (VIEW_MAX_F >> MATRIX_FIXED_SHIFT)))
return false;

vec3i v[8];
v[0] = _vec3i( box->minX, box->minY, box->minZ ),
v[1] = _vec3i( box->maxX, box->minY, box->minZ ),
v[2] = _vec3i( box->minX, box->maxY, box->minZ ),
v[3] = _vec3i( box->maxX, box->maxY, box->minZ ),
v[4] = _vec3i( box->minX, box->minY, box->maxZ ),
v[5] = _vec3i( box->maxX, box->minY, box->maxZ ),
v[6] = _vec3i( box->minX, box->maxY, box->maxZ ),
v[7] = _vec3i( box->maxX, box->maxY, box->maxZ );

*rect = RectMinMax( INT_MAX, INT_MAX, INT_MIN, INT_MIN );

for (int32 i = 0; i < 8; i++)
{
int32 z = DP43(m.e20, m.e21, m.e22, m.e23, v[i].x, v[i].y, v[i].z);

if (z < VIEW_MIN_F || z >= VIEW_MAX_F)
continue;

int32 x = DP43(m.e00, m.e01, m.e02, m.e03, v[i].x, v[i].y, v[i].z);
int32 y = DP43(m.e10, m.e11, m.e12, m.e13, v[i].x, v[i].y, v[i].z);

x >>= FIXED_SHIFT;
y >>= FIXED_SHIFT;
z >>= FIXED_SHIFT;

PERSPECTIVE(x, y, z);

if (x < rect->x0) rect->x0 = x;
if (x > rect->x1) rect->x1 = x;
if (y < rect->y0) rect->y0 = y;
if (y > rect->y1) rect->y1 = y;
}

rect->x0 += (FRAME_WIDTH / 2);
rect->y0 += (FRAME_HEIGHT / 2);
rect->x1 += (FRAME_WIDTH / 2);
rect->y1 += (FRAME_HEIGHT / 2);

return true;
}

int32 rectIsVisible(const RectMinMax* rect)
{
if (rect->x0 > rect->x1 ||
rect->x0 > viewport.x1 ||
rect->x1 < viewport.x0 ||
rect->y0 > viewport.y1 ||
rect->y1 < viewport.y0) return 0; // not visible

if (rect->x0 < viewport.x0 ||
rect->x1 > viewport.x1 ||
rect->y0 < viewport.y0 ||
rect->y1 > viewport.y1) return -1; // clipped

return 1; // fully visible
}

int32 boxIsVisible_c(const AABBs* box)
{
RectMinMax rect;
if (!transformBoxRect(box, &rect))
return 0; // not visible
return rectIsVisible(&rect);
}

int32 sphereIsVisible_c(int32 sx, int32 sy, int32 sz, int32 r)
{
Matrix &m = matrixGet();
Expand Down
Loading

0 comments on commit dba6a54

Please sign in to comment.