From 69f2c0d036a236025a8e26cd5af0944212ebeb2d Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 8 Aug 2026 23:13:18 -0400 Subject: [PATCH] Prepping for: resolve_look_at impl. --- code/duffle/dsl.h | 4 +- code/duffle/gen/macs.h | 21 ++++++++ code/duffle/gte.h | 6 ++- code/duffle/math.atom.c | 18 +++++++ code/duffle/math.h | 30 ++++++++--- code/duffle/psyq.h | 8 ++- code/hello_camera/gen/offsets.h | 2 +- code/hello_camera/hello_camera.atom.c | 65 +++++++++++++---------- code/hello_camera/hello_camera.c | 74 +++++++++++++++------------ code/hello_camera/hello_camera.h | 6 +-- scripts/update_deps.ps1 | 5 ++ 11 files changed, 164 insertions(+), 75 deletions(-) diff --git a/code/duffle/dsl.h b/code/duffle/dsl.h index f01b0a6..a501f00 100644 --- a/code/duffle/dsl.h +++ b/code/duffle/dsl.h @@ -134,8 +134,8 @@ typedef __UINT32_TYPE__ TSet_(B4); #define u4_v(value) C_(U4 V_*, value) enum { false = 0, true = 1, true_overflow, }; -#define u4_lo(value) ((value) & 0xFFFFU) -#define u4_hi(value) ((value) >> 12) +#define u4_lo(value) (u4_(value) & 0xFFFFU) +#define u4_hi(value) (u4_(value) >> (S_(U2) * 8)) typedef void Proc_(VoidFn) (void); diff --git a/code/duffle/gen/macs.h b/code/duffle/gen/macs.h index e20e7a3..b29be3c 100644 --- a/code/duffle/gen/macs.h +++ b/code/duffle/gen/macs.h @@ -70,6 +70,27 @@ WORD_COUNT(mac_load_v2s2, 2) , store_half(rt_y, base, offset + O_(V2_S2,y)) WORD_COUNT(mac_store_v2s2, 2) +/* atom_dbg_skip */ +#define mac_load_v3s4(rs_x, rs_y, rs_z, r_base, offset) \ + load_word( rs_x, r_base, O_(V3_S4,x)) \ +, load_word( rs_y, r_base, O_(V3_S4,y)) \ +, load_word( rs_z, r_base, O_(V3_S4,z)) +WORD_COUNT(mac_load_v3s4, 3) + +/* atom_dbg_skip */ +#define mac_store_v3s4(rt_x, rt_y, rt_z, base, offset) \ + store_word(rt_x, base, offset + O_(V3_S4,x)) \ +, store_word(rt_y, base, offset + O_(V3_S4,y)) \ +, store_word(rt_z, base, offset + O_(V3_S4,z)) +WORD_COUNT(mac_store_v3s4, 3) + +/* atom_dbg_skip */ +#define mac_sub_v3s4(rds_x, rds_y, rds_z, rt_x, rt_y, rt_z) \ + sub_s(rds_x, rds_x, rt_x) \ +, sub_s(rds_y, rds_y, rt_y) \ +, sub_s(rds_z, rds_z, rt_z) +WORD_COUNT(mac_sub_v3s4, 3) + /* atom_dbg_skip */ #define mac_store_rects2(rt_x, rt_y, rt_width, rt_height, base, offset) \ store_half(rt_x, base, offset + O_(Rect_S2,x)) \ diff --git a/code/duffle/gte.h b/code/duffle/gte.h index 40f0af8..30c264b 100644 --- a/code/duffle/gte.h +++ b/code/duffle/gte.h @@ -378,11 +378,15 @@ enum { _C2_TX_SUBS_ = 0 #define gte_cmdw_nclip (gte_cmd_base | enc_gte_cmd(gte_cmd_nclip)) #define gte_cmdw_op (gte_cmd_base | enc_gte_cmd(gte_cmd_op )) #define gte_cmdw_outer_product gte_cmdw_op /* "outer product" -- NOCASH/Sdk terminology */ -#define gte_cmdw_wedge gte_cmdw_op /* "wedge product" -- geometric-algebra terminology */ +#define gte_cmdw_wedge gte_cmdw_op /* "wedge product" -- geometric-algebra terminology. + * RGA(Lengyel): the GTE OP is a 3D signed-16-bit D x IR cross, not a generic RGA exterior product. + * The wedge alias is the 3D complement interpretation of the same 3 scalars (MAC1..MAC3). */ #define gte_cmdw_mvmva (gte_cmd_base | enc_gte_cmd(gte_cmd_mvmva)) #define gte_cmdw_rotate_translate_perspective_single gte_cmdw_rtps #define gte_cmdw_rotate_translate_perspective_triple gte_cmdw_rtpt +/* RGA(Lengyel): RTPS/RTPT consume the matrix expansion of a rigid transformation (rotation matrix + translation vector) loaded into the RT/TR control registers. + * For unitized points the same result equals the motor antiproduct; the GTE executes the LA form, not a symbolic antiproduct. */ /* PsyQ compatibility bits for AVSZ3 (Bits 20, 22, 24 must be set) */ #define gte_cmdw_psyq_avsz3_compat (0x15 << 20) diff --git a/code/duffle/math.atom.c b/code/duffle/math.atom.c index c01fe66..68ee017 100644 --- a/code/duffle/math.atom.c +++ b/code/duffle/math.atom.c @@ -19,6 +19,24 @@ FI_ Slice_MipsCode ac_store_v2s2(U4 rt_x, U4 rt_y, U4 base, U4 offset) atom_dbg_ store_half(rt_y, base, offset + O_(V2_S2,y)), }) +FI_ Slice_MipsCode ac_load_v3s4(U4 rs_x, U4 rs_y, U4 rs_z, U4 r_base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ac_load_v3s4, { + load_word( rs_x, r_base, O_(V3_S4,x)), + load_word( rs_y, r_base, O_(V3_S4,y)), + load_word( rs_z, r_base, O_(V3_S4,z)), +}) + +FI_ Slice_MipsCode ac_store_v3s4(U4 rt_x, U4 rt_y, U4 rt_z, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ac_store_v3s4, { + store_word(rt_x, base, offset + O_(V3_S4,x)), + store_word(rt_y, base, offset + O_(V3_S4,y)), + store_word(rt_z, base, offset + O_(V3_S4,z)), +}) + +FI_ Slice_MipsCode ac_sub_v3s4(U4 rds_x, U4 rds_y, U4 rds_z, U4 rt_x, U4 rt_y, U4 rt_z) atom_dbg_skip MipsAtomComp_Proc_(ac_sub_v3s4, { + sub_s(rds_x, rds_x, rt_x), + sub_s(rds_y, rds_y, rt_y), + sub_s(rds_z, rds_z, rt_z), +}) + FI_ Slice_MipsCode ac_store_rects2(U4 rt_x, U4 rt_y, U4 rt_width, U4 rt_height, U4 base, U4 offset) atom_dbg_skip MipsAtomComp_Proc_(ac_store_rects2, { store_half(rt_x, base, offset + O_(Rect_S2,x)), store_half(rt_y, base, offset + O_(Rect_S2,y)), diff --git a/code/duffle/math.h b/code/duffle/math.h index a518231..40e08e9 100644 --- a/code/duffle/math.h +++ b/code/duffle/math.h @@ -7,6 +7,18 @@ #define max(A, B) (((A) > (B)) ? (A) : (B)) #define clamp_bot(X, B) max(X, B) +/* Convention + ## _ ## +For types with compound data (Ex: Rotation Matrix & Translation): + ## ## _ ## ## ## + +A: Array +V: Vector +R: Range +M: Matrix +T: Translation +*/ + enum { v3s2_byteoff = 3, // log2(8), used with shift_left_logical op for index via byte offset. }; @@ -27,17 +39,25 @@ typedef Struct_(V2_U1) { U1 x; U1 y; }; typedef Struct_(V2_S2) { S2 x; S2 y; }; typedef Struct_(V2_S4) { S4 x; S4 y; }; typedef Struct_(V3_S2) { S2 x; S2 y; S2 z; S2 pad; }; // PSY-Q: SVECTOR -typedef Struct_(V3_S4) { S4 x; S4 y; S4 z; S4 pad; }; // PSY-Q: VECTOR +typedef Struct_(V3_S4) { S4 x; S4 y; S4 z; S4 pad; }; // PSY-Q: VECTOR. RGA(Lengyel): Euclidean vector or direction. A zero-weight RGA point is stored as a V3_S4 with the implicit weight dropped. typedef Struct_(V4_S2) { S2 x; S2 y; S2 z; S2 w; }; typedef Struct_(V4_S4) { S4 x; S4 y; S4 z; S4 w; }; -typedef Struct_(R2_S2) { V2_S2 p0; V2_S2 p1; }; -typedef Struct_(R2_S4) { V2_S4 p0; V2_S4 p1; }; +// typedef Struct_(P3_S4) { S4 x; S4 y; S4 z; S4 w1; }; // RGA(Lengyel): Affine point with implicit weight one. Storage alias of V3_S4. Use P3_S4 when the value is a point. +typedef V3_S4 P3_S4; + +typedef Struct_(R2_S2) { V2_S2 p0; V2_S2 p1; }; // Range-2 Signed 2-Byte (16-bit) +typedef Struct_(R2_S4) { V2_S4 p0; V2_S4 p1; }; // Range-2 Signed 4-Byte (32-bit) typedef Struct_(Rect_S2) { S2 x; S2 y; S2 width; S2 height; }; typedef Struct_(Rect_S4) { S4 x; S4 y; S4 width; S4 height; }; -typedef Struct_(MT3_S2S4) { A3x3_S2 m; A3_S4 t; }; // PSY-Q: MATRIX +typedef Struct_(MT3_S2S4) { A3x3_S2 m; A3_S4 t; }; // PSY-Q: MATRIX. RGA(Lengyel): Matrix expansion of a rigid transformation. GTE utilizes this representation; corresponding motor not constructed here. + +/* RGA(Lengyel) reserved names (deferred): + * P4_S4 - future flat point with explicit weight (Lengyel/TML FlatPoint3D analog). + * B3_S4 - future 3D bivector (callers store a Complement(Wedge(...)) as a V3_S4). + * Mo8_S4 - future motor. Not introduced until a course operation actually needs composition, interpolation, or inversion. */ typedef Array_(V2_U1, 2); typedef Array_(V2_S2, 2); @@ -93,5 +113,3 @@ FI_ void sub_v3s4 (V3_S4_R out_a, V3_S4 b) { sub_a3s4 (pcast(A3_S4_R, out_a FI_ void sub_v3s4_fp(V3_S4_R out_a, V3_S4 b) { sub_a3s4_fp(pcast(A3_S4_R, out_a), pcast(A3_S4, b)); } FI_ void mul_v3s4 (V3_S4_R out_a, V3_S4 b) { mul_a3s4 (pcast(A3_S4_R, out_a), pcast(A3_S4, b)); } - - diff --git a/code/duffle/psyq.h b/code/duffle/psyq.h index 39def23..3fdfd44 100644 --- a/code/duffle/psyq.h +++ b/code/duffle/psyq.h @@ -103,13 +103,19 @@ void gte_matrix_set_rotation (MT3_S2S4* mat) asm("SetRotMatrix"); void gte_matrix_set_translation(MT3_S2S4* mat) asm("SetTransMatrix"); // Einheit, Metrication to unit vector. "Normalization", not Orthogonal "Normal, Normalis". Directionalization. +// RGA(Lengyel): Normalize the bulk of a zero-weight direction. This is not finite-point unitization (which forces w=1). S4 normalize_v3s4(V3_S4* v0, V3_S4* v1) asm("VectorNormal"); +// RGA(Lengyel): Apply the matrix expansion of a rigid transformation. +// Motor antiproduct is equivalent for unitized points; LA form is what GTE consumes. V3_S4* mul_m3s2_v3s4(MT3_S2S4* m, V3_S4* v, V3_S4* result) asm("ApplyMatrixLV"); +// RGA(Lengyel): Store the full translation column. The motor translator would store half this displacement in m.xyz. MT3_S2S4* trans_m3s2(MT3_S2S4* m, V3_S4* off) asm("TransMatrix"); MT3_S2S4* gte_comp_coord_m3s2(MT3_S2S4* m0, MT3_S2S4* m1, MT3_S2S4* result) asm("CompMatrixLV"); -// TODO(Ed): Want to interpret this under the lens of Eric Lengyel's geometric algebra +// RGA(Lengyel): Complement(Wedge(a,b)), i.e. the Euclidean 3D complement of the exterior product, stored as a V3_S4. +// The underlying GTE OP is a specialized signed-16-bit D x IR command; the wedge interpretation is a 3D dual of the same 3 scalars. void cross_v3s4(V3_S4* v0, V3_S4* v1, V3_S4* result) asm("OuterProduct12"); + diff --git a/code/hello_camera/gen/offsets.h b/code/hello_camera/gen/offsets.h index 4b3fdc2..2e95a28 100644 --- a/code/hello_camera/gen/offsets.h +++ b/code/hello_camera/gen/offsets.h @@ -26,7 +26,7 @@ enum { atom_offset_end_low_exit_stick = _atom_offset_end_low_exit_stick, }; -// --- atom: pad_input_cam (41 words) --- +// --- atom: pad_input_cam (40 words) --- #define _atom_offset_left_x_exit_left_x 3 #define _atom_offset_right_x_exit_right_x 3 diff --git a/code/hello_camera/hello_camera.atom.c b/code/hello_camera/hello_camera.atom.c index f03df45..b0571b3 100644 --- a/code/hello_camera/hello_camera.atom.c +++ b/code/hello_camera/hello_camera.atom.c @@ -180,26 +180,6 @@ internal MipsAtom_(gp_screen_init) atom_info(atom_phase(screen_init), atom_reads mac_yield(), }; -/* ----- pad_apply_input ----- - * Reads pad[0].buttons + pad[0].left_x; - * Applies the input-semantics deltas to cube_rot.y + floor_rot.y: - * - D-pad Left: cube_rot.y += 30, floor_rot.y += 5 - * - D-pad Right: cube_rot.y -= 30, floor_rot.y -= 5 - * - Analog stick X (dead zone 0x70..0x90): - * cube delta = (0x80 - left_x) >> 2 (range approx -32..+32) - * floor delta = (0x80 - left_x) >> 5 (range approx -4..+4) - * - D-pad + analog deltas add when used together. - * - * Convention: - * pad_state = 0 means no buttons active. - * The fail-safe zero-button value flows through unchanged, so a disconnected/fresh pad produces no rotation. - * The branch_le_zero pattern below matches the existing pad_input_demo convention (atom body lines 248/257). - * - * Signed-delta trick: - * load_byte_u zero-extends left_x to 32 bits; sub_u from 0x80 wraps to a SIGNED two's-complement value in the negative range; - * shift_aright (sra) then correctly sign-extends the shift for both positive (left_x < 0x80) and negative (left_x > 0x80) cases. - * Digital pads publish left_x = 0x80 → delta = 0 → no rotation, so the analog step is naturally a no-op for digital controllers. - */ typedef Struct_(Binds_PadApplyInput) { PadState* state; V3_S2* cube_rot; @@ -334,10 +314,9 @@ internal MipsAtom_(pad_input_cam) atom_info(atom_bind(Binds_PadInputCam) load_word(R_T1, R_Cam, O_(Camera,pos.x)), // BD-Slot. // D-pad Left → cam.pos.x -= 50. and_i fulfills BD-slot for load on R_Cam. - and_i(R_T3, R_T0, Pad_Left), branch_le_zero(R_T3, atom_offset(left_x, exit_left_x)), nop, + and_i(R_T3, R_T0, Pad_Left), branch_le_zero(R_T3, atom_offset(left_x, exit_left_x)), mac_yield_load(), add_si(R_T1, R_T1, -50), store_word(R_T1, R_Cam, O_(Camera,pos.x)), atom_label(exit_left_x) - /* D-pad Right → cam.pos.x += 50. Reuses R_T1 from Left. */ and_i(R_T3, R_T0, Pad_Right), branch_le_zero(R_T3, atom_offset(right_x, exit_right_x)), nop, add_si(R_T1, R_T1, 50), store_word(R_T1, R_Cam, O_(Camera,pos.x)), @@ -348,7 +327,6 @@ atom_label(exit_right_x) and_i(R_T3, R_T0, Pad_Up), branch_le_zero(R_T3, atom_offset(up_y, exit_up_y)), nop, add_si(R_T1, R_T1, -50), store_word(R_T1, R_Cam, O_(Camera,pos.y)), atom_label(exit_up_y) - /* D-pad Down → cam.pos.y += 50. Reuses R_T1 from Up. */ and_i(R_T3, R_T0, Pad_Down), branch_le_zero(R_T3, atom_offset(down_y, exit_down_y)), nop, add_si(R_T1, R_T1, 50), store_word(R_T1, R_Cam, O_(Camera,pos.y)), @@ -359,23 +337,54 @@ atom_label(exit_down_y) and_i(R_T3, R_T0, Pad_Cross), branch_le_zero(R_T3, atom_offset(cross_z, exit_cross_z)), nop, add_si(R_T1, R_T1, -50), store_word(R_T1, R_Cam, O_(Camera,pos.z)), atom_label(exit_cross_z) - /* D-pad Circle → cam.pos.z += 50. Reuses R_T1 from Cross. */ and_i(R_T3, R_T0, Pad_Circle), branch_le_zero(R_T3, atom_offset(circle_z, exit_circle_z)), nop, add_si(R_T1, R_T1, 50), store_word(R_T1, R_Cam, O_(Camera,pos.z)), atom_label(exit_circle_z) - mac_yield(), + mac_yield_tail(), }; enum { - _LookAt_WIP, + R_LookAt = R_T0 atom_reg atom_type(MT3_S2S4*), + R_CamEye = R_T1 atom_reg atom_type(P3_S4*), + R_CamTarget = R_T2 atom_reg atom_type(P3_S4*), + R_WorldUp = R_T3 atom_reg atom_type(V3_S4*), + + R_LkAt_Fwdx = R_T4 atom_reg atom_type(V3_S4*), + R_LkAt_Fwdy = R_T5 atom_reg atom_type(V3_S4*), + R_LkAt_Fwdz = R_T6 atom_reg atom_type(V3_S4*), + R_Eye_x = R_T7 atom_reg atom_type(V3_S4*), + R_Eye_y = R_T8 atom_reg atom_type(V3_S4*), + R_Eye_z = R_V0 atom_reg atom_type(V3_S4*), + + R_LkAt_Up = R_T5 atom_reg atom_type(V3_S4*), + R_LkAt_Right = R_T6 atom_reg atom_type(V3_S4*), + + R_AxisX = R_T7 atom_reg atom_type(V3_S4*), + R_AxisY = R_T8 atom_reg atom_type(V3_S4*), + R_AxisZ = R_T7 atom_reg atom_type(V3_S4*), }; typedef Struct_(Binds_ResolveLookAt) { - U1 bla; + MT3_S2S4* look_at; + P3_S4* eye; + P3_S4* target; + V3_S4* up_in; }; internal MipsAtom_(resolve_look_at) atom_info(atom_bind(Binds_ResolveLookAt)) { - add_ui_self(R_TapePtr, S_(Binds_ResolveLookAt)), + load_word(R_LookAt, R_TapePtr, O_(Binds_ResolveLookAt,look_at)), + load_word(R_CamEye, R_TapePtr, O_(Binds_ResolveLookAt,eye)), + load_word(R_CamTarget, R_TapePtr, O_(Binds_ResolveLookAt,target)), + load_word(R_WorldUp, R_TapePtr, O_(Binds_ResolveLookAt,up_in)), + add_ui_self( R_TapePtr, S_(Binds_ResolveLookAt)), + + // load look_at and eye, then subtract (get direction), then normalize to unit vector. + mac_load_v3s4(R_LkAt_Fwdx, R_LkAt_Fwdy, R_LkAt_Fwdz, R_LookAt, 0), + mac_load_v3s4(R_Eye_x, R_Eye_y, R_Eye_z, R_CamEye, 0), + mac_sub_v3s4( R_LkAt_Fwdx, R_LkAt_Fwdy, R_LkAt_Fwdz, + R_Eye_x, R_Eye_y, R_Eye_z), + + mac_yield(), }; diff --git a/code/hello_camera/hello_camera.c b/code/hello_camera/hello_camera.c index 551a97c..16dcb34 100644 --- a/code/hello_camera/hello_camera.c +++ b/code/hello_camera/hello_camera.c @@ -93,36 +93,40 @@ I_ B1* prim__alloc(U4 type_width, Str8 type_name) { #define prim_alloc(type) (type*)prim__alloc(S_(type), slit( stringify(type))) void -resolve_look_at_c11(MT3_S2S4* look_at, V3_S4* eye, V3_S4* target, V3_S4* up_in) { -// TODO(Ed): Want to interpret this under the lens of Eric Lengyel's geometric algebra +resolve_look_at_c11(MT3_S2S4* look_at, P3_S4* eye, P3_S4* target, V3_S4* up_in) { +// RGA(Lengyel): Build matrix expansion of a rigid transformation. Corresponding motor is not constructed; we write the LA form for GTE. +// Preconditions: eye != target, up_in not collinear with (target - eye). V3_S4 right, up, forward; V3_S4 ux, uy, uz; V3_S4 pos, off; - forward = target[0]; sub_v3s4(& forward, eye[0]); - normalize_v3s4(& forward, & uz); + forward = target[0]; sub_v3s4(& forward, eye[0]); // RGA(Lengyel): Affine point - point = zero-weight direction. + normalize_v3s4(& forward, & uz); // RGA(Lengyel): Normalize the direction bulk. Not finite-point unitization. - cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux); - cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); + cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux); // RGA(Lengyel): Complement(Wedge(forward, up_in)) -> right axis. + cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); // RGA(Lengyel): Complement(Wedge(forward, right)) -> up axis. + // RGA(Lengyel): matrix expansion of the world-to-camera rotation (basis rows). look_at->m[0][0] = ux.x; look_at->m[0][1] = ux.y; look_at->m[0][2] = ux.z; look_at->m[1][0] = uy.x; look_at->m[1][1] = uy.y; look_at->m[1][2] = uy.z; look_at->m[2][0] = uz.x; look_at->m[2][1] = uz.y; look_at->m[2][2] = uz.z; - - pos = eye[0]; mul_v3s4(& pos, v3s4(-1,-1,-1)); + pos = eye[0]; mul_v3s4(& pos, v3s4(-1,-1,-1)); // RGA(Lengyel): -eye in world coordinates (spatial bulk only; implicit weight is dropped). + + // RGA(Lengyel): R * (-eye) is the full matrix translation column. + // Motor translator would store half this displacement in m.xyz; GTE consumes full column. mul_m3s2_v3s4(look_at, & pos, & off); - trans_m3s2(look_at, & off); + trans_m3s2( look_at, & off); } -FI_ void camera_look_at_c11(Camera* c, V3_S4* target, V3_S4* up_in) { resolve_look_at_c11(& c->look_at, & c->pos, target, up_in); } +FI_ void camera_look_at_c11(Camera* c, P3_S4* target, V3_S4* up_in) { resolve_look_at_c11(& c->look_at, & c->pos, target, up_in); } GCC_OPTIMIZATION_DISABLE void update(PrimitiveArena* pa, U4* ordering_buf) { TapeBuilder tb = tb_make(slice_ut_arr(smem.MemTape)); - if (1) // Pad Input + // Pad Input { tb.used = 0; tb_scope_run(& tb) { // Grab latest state from bios. @@ -133,32 +137,10 @@ void update(PrimitiveArena* pa, U4* ordering_buf) tb_data_(raw, & smem.pad_raw[1]); tb_data_(state, & smem.pad[1]); - // TODO(Ed): Implement based on below. tb_emit_(pad_input_cam); tb_data_(state, & smem.pad[0]); tb_data_(cam, & smem.cam); - // if (pad0_btn_(Pad_Left)) { - // smem.cam.pos.x -= 50; - // } - // if (pad0_btn_(Pad_Right)) { - // smem.cam.pos.x += 50; - // } - // if (pad0_btn_(Pad_Up)) { - // smem.cam.pos.y -= 50; - // } - // if (pad0_btn_(Pad_Down)) { - // smem.cam.pos.y += 50; - // } - // if (pad0_btn_(Pad_Cross)) { - // smem.cam.pos.z -= 50; - // } - // if (pad0_btn_(Pad_Circle)) { - // smem.cam.pos.z += 50; - // } - - - // Demo input (not longer using) // tb_emit_(pad_input_cube_rotation); // tb_data_(state, & smem.pad[0]); // tb_data_(cube_rot, & smem.cube.rot); @@ -197,10 +179,36 @@ void update(PrimitiveArena* pa, U4* ordering_buf) // Camera look at (Tape) if (0) { + MT3_S2S4* look_at = & smem.cam.look_at; + P3_S4* eye = & smem.cam.pos; + V3_S4* up_in = & v3s4(0, -fp_one, 0); + + V3_S4 right, up, forward; + V3_S4 ux, uy, uz; + V3_S4 pos, off; + tb.used = 0; tb_scope_run(& tb) { tb_emit_(resolve_look_at); // tb_data_(); } + + // forward = target[0]; sub_v3s4(& forward, eye[0]); // RGA(Lengyel): Affine point - point = zero-weight direction. + // normalize_v3s4(& forward, & uz); // RGA(Lengyel): Normalize the direction bulk. Not finite-point unitization. + + cross_v3s4(& uz, up_in, & right); normalize_v3s4(& right, & ux); // RGA(Lengyel): Complement(Wedge(forward, up_in)) -> right axis. + cross_v3s4(& uz, & ux, & up); normalize_v3s4(& up, & uy); // RGA(Lengyel): Complement(Wedge(forward, right)) -> up axis. + + // RGA(Lengyel): matrix expansion of the world-to-camera rotation (basis rows). + look_at->m[0][0] = ux.x; look_at->m[0][1] = ux.y; look_at->m[0][2] = ux.z; + look_at->m[1][0] = uy.x; look_at->m[1][1] = uy.y; look_at->m[1][2] = uy.z; + look_at->m[2][0] = uz.x; look_at->m[2][1] = uz.y; look_at->m[2][2] = uz.z; + + pos = eye[0]; mul_v3s4(& pos, v3s4(-1,-1,-1)); // RGA(Lengyel): -eye in world coordinates (spatial bulk only; implicit weight is dropped). + + // RGA(Lengyel): R * (-eye) is the full matrix translation column. + // Motor translator would store half this displacement in m.xyz; GTE consumes full column. + mul_m3s2_v3s4(look_at, & pos, & off); + trans_m3s2( look_at, & off); } // Draw cube diff --git a/code/hello_camera/hello_camera.h b/code/hello_camera/hello_camera.h index 9c0de65..1746882 100644 --- a/code/hello_camera/hello_camera.h +++ b/code/hello_camera/hello_camera.h @@ -61,7 +61,7 @@ I_ void ent_cube128_init(A8_V3_S2* verts, A6_V4_S2* faces) { typedef Struct_(Ent_Cube) { V3_S4 accel; V3_S4 vel; - V3_S4 pos; + V3_S4 pos; // RGA(Lengyel): affine point with implicit weight one. Storage alias of V3_S4. V3_S4 scale; V3_S2 rot; A8_V3_S2 verts; @@ -88,7 +88,7 @@ I_ void ent_floor_init(A4_V3_S2* verts, A2_V3_S2* faces) { }; typedef Struct_(Ent_Floor) { V3_S4 accel; - V3_S4 pos; + V3_S4 pos; // RGA(Lengyel): affine point with implicit weight one. Storage alias of V3_S4. V3_S4 scale; V3_S2 rot; A4_V3_S2 verts; @@ -96,7 +96,7 @@ typedef Struct_(Ent_Floor) { }; typedef Struct_(Camera) { - V3_S4 pos; + P3_S4 pos; // RGA(Lengyel): affine point with implicit weight one. Storage alias of V3_S4. V3_S2 rot; MT3_S2S4 look_at; }; diff --git a/scripts/update_deps.ps1 b/scripts/update_deps.ps1 index d3711a0..ad814a8 100644 --- a/scripts/update_deps.ps1 +++ b/scripts/update_deps.ps1 @@ -14,16 +14,21 @@ $url_armips = 'https://github.com/Kingcom/armips.git' $url_pcsx_redux = 'https://github.com/grumpycoders/pcsx-redux.git' $url_psyq_iwyu = 'https://github.com/johnbaumann/psyq_include_what_you_use.git' $url_lpeg = 'https://github.com/roberto-ieru/LPeg.git' +# $url_mkpsxiso = 'https://github.com/Lameguy64/mkpsxiso.git' + +$url_mkpsxiso_win64 = 'https://github.com/Lameguy64/mkpsxiso/releases/download/v2.30/mkpsxiso-2.30-win64.zip' $path_armips = join-path $path_toolchain 'armips' $path_pcsx_redux = join-path $path_toolchain 'pcsx-redux' $path_psyq_iwyu = join-path $path_toolchain 'psyq_iwyu' $path_lpeg = join-path $path_toolchain 'lpeg' +$path_mkpsxiso = join-path $path_toolchain 'mkpsxiso' clone-gitrepo $path_armips $url_armips clone-gitrepo $path_lpeg $url_lpeg clone-gitrepo $path_pcsx_redux $url_pcsx_redux clone-gitrepo $path_psyq_iwyu $url_psyq_iwyu +# clone-gitrepo $path_mkpsxiso $url_mkpsxiso $path_armips_build = join-path $path_armips 'build' verify-path $path_armips_build