diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index 16c174f8b8..65774c1ca7 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -15186,7 +15186,7 @@ (define-extern get-debug-line (function debug-line)) (define-extern internal-draw-debug-line (function bucket-id vector vector rgba symbol rgba pointer)) (define-extern draw-string (function string dma-buffer font-context float)) -(define-extern transform-float-point (function vector vector vector)) +(define-extern transform-float-point (function vector vector4w vector4w)) (define-extern add-debug-point (function symbol bucket-id vector symbol)) ;; unused (define-extern add-debug-outline-triangle (function symbol bucket-id vector vector vector rgba symbol)) (define-extern add-debug-triangle-normal (function symbol bucket-id vector vector vector rgba symbol)) diff --git a/game/graphics/opengl_renderer/DirectRenderer.cpp b/game/graphics/opengl_renderer/DirectRenderer.cpp index c1f2ec8738..a54e4cdcef 100644 --- a/game/graphics/opengl_renderer/DirectRenderer.cpp +++ b/game/graphics/opengl_renderer/DirectRenderer.cpp @@ -540,7 +540,7 @@ void DirectRenderer::handle_xyzf2_packed(const u8* data, SharedRenderState* rend u8 f = (upper >> 36); bool adc = upper & (1ull << 47); assert(!adc); - assert(!f); + // assert(!f); handle_xyzf2_common(x, y, z, f, render_state); } @@ -619,7 +619,8 @@ void DirectRenderer::handle_xyzf2_common(u32 x, if (m_prim_buffer.is_full()) { flush_pending(render_state); } - assert(f == 0); + // assert(f == 0); + m_prim_building.building_st.at(m_prim_building.building_idx) = m_prim_building.st_reg; m_prim_building.building_rgba.at(m_prim_building.building_idx) = m_prim_building.rgba_reg; m_prim_building.building_vert.at(m_prim_building.building_idx) = {x << 16, y << 16, z}; @@ -669,39 +670,44 @@ void DirectRenderer::handle_xyzf2_common(u32 x, } } break; - // case GsPrim::Kind::LINE: { - // if (m_prim_building.building_idx == 1) { - // math::Vector pt0 = m_prim_building.building_vert[0].cast(); - // math::Vector pt1 = m_prim_building.building_vert[1].cast(); - // auto normal = (pt1 - pt0).normalized().cross({0, 0, 1}); - // - // double line_width = (1 << 28); - // fmt::print("Line:\n "); - // fmt::print(" {} {} {} {}\n", m_prim_building.building_vert[0].x(), - // m_prim_building.building_vert[0].y(), - // m_prim_building.building_vert[1].x(), - // m_prim_building.building_vert[1].y()); - // // debug_print_vtx(m_prim_building.building_vert[0]); - // // debug_print_vtx(m_prim_building.building_vert[1]); - // - // math::Vector a = pt0 + normal * line_width; - // math::Vector b = pt1 + normal * line_width; - // math::Vector c = pt0 - normal * line_width; - // math::Vector d = pt1 - normal * line_width; - // - // // ACB: - // m_prim_buffer.push(m_prim_building.building_rgba[0], a.cast(), {}); - // m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast(), {}); - // m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast(), {}); - // // b c d - // m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast(), {}); - // m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast(), {}); - // m_prim_buffer.push(m_prim_building.building_rgba[1], d.cast(), {}); - // // - // - // m_prim_building.building_idx = 0; - // } - // } break; + + case GsPrim::Kind::TRI: + if (m_prim_building.building_idx == 3) { + m_prim_building.building_idx = 0; + for (int i = 0; i < 3; i++) { + m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i], + m_prim_building.building_st[i]); + } + } + break; + case GsPrim::Kind::LINE: { + if (m_prim_building.building_idx == 2) { + math::Vector pt0 = m_prim_building.building_vert[0].cast(); + math::Vector pt1 = m_prim_building.building_vert[1].cast(); + auto normal = (pt1 - pt0).normalized().cross({0, 0, 1}); + + double line_width = (1 << 19); + // debug_print_vtx(m_prim_building.building_vert[0]); + // debug_print_vtx(m_prim_building.building_vert[1]); + + math::Vector a = pt0 + normal * line_width; + math::Vector b = pt1 + normal * line_width; + math::Vector c = pt0 - normal * line_width; + math::Vector d = pt1 - normal * line_width; + + // ACB: + m_prim_buffer.push(m_prim_building.building_rgba[0], a.cast(), {}); + m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast(), {}); + m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast(), {}); + // b c d + m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast(), {}); + m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast(), {}); + m_prim_buffer.push(m_prim_building.building_rgba[1], d.cast(), {}); + // + + m_prim_building.building_idx = 0; + } + } break; default: fmt::print("prim type {} is unsupported.\n", (int)m_prim_building.kind); assert(false); diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.cpp b/game/graphics/opengl_renderer/OpenGLRenderer.cpp index 588145991d..6c1896f400 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.cpp +++ b/game/graphics/opengl_renderer/OpenGLRenderer.cpp @@ -70,7 +70,7 @@ void OpenGLRenderer::init_bucket_renderers() { */ void OpenGLRenderer::render(DmaFollower dma, int window_width_px, int window_height_px) { setup_frame(window_width_px, window_height_px); - draw_test_triangle(); + // draw_test_triangle(); // render the buckets! dispatch_buckets(dma); } diff --git a/goal_src/engine/camera/math-camera.gc b/goal_src/engine/camera/math-camera.gc index 8648c84998..3c53a02e98 100644 --- a/goal_src/engine/camera/math-camera.gc +++ b/goal_src/engine/camera/math-camera.gc @@ -467,9 +467,9 @@ (.mul.x.vf acc vf24 vf28) (.add.mul.y.vf acc vf25 vf28 acc) (.add.mul.z.vf acc vf26 vf28 acc) - (.add.mul.w.vf vf28 vf27 vf0 acc) - (.add.w.vf vf23 vf0 vf0) - (.mul.vf vf31 vf28 vf29) + (.add.mul.w.vf vf28 vf27 vf0 acc) ;; matrix mult. + (.add.w.vf vf23 vf0 vf0) ;; clear w. + (.mul.vf vf31 vf28 vf29) ;; scale. ;;(TODO.VCLIP vf31 vf31) (let ((clip (vu-clip vf31 0))) (.div.vf Q vf0 vf31 :fsf #b11 :ftf #b11) diff --git a/goal_src/engine/debug/debug.gc b/goal_src/engine/debug/debug.gc index 2843cc4e0a..85b323bae4 100644 --- a/goal_src/engine/debug/debug.gc +++ b/goal_src/engine/debug/debug.gc @@ -5,8 +5,12 @@ ;; name in dgo: debug ;; dgos: GAME, ENGINE +;; This file contains functions for debug drawing. +;; In general, the 3d functions draw using the camera and the 2d functions draw in screen coordinated. +;; Most functions take a boolean as their first argument. If the boolean is set to #f, it will skip drawing the point. -(defun transform-float-point ((in vector) (out vector)) + +(defun transform-float-point ((in vector) (out vector4w)) "Transform point in and store the result in out. This uses the cached vf register transformation matrix Note that the input/output order of the arguments is swapped from usual" @@ -44,7 +48,8 @@ ;; They do a DMA packet per thing drawn. (defun-debug add-debug-point ((enable-draw symbol) (bucket bucket-id) (pt vector)) - "Draw a point." + "Draw a point. + The point is actually a pretty large square with some weird rgb gradient." (if (not enable-draw) (return #f) ) @@ -60,8 +65,9 @@ (new 'static 'gif-tag64 :nloop 1 :eop 1 :pre 1 :nreg 8 :prim (gif-prim tri-strip)) (gs-reg-list rgbaq xyzf2 rgbaq xyzf2 rgbaq xyzf2 rgbaq xyzf2) ) - - (set! (-> s5-0 vector 1 x) 255) + + ;; upper point is red + (set! (-> s5-0 vector 1 x) 255) ;; r (set! (-> s5-0 vector 1 y) 128) (set! (-> s5-0 vector 1 z) 128) (set! (-> s5-0 vector 1 w) 128) @@ -70,16 +76,18 @@ (-> s5-0 quad 1) (-> s5-0 quad 0) ) - + + ;; left point is green (+! (-> s5-0 vector 0 x) -256) (+! (-> s5-0 vector 0 y) -160) (set! (-> s5-0 vector 1 x) 128) - (set! (-> s5-0 vector 1 y) 255) + (set! (-> s5-0 vector 1 y) 255) ;; g (dma-buffer-add-uint128 v1-7 (-> s5-0 quad 1) (-> s5-0 quad 0) ) - + + ;; right point is blue (+! (-> s5-0 vector 0 x) 512) (set! (-> s5-0 vector 1 y) 128) (set! (-> s5-0 vector 1 z) 255) @@ -87,7 +95,8 @@ (-> s5-0 quad 1) (-> s5-0 quad 0) ) - + + ;; bottom point is red again (+! (-> s5-0 vector 0 x) -256) (+! (-> s5-0 vector 0 y) -160) (set! (-> s5-0 vector 1 x) 255) @@ -244,21 +253,21 @@ #f ) -(defun-debug add-debug-flat-triangle ((arg0 symbol) (arg1 bucket-id) (arg2 vector) (arg3 vector) (arg4 vector) (arg5 rgba)) - (if (not arg0) +(defun-debug add-debug-flat-triangle ((enable-draw symbol) (bucket bucket-id) (p0 vector) (p1 vector) (p2 vector) (arg5 rgba)) + (if (not enable-draw) (return #f) ) (let ((s5-0 (new 'stack 'vector4w-3)) (s4-0 (new 'stack 'vector4w-3)) ) - (set! (-> arg2 w) 1.0) - (set! (-> arg3 w) 1.0) - (set! (-> arg4 w) 1.0) - (when (and (transform-point-qword! (-> s5-0 vector 0) arg2) - (transform-point-qword! (-> s5-0 vector 1) arg3) - (transform-point-qword! (-> s5-0 vector 2) arg4) + (set! (-> p0 w) 1.0) + (set! (-> p1 w) 1.0) + (set! (-> p2 w) 1.0) + (when (and (transform-point-qword! (-> s5-0 vector 0) p0) + (transform-point-qword! (-> s5-0 vector 1) p1) + (transform-point-qword! (-> s5-0 vector 2) p2) ) - (with-dma-buffer-add-bucket ((v1-9 (current-display-frame debug-buf)) (current-display-frame bucket-group) arg1) + (with-dma-buffer-add-bucket ((v1-9 (current-display-frame debug-buf)) (current-display-frame bucket-group) bucket) (with-cnt-vif-block (v1-9) (dma-buffer-add-gif-tag v1-9 (new 'static 'gif-tag64 :nloop 1 :eop 1 :pre 1 :nreg 6 :prim (gif-prim tri)) diff --git a/goal_src/examples/debug-draw-example.gc b/goal_src/examples/debug-draw-example.gc new file mode 100644 index 0000000000..d5e92e4356 --- /dev/null +++ b/goal_src/examples/debug-draw-example.gc @@ -0,0 +1,130 @@ +;; This file demonstrates how to use the debug draw. + +;; To run this: + +#| +(make-group "iso") ;; build the game +(lt) ;; connect to the runtime +(lg) ;; have the runtime load the game engine +(test-play) ;; start the game loop +(ml "goal_src/examples/debug-draw-example.gc") ;; build and load this file. +|# + +(defun hack-update-camera ((location vector) (inv-rot matrix)) + "Debugging function to set the camera's position and orientation" + ;; update to compute the perspective matrix. + (update-math-camera + *math-camera* + (-> *setting-control* current video-mode) + (-> *setting-control* current aspect-ratio) + ) + + ;; copy the input rotation + (matrix-copy! (-> *math-camera* inv-camera-rot) inv-rot) + ;; inverse of rotation matrix matrix is its transpose + (matrix-transpose! (-> *math-camera* camera-rot) (-> *math-camera* inv-camera-rot)) + + ;; fake some value here + (set! (-> *math-camera* fov-correction-factor) 1.0) + + ;; do the math + (set! (-> *math-camera* trans quad) (-> location quad)) + (let ((cam-temp (-> *math-camera* camera-temp)) + (cam-rot (-> *math-camera* camera-rot)) + (inv-cam-rot (-> *math-camera* inv-camera-rot)) + (cam-trans (-> *math-camera* trans)) + ) + (let ((rotated-trans (new-stack-vector0))) + (set! (-> rotated-trans x) (- (-> cam-trans x))) + (set! (-> rotated-trans y) (- (-> cam-trans y))) + (set! (-> rotated-trans z) (- (-> cam-trans z))) + (set! (-> rotated-trans w) 1.0) + (vector-matrix*! rotated-trans rotated-trans cam-rot) + (set! (-> cam-rot vector 3 quad) (-> rotated-trans quad)) + ) + (matrix*! cam-temp cam-rot (-> *math-camera* perspective)) + (set! (-> inv-cam-rot vector 3 quad) (-> cam-trans quad)) + ) + + (none) + ) + +(defun test-function ((iter int)) + "This function draws the debug stuff. You can edit this, then reload this file to play with it." + + ;; val will increase from 0 to 1, then reset back to 0. + (let* ((frame (the float (mod (* 4 iter) 1600))) + (val (/ frame 1600.0))) + (format *stdcon* "~0kval ~f~%" val) + + ;; orbit the camera around in a circle with radius 5 m. + (let* ((rad (meters 5.0)) + (x (* rad (sin (* (degrees 360.0) val)))) + (z (* rad (cos (* (degrees 360.0) val)))) + (cam-pos (new 'stack 'vector)) + (cam-inv-rot (new 'stack 'matrix)) + ) + ;; this matrix will look directly at the origin... + (set! (-> cam-pos x) x) + (set! (-> cam-pos z) z) + (set! (-> cam-pos y) (meters 2.)) + (forward-down->inv-matrix cam-inv-rot cam-pos (new 'static 'vector :y 1.0)) + + ;; if the camera is here. + (set! (-> cam-pos x) (- 0. x)) + (set! (-> cam-pos z) (- 0. z)) + (set! (-> cam-pos y) (meters -2.)) + (hack-update-camera cam-pos cam-inv-rot) + + + ;; create some test points + (let ((p0 (new 'static 'vector :x (meters .8) :y (meters .2) :z (meters 2.0))) + (p1 (new 'static 'vector :x (meters .3) :y (meters .3) :z (meters 2.5))) + (p2 (new 'static 'vector :x (meters .5) :y (meters .7) :z (meters 1.5))) + ) + + ;;(add-debug-point #t (bucket-id debug-draw0) (new 'static 'vector)) + (add-debug-x #t (bucket-id debug-draw0) (new 'static 'vector) (new 'static 'rgba :g #x80 :a #x80)) + (add-debug-box #t (bucket-id debug-draw0) p0 p2 (new 'static 'rgba :b #x80 :a #x80)) + (add-debug-flat-triangle #t (bucket-id debug-draw0) p0 p1 p2 (new 'static 'rgba :r #x80)) + (add-debug-text-3d #t (bucket-id debug-draw0) "triangle!" p0 (the rgba 1) (the vector2h #f)) + (add-debug-sphere #t (bucket-id debug-draw0) p2 (meters 0.5) (new 'static 'rgba :r #x80)) + ) + ) + + ;; these also work + ;; (draw-end-credits (the int frame)) + ;; (draw-title-credits val) + + ) + (none) + ) + + +(defun launch-test-process () + "Call this to launch a process that draws the debug demo" + (let ((proc (get-process *nk-dead-pool* process 1024))) + (activate proc *active-pool* 'test *kernel-dram-stack*) + (run-next-time-in-process proc (lambda () + (let ((iter 0)) + (while #t + (test-function iter) + (suspend) + (+! iter 1) + ) + ) + ) + ) + proc) + + ) + +;; This will spawn a process the first time this file is loaded +(define-perm *test-process* process (launch-test-process)) + +(defun kill-test-procs () + "Kill all processes started by launch-test-process" + (kill-by-name "test" *active-pool*) + ) + +(set! *display-profile* #t)