1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-01 02:40:43 +02:00

#368 GBA use sphere culling instead of box (boxIsVisible)

This commit is contained in:
XProger
2022-04-30 03:57:33 +03:00
parent d5f6139678
commit dba6a54739
9 changed files with 116 additions and 547 deletions

View File

@@ -63,7 +63,7 @@
#define USE_FMT (LVL_FMT_PKD)
#include <tonc.h>
#include <tonc.h>
#elif defined(__NDS__)
#define USE_DIV_TABLE
@@ -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__)
@@ -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)
{
@@ -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;
@@ -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
};
@@ -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;
@@ -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();
}
@@ -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
@@ -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
@@ -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
@@ -2807,7 +2805,6 @@ vec3i boxPushOut(const AABBi &a, const AABBi &b);
#undef matrixRotateYQ
//#undef boxTranslate
//#undef boxRotateYQ
//#undef boxIsVisible
//#undef sphereIsVisible
//#undef flush
@@ -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
@@ -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();
}

View File

@@ -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()
@@ -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];
@@ -40,16 +50,6 @@ void drawInit()
#endif
}
void drawFree()
{
renderFree();
}
void drawLevelInit()
{
renderLevelInit();
}
void drawLevelFree()
{
renderLevelFree();
@@ -622,35 +622,81 @@ void drawModel(const ItemObj* item)
frameDelta = 0;
#endif
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));
// approx. radius (TODO more precise)
sr = (sr >> 1) + (sr >> 2);
// rotate sphere center by quadrant
uint16 quadrant = uint16(item->angle.y + ANGLE_45) >> ANGLE_SHIFT_90;
if (quadrant != 0)
{
int32 ix = sx;
int32 iz = sz;
switch (quadrant)
{
case 1:
sx = iz;
sz = -ix;
break;
case 2:
sx = -ix;
sz = -iz;
break;
case 3:
sx = -iz;
sz = ix;
break;
}
}
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 vis = boxIsVisible(&frameA->box);
int32 intensity = item->intensity << 5;
if (vis)
{
int32 intensity = item->intensity << 5;
if (intensity == 0) {
vec3i point = item->getRelative(frameA->box.getCenter());
calcLightingDynamic(item->room, point);
} else {
calcLightingStatic(intensity);
}
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);
}
// 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
}
}
@@ -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();
}

View File

@@ -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();

View File

@@ -43,9 +43,6 @@ extern Item screenItem;
#define FACE_MIP_SHIFT 11
#define FACE_TEXTURE 0x07FF
#define F16_SHIFT 2 // special f14 to f16 shift for the math co-processor
#define DUP16(value) value | (value << 16)
enum ShadeValue
@@ -693,131 +690,6 @@ void faceAddMeshTrianglesFlat_c(const MeshTriangle* polys, int32 count, uint32 s
}
}
int32 boxIsVisible_c(const AABBs* box)
{
Matrix &m = matrixGet();
if ((m.e23 < VIEW_MIN_F) || (m.e23 >= VIEW_MAX_F)) {
return 0;
}
const int32* ptr = (int32*)box;
enum {
MAX_X,
MIN_X,
MAX_Y,
MIN_Y,
MAX_Z,
MIN_Z,
MIN_MAX_SIZE
};
int32 mm[MIN_MAX_SIZE][3];
int32 min, max, minX, minY, minZ, maxX, maxY, maxZ;
#define PROJECT(dx,dy,dz){\
int32 x, y, z;\
x = mm[dx][0] + mm[dy][0] + mm[dz][0];\
y = mm[dx][1] + mm[dy][1] + mm[dz][1];\
z = mm[dx][2] + mm[dy][2] + mm[dz][2];\
if (z >= VIEW_MIN_F && z <= VIEW_MAX_F) {\
z = gDivTable[z >> (FIXED_SHIFT + PROJ_SHIFT)];\
x = x * z;\
y = y * z;\
if (x < rMinX) rMinX = x;\
if (y < rMinY) rMinY = y;\
if (x > rMaxX) rMaxX = x;\
if (y > rMaxY) rMaxY = y;\
}\
}
int32 xx = ptr[0];
int32 yy = ptr[1];
int32 zz = ptr[2];
// pre-transform min/max Z
min = zz >> 16;
minX = m.e02 * min + m.e03;
minY = m.e12 * min + m.e13;
minZ = m.e22 * min + m.e23;
max = zz << 16 >> 16;
maxX = m.e02 * max + m.e03;
maxY = m.e12 * max + m.e13;
maxZ = m.e22 * max + m.e23;
mm[MAX_Z][0] = maxX >> FIXED_SHIFT;
mm[MAX_Z][1] = maxY >> FIXED_SHIFT;
mm[MAX_Z][2] = maxZ;
mm[MIN_Z][0] = minX >> FIXED_SHIFT;
mm[MIN_Z][1] = minY >> FIXED_SHIFT;
mm[MIN_Z][2] = minZ;
// pre-transform min/max Y
min = yy >> 16;
minX = m.e01 * min;
minY = m.e11 * min;
minZ = m.e21 * min;
max = yy << 16 >> 16;
maxX = m.e01 * max;
maxY = m.e11 * max;
maxZ = m.e21 * max;
mm[MAX_Y][0] = maxX >> FIXED_SHIFT;
mm[MAX_Y][1] = maxY >> FIXED_SHIFT;
mm[MAX_Y][2] = maxZ;
mm[MIN_Y][0] = minX >> FIXED_SHIFT;
mm[MIN_Y][1] = minY >> FIXED_SHIFT;
mm[MIN_Y][2] = minZ;
// pre-transform min/max X
min = xx >> 16;
minX = m.e00 * min;
minY = m.e10 * min;
minZ = m.e20 * min;
max = xx << 16 >> 16;
maxX = m.e00 * max;
maxY = m.e10 * max;
maxZ = m.e20 * max;
mm[MAX_X][0] = maxX >> FIXED_SHIFT;
mm[MAX_X][1] = maxY >> FIXED_SHIFT;
mm[MAX_X][2] = maxZ;
mm[MIN_X][0] = minX >> FIXED_SHIFT;
mm[MIN_X][1] = minY >> FIXED_SHIFT;
mm[MIN_X][2] = minZ;
int32 rMinX = INT_MAX;
int32 rMinY = INT_MAX;
int32 rMaxX = INT_MIN;
int32 rMaxY = INT_MIN;
PROJECT(MIN_X, MIN_Y, MIN_Z);
PROJECT(MAX_X, MIN_Y, MIN_Z);
PROJECT(MIN_X, MAX_Y, MIN_Z);
PROJECT(MAX_X, MAX_Y, MIN_Z);
PROJECT(MIN_X, MIN_Y, MAX_Z);
PROJECT(MAX_X, MIN_Y, MAX_Z);
PROJECT(MIN_X, MAX_Y, MAX_Z);
PROJECT(MAX_X, MAX_Y, MAX_Z);
rMinX >>= (16 - PROJ_SHIFT);
rMaxX >>= (16 - PROJ_SHIFT);
if (rMinX > rMaxX) return 0;
// rect Y is shifted left by 16
rMinY <<= PROJ_SHIFT;
rMaxY <<= PROJ_SHIFT;
int32 vMinXY = viewportRel.minXY;
int32 vMaxXY = viewportRel.maxXY;
if (rMaxX < (vMinXY >> 16) ||
rMaxY < (vMinXY << 16) ||
rMinX > (vMaxXY >> 16) ||
rMinY > (vMaxXY << 16)) return 0;
return 1;
}
int32 sphereIsVisible_c(int32 x, int32 y, int32 z, int32 r)
{
Matrix &m = matrixGet();

View File

@@ -30,6 +30,8 @@
<ClInclude Include="..\..\fixed\common.h" />
<ClInclude Include="..\..\fixed\draw.h" />
<ClInclude Include="..\..\fixed\enemy.h" />
<ClInclude Include="..\..\fixed\fmt\phd.h" />
<ClInclude Include="..\..\fixed\fmt\pkd.h" />
<ClInclude Include="..\..\fixed\game.h" />
<ClInclude Include="..\..\fixed\inventory.h" />
<ClInclude Include="..\..\fixed\item.h" />
@@ -116,7 +118,7 @@
<WarningLevel>Level2</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__GBA_WIN__;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
@@ -132,7 +134,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__GBA_WIN__;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
@@ -149,7 +151,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__GBA_WIN__;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
@@ -170,7 +172,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__GBA_WIN__;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>

View File

@@ -1,209 +0,0 @@
#include "common_asm.inc"
mx .req r0
my .req r1
mz .req r2
m .req r3
vx .req r4
vy .req r5
vz .req r6
x .req r7
y .req r8
z .req r9
rMinX .req r10
rMinY .req r11
rMaxX .req r12
rMaxY .req lr
boxArg .req mx
tmp .req mz
bz .req mz
offset .req m
dz .req offset
xx .req rMinX
yy .req rMinY
zz .req rMaxX
min .req rMaxY
max .req rMaxY
vMinXY .req x
vMaxXY .req y
vp .req x
minX .req x
minY .req y
minZ .req z
maxX .req mx
maxY .req my
maxZ .req mz
MAX_X = (0 * 3 * 4)
MIN_X = (1 * 3 * 4)
MAX_Y = (2 * 3 * 4)
MIN_Y = (3 * 3 * 4)
MAX_Z = (4 * 3 * 4)
MIN_Z = (5 * 3 * 4)
SIZE = (6 * 3 * 4)
.macro project dx, dy, dz
add offset, sp, \dz
ldmia offset, {x, y, z}
add offset, sp, \dy
ldmia offset, {vx, vy, vz}
add x, x, vx
add y, y, vy
add z, z, vz
add offset, sp, \dx
ldmia offset, {vx, vy, vz}
add z, z, vz
// check z clipping
sub offset, z, #VIEW_MIN_F
cmp offset, #(VIEW_MAX_F - VIEW_MIN_F)
bhi 1f
add x, x, vx
add y, y, vy
mov dz, z, lsr #(FIXED_SHIFT + 6)
add dz, dz, z, lsr #(FIXED_SHIFT + 4)
divLUT tmp, dz
mul x, tmp, x
mul y, tmp, y
cmp x, rMinX
movlt rMinX, x
cmp y, rMinY
movlt rMinY, y
cmp x, rMaxX
movgt rMaxX, x
cmp y, rMaxY
movgt rMaxY, y
1:
.endm
.global boxIsVisible_asm
boxIsVisible_asm:
ldr m, =gMatrixPtr
ldr m, [m]
ldr bz, [m, #(11 * 4)]
add bz, bz, #VIEW_OFF_F
cmp bz, #(VIEW_OFF_F + VIEW_MAX_F)
movhi r0, #0
bxhi lr
stmfd sp!, {r4-r11, lr}
ldmia boxArg, {xx, yy, zz}
// pre-transform min/max Z
ldr mx, [m, #8]
ldr vx, [m, #12]
ldr my, [m, #24]
ldr vy, [m, #28]
ldr mz, [m, #40]
ldr vz, [m, #44]
mov min, zz, asr #16
mla minX, min, mx, vx
mla minY, min, my, vy
mla minZ, min, mz, vz
mov minX, minX, asr #FIXED_SHIFT
mov minY, minY, asr #FIXED_SHIFT
mov max, zz, lsl #16
mov max, max, asr #16
mla maxX, max, mx, vx
mla maxY, max, my, vy
mla maxZ, max, mz, vz
mov maxX, maxX, asr #FIXED_SHIFT
mov maxY, maxY, asr #FIXED_SHIFT
stmdb sp!, {maxX, maxY, maxZ, minX, minY, minZ}
// pre-transform min/max Y
ldr mx, [m, #4]
ldr my, [m, #20]
ldr mz, [m, #36]
mov min, yy, asr #16
mul minX, mx, min
mul minY, my, min
mul minZ, mz, min
mov minX, minX, asr #FIXED_SHIFT
mov minY, minY, asr #FIXED_SHIFT
mov max, yy, lsl #16
mov max, max, asr #16
mul maxX, max, mx
mul maxY, max, my
mul maxZ, max, mz
mov maxX, maxX, asr #FIXED_SHIFT
mov maxY, maxY, asr #FIXED_SHIFT
stmdb sp!, {maxX, maxY, maxZ, minX, minY, minZ}
// pre-transform min/max X
ldr mx, [m, #0]
ldr my, [m, #16]
ldr mz, [m, #32]
mov min, xx, asr #16
mul minX, mx, min
mul minY, my, min
mul minZ, mz, min
mov minX, minX, asr #FIXED_SHIFT
mov minY, minY, asr #FIXED_SHIFT
mov max, xx, lsl #16
mov max, max, asr #16
mul maxX, max, mx
mul maxY, max, my
mul maxZ, max, mz
mov maxX, maxX, asr #FIXED_SHIFT
mov maxY, maxY, asr #FIXED_SHIFT
stmdb sp!, {maxX, maxY, maxZ, minX, minY, minZ}
mov rMinX, #MAX_INT32
mov rMinY, #MAX_INT32
mov rMaxX, #MIN_INT32
mov rMaxY, #MIN_INT32
project #MIN_X, #MIN_Y, #MIN_Z
project #MAX_X, #MIN_Y, #MIN_Z
project #MIN_X, #MAX_Y, #MIN_Z
project #MAX_X, #MAX_Y, #MIN_Z
project #MIN_X, #MIN_Y, #MAX_Z
project #MAX_X, #MIN_Y, #MAX_Z
project #MIN_X, #MAX_Y, #MAX_Z
project #MAX_X, #MAX_Y, #MAX_Z
mov r0, #0
mov rMinX, rMinX, asr #(16 - PROJ_SHIFT)
mov rMaxX, rMaxX, asr #(16 - PROJ_SHIFT)
cmp rMinX, rMaxX
beq .done
// rect Y must remain shifted up by 16
mov rMinY, rMinY, lsl #PROJ_SHIFT
mov rMaxY, rMaxY, lsl #PROJ_SHIFT
// check xy clipping
ldr vp, =viewportRel
ldmia vp, {vMinXY, vMaxXY}
cmp rMaxX, vMinXY, asr #16
blt .done
cmp rMaxY, vMinXY, lsl #16
blt .done
cmp rMinX, vMaxXY, asr #16
bgt .done
cmp rMinY, vMaxXY, lsl #16
bgt .done
mov r0, #1
.done:
add sp, sp, #SIZE
ldmfd sp!, {r4-r11, lr}
bx lr

View File

@@ -72,7 +72,7 @@
.equ PROJ_SHIFT, 4
.equ OT_SHIFT, 4
.equ VIEW_DIST, (1024 * 10) // max = DIV_TABLE_END << PROJ_SHIFT
.equ VIEW_DIST, (1024 * 10)
.equ FOG_SHIFT, 1
.equ FOG_MAX, VIEW_DIST
.equ FOG_MIN, (FOG_MAX - (8192 >> FOG_SHIFT))
@@ -124,7 +124,7 @@
asr \tmp, \uv, #16
mul \tmp, \f // u = f * int16(uv >> 16)
lsl \uv, \uv, #16
lsl \uv, #16
asr \uv, #16
mul \uv, \f // v = f * int16(uv)

View File

@@ -5,7 +5,7 @@ EWRAM_DATA int32 frameIndex = 0;
EWRAM_DATA int32 fpsCounter = 0;
EWRAM_DATA uint32 curSoundBuffer = 0;
#ifdef _WIN32
#ifdef __GBA_WIN__
const void* TRACKS_IMA;
const void* TITLE_SCR;
const void* levelData;

View File

@@ -25,7 +25,7 @@ struct ViewportRel {
ViewportRel viewportRel;
#if defined(_WIN32)
#if defined(__GBA_WIN__)
uint16 fb[VRAM_WIDTH * FRAME_HEIGHT];
#elif defined(__GBA__)
uint32 fb = MEM_VRAM;
@@ -508,79 +508,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();
@@ -802,6 +729,18 @@ void renderInit()
gFacesBase = gFaces;
}
void renderFree()
{
}
void renderLevelInit()
{
}
void renderLevelFree()
{
}
extern "C" X_NOINLINE void drawTriangle(uint32 flags, VertexLink* v)
{
VertexLink* v0 = v + 0;