1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-10 23:24:06 +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)
#define PERSPECTIVE_DZ(z) (z >> 4)
#define PROJ_SHIFT 4
#define PERSPECTIVE_DZ(z) (z >> PROJ_SHIFT)
#define PERSPECTIVE(x, y, z) {\
int32 dz = PERSPECTIVE_DZ(z);\
if (dz >= DIV_TABLE_SIZE) dz = DIV_TABLE_SIZE - 1;\
int32 d = FixedInvU(dz);\
x = (x * d) >> 12;\
y = (y * d) >> 12;\
x = (x * d) >> (16 - PROJ_SHIFT);\
y = (y * d) >> (16 - PROJ_SHIFT);\
}
#elif defined(MODE13)
#define PERSPECTIVE(x, y, z) {\

View File

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

View File

@@ -696,7 +696,7 @@ bool transformBoxRect_c(const AABBs* box, RectMinMax* rect)
}
const int32* ptr = (int32*)box;
#if 0
int32 minX = ptr[0] >> 16 << F16_SHIFT;
int32 maxX = ptr[0] << 16 >> (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->x1 = x1 + (FRAME_WIDTH / 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;
}

View File

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