1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-13 08:34:32 +02:00

#370 use soft transform for transformBoxRect

This commit is contained in:
XProger
2021-12-16 02:33:14 +03:00
parent 8689a4dc3f
commit 3114c818af
4 changed files with 265 additions and 90 deletions

View File

@@ -2001,14 +2001,16 @@ struct IMA_STATE
}; };
#if defined(MODEHW) #if defined(MODEHW)
#define PERSPECTIVE_DZ(z) (z >> 4) #define PROJ_SHIFT 4
#define PERSPECTIVE_DZ(z) (z >> PROJ_SHIFT)
#define PERSPECTIVE(x, y, z) {\ #define PERSPECTIVE(x, y, z) {\
int32 dz = PERSPECTIVE_DZ(z);\ int32 dz = PERSPECTIVE_DZ(z);\
if (dz >= DIV_TABLE_SIZE) dz = DIV_TABLE_SIZE - 1;\ if (dz >= DIV_TABLE_SIZE) dz = DIV_TABLE_SIZE - 1;\
int32 d = FixedInvU(dz);\ int32 d = FixedInvU(dz);\
x = (x * d) >> 12;\ x = (x * d) >> (16 - PROJ_SHIFT);\
y = (y * d) >> 12;\ y = (y * d) >> (16 - PROJ_SHIFT);\
} }
#elif defined(MODE13) #elif defined(MODE13)
#define PERSPECTIVE(x, y, z) {\ #define PERSPECTIVE(x, y, z) {\

View File

@@ -60,4 +60,7 @@ DIV_TABLE_END EQU (1025 - 1)
VIEW_MIN EQU (256 << CLIP_SHIFT) VIEW_MIN EQU (256 << CLIP_SHIFT)
VIEW_MAX EQU (VIEW_DIST << CLIP_SHIFT) VIEW_MAX EQU (VIEW_DIST << CLIP_SHIFT)
MIN_INT32 EQU 0x80000000
MAX_INT32 EQU 0x7FFFFFFF
MulManyVec3Mat33_F16 EQU (0x50000 + 2) MulManyVec3Mat33_F16 EQU (0x50000 + 2)

View File

@@ -696,7 +696,7 @@ bool transformBoxRect_c(const AABBs* box, RectMinMax* rect)
} }
const int32* ptr = (int32*)box; const int32* ptr = (int32*)box;
#if 0
int32 minX = ptr[0] >> 16 << F16_SHIFT; int32 minX = ptr[0] >> 16 << F16_SHIFT;
int32 maxX = ptr[0] << 16 >> (16 - F16_SHIFT); int32 maxX = ptr[0] << 16 >> (16 - F16_SHIFT);
int32 minY = ptr[1] >> 16 << F16_SHIFT; int32 minY = ptr[1] >> 16 << F16_SHIFT;
@@ -741,6 +741,107 @@ bool transformBoxRect_c(const AABBs* box, RectMinMax* rect)
rect->y0 = y0 + (FRAME_HEIGHT / 2); rect->y0 = y0 + (FRAME_HEIGHT / 2);
rect->x1 = x1 + (FRAME_WIDTH / 2); rect->x1 = x1 + (FRAME_WIDTH / 2);
rect->y1 = y1 + (FRAME_HEIGHT / 2); rect->y1 = y1 + (FRAME_HEIGHT / 2);
#else
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 = divTable[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);
rect->x0 = (rMinX >> (16 - PROJ_SHIFT)) + (FRAME_WIDTH / 2);
rect->y0 = (rMinY >> (16 - PROJ_SHIFT)) + (FRAME_HEIGHT / 2);
rect->x1 = (rMaxX >> (16 - PROJ_SHIFT)) + (FRAME_WIDTH / 2);
rect->y1 = (rMaxY >> (16 - PROJ_SHIFT)) + (FRAME_HEIGHT / 2);
#endif
return true; return true;
} }

View File

@@ -9,115 +9,184 @@
boxArg RN r0 boxArg RN r0
rectArg RN r1 rectArg RN r1
m RN r2 divLUT RN r2
vert RN r3 m RN r3
vptr RN r4 vx RN r4
rect RN r5 ; must be in r4-r6 vy RN r5
minX RN boxArg vz RN r6
maxX RN rectArg x RN r7
minY RN m y RN r8
maxY RN r6 z RN r9
minZ RN r12 rMinX RN r10
maxZ RN lr rMinY RN r11
rMaxX RN r12
rMaxY RN lr
xx RN maxX bz RN divLUT
yy RN maxY offset RN m
zz RN maxZ xx RN rMinX
rMinX RN boxArg yy RN rMinY
rMinY RN rectArg zz RN rMaxX
rMaxX RN m min RN rMaxY
rMaxY RN maxY max RN rMaxY
vx RN vptr w RN x
vy RN minZ h RN y
vz RN maxZ mx RN boxArg
my RN rectArg
mz RN divLUT
INT_MIN EQU 0x80000000 minX RN x
INT_MAX EQU 0x7FFFFFFF minY RN y
minZ RN z
maxX RN mx
maxY RN my
maxZ RN mz
MAX_X EQU (0 * 3 * 4)
MIN_X EQU (1 * 3 * 4)
MAX_Y EQU (2 * 3 * 4)
MIN_Y EQU (3 * 3 * 4)
MAX_Z EQU (4 * 3 * 4)
MIN_Z EQU (5 * 3 * 4)
SIZE EQU (6 * 3 * 4)
MACRO MACRO
$index check $index project $dx, $dy, $dz
ldmia vert!, {vx, vy, vz} add offset, sp, $dz
tst vz, #(CLIP_NEAR | CLIP_FAR) ldmia offset, {x, y, z}
bne $index.skip
cmp vx, rMinX add offset, sp, $dy
movlt rMinX, vx ldmia offset, {vx, vy, vz}
cmp vy, rMinY add x, x, vx
movlt rMinY, vy add y, y, vy
cmp vx, rMaxX add z, z, vz
movgt rMaxX, vx
cmp vy, rMaxY add offset, sp, $dx
movgt rMaxY, vy 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 $index.skip
add x, x, vx
add y, y, vy
mov z, z, lsr #(FIXED_SHIFT + PROJ_SHIFT) ; z is positive
ldr z, [divLUT, z, lsl #2]
mul x, z, x
mul y, z, 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
$index.skip $index.skip
MEND MEND
transformBoxRect_asm transformBoxRect_asm
ldr m, =matrixPtr ldr m, =matrixPtr
ldr m, [m] ldr m, [m]
ldr m, [m, #(11 * 4)] ldr bz, [m, #(11 * 4)]
cmp m, #VIEW_MIN_F sub bz, bz, #VIEW_MIN_F
movlt r0, #0 cmp bz, #(VIEW_MAX_F - VIEW_MIN_F)
movlt pc, lr movhi r0, #0
cmp m, #VIEW_MAX_F movhi pc, lr
movge r0, #0
movge pc, lr
stmfd sp!, {r4-r6, lr} stmfd sp!, {rectArg, r4-r11, lr}
mov rect, rectArg ; to use after projectVertices_asm call
ldmia boxArg, {xx, yy, zz} ldmia boxArg, {xx, yy, zz}
mov minX, xx, asr #16 add m, m, #(12 * 4)
mov maxX, xx, lsl #16
mov maxX, maxX, asr #(16 - F16_SHIFT)
mov minX, minX, lsl #2
mov minY, yy, asr #16 ; pre-transform min/max Z
mov maxY, yy, lsl #16 ldmdb m!, {mx, my, mz, vx, vy, vz}
mov maxY, maxY, asr #(16 - F16_SHIFT) mov min, zz, asr #16
mov minY, minY, lsl #2 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 minZ, zz, asr #16 mov max, zz, lsl #16
mov maxZ, zz, lsl #16 mov max, max, asr #16
mov maxZ, maxZ, asr #(16 - F16_SHIFT) mla maxX, max, mx, vx
mov minZ, minZ, lsl #2 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}
ldr vptr, =gVertices ; pre-transform min/max Y
ldmdb m!, {mx, my, mz}
mov vert, vptr mov min, yy, asr #16
stmia vert!, {minX, minY, minZ} mul minX, mx, min
stmia vert!, {maxX, minY, minZ} mul minY, my, min
stmia vert!, {minX, maxY, minZ} mul minZ, mz, min
stmia vert!, {maxX, maxY, minZ} mov minX, minX, asr #FIXED_SHIFT
stmia vert!, {minX, minY, maxZ} mov minY, minY, asr #FIXED_SHIFT
stmia vert!, {maxX, minY, maxZ}
stmia vert!, {minX, maxY, maxZ}
stmia vert!, {maxX, maxY, maxZ}
mov r0, #8 mov max, yy, lsl #16
bl projectVertices_asm ; TODO compare with non-SWI version 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, #INT_MAX ; pre-transform min/max X
mov rMinY, #INT_MAX ldmdb m!, {mx, my, mz}
mov rMaxX, #INT_MIN
mov rMaxY, #INT_MIN
mov vert, vptr mov min, xx, asr #16
_0 check mul minX, mx, min
_1 check mul minY, my, min
_2 check mul minZ, mz, min
_3 check mov minX, minX, asr #FIXED_SHIFT
_4 check mov minY, minY, asr #FIXED_SHIFT
_5 check
_6 check
_7 check
_done add rMinX, rMinX, #(FRAME_WIDTH >> 1) mov max, xx, lsl #16
add rMinY, rMinY, #(FRAME_HEIGHT >> 1) mov max, max, asr #16
add rMaxX, rMaxX, #(FRAME_WIDTH >> 1) mul maxX, max, mx
add rMaxY, rMaxY, #(FRAME_HEIGHT >> 1) 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}
stmia rect, {rMinX, rMinY, rMaxX, rMaxY} ldr divLUT, =divTable
mov rMinX, #MAX_INT32
mov rMinY, #MAX_INT32
mov rMaxX, #MIN_INT32
mov rMaxY, #MIN_INT32
_0 project #MIN_X, #MIN_Y, #MIN_Z
_1 project #MAX_X, #MIN_Y, #MIN_Z
_2 project #MIN_X, #MAX_Y, #MIN_Z
_3 project #MAX_X, #MAX_Y, #MIN_Z
_4 project #MIN_X, #MIN_Y, #MAX_Z
_5 project #MAX_X, #MIN_Y, #MAX_Z
_6 project #MIN_X, #MAX_Y, #MAX_Z
_7 project #MAX_X, #MAX_Y, #MAX_Z
_done mov w, #(FRAME_WIDTH >> 1)
mov h, #(FRAME_HEIGHT >> 1)
add rMinX, w, rMinX, asr #(16 - PROJ_SHIFT)
add rMinY, h, rMinY, asr #(16 - PROJ_SHIFT)
add rMaxX, w, rMaxX, asr #(16 - PROJ_SHIFT)
add rMaxY, h, rMaxY, asr #(16 - PROJ_SHIFT)
add sp, sp, #SIZE
ldmfd sp!, {rectArg}
stmia rectArg, {rMinX, rMinY, rMaxX, rMaxY}
mov r0, #1 mov r0, #1
ldmfd sp!, {r4-r6, pc} ldmfd sp!, {r4-r11, pc}
END END