From fe0bfc56cde0ee8fed2e45aaa5a3f11a102e476b Mon Sep 17 00:00:00 2001 From: David Thompson Date: Mon, 10 May 2021 07:07:10 -0400 Subject: graphics: model: Pre-compute world matrices for model nodes. --- chickadee/graphics/model.scm | 139 ++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 76 deletions(-) diff --git a/chickadee/graphics/model.scm b/chickadee/graphics/model.scm index 449bf87..a337535 100644 --- a/chickadee/graphics/model.scm +++ b/chickadee/graphics/model.scm @@ -64,54 +64,35 @@ ;;; (define-record-type - (%make-render-state renderer view-matrix - matrix-stack matrix-pool) + (%make-render-state renderer view-matrix model-matrix world-model-matrix) render-state? (renderer render-state-renderer) (view-matrix render-state-view-matrix) - (matrix-stack render-state-matrix-stack) - (matrix-pool render-state-matrix-pool)) + (model-matrix render-state-model-matrix) + (world-model-matrix render-state-world-model-matrix)) (define (make-render-state renderer) (%make-render-state renderer (make-identity-matrix4) - (make-array-list) - (array-list (make-identity-matrix4)))) - -(define (render-state-matrix-borrow state) - (let ((mpool (render-state-matrix-pool state))) - (if (array-list-empty? mpool) - (make-identity-matrix4) - (array-list-pop! mpool)))) - -(define (render-state-matrix-current state) - (let ((mstack (render-state-matrix-stack state))) - (array-list-ref mstack (- (array-list-size mstack) 1)))) + (make-identity-matrix4) + (make-identity-matrix4))) (define (render-state-reset! state) (matrix4-identity! (render-state-view-matrix state)) - (let ((mstack (render-state-matrix-stack state)) - (mpool (render-state-matrix-pool state))) - (let loop () - (unless (array-list-empty? mstack) - (array-list-push! mpool (array-list-pop! mstack)) - (loop))) - (let ((m (render-state-matrix-borrow state))) - (matrix4-identity! m) - (array-list-push! mstack m)))) + (matrix4-identity! (render-state-model-matrix state))) (define (render-state-view-matrix-mult! state matrix) (let ((view (render-state-view-matrix state))) (matrix4-mult! view view matrix))) -(define (render-state-matrix-push-and-mult! state matrix) - (let ((new (render-state-matrix-borrow state))) - (matrix4-mult! new matrix (render-state-matrix-current state)) - (array-list-push! (render-state-matrix-stack state) new))) +(define (render-state-model-matrix-mult! state matrix) + (let ((model (render-state-model-matrix state))) + (matrix4-mult! model model matrix))) -(define (render-state-matrix-pop! state) - (array-list-push! (render-state-matrix-pool state) - (array-list-pop! (render-state-matrix-stack state)))) +(define (render-state-world-model-matrix-mult! state matrix) + (matrix4-mult! (render-state-world-model-matrix state) + (render-state-model-matrix state) + matrix)) ;;; @@ -129,13 +110,13 @@ (define (draw-primitive/phong primitive state) (shader-apply/phong (primitive-vertex-array primitive) (primitive-material primitive) - (render-state-matrix-current state) + (render-state-world-model-matrix state) (render-state-view-matrix state))) (define (draw-primitive/pbr primitive state) (shader-apply/pbr (primitive-vertex-array primitive) (primitive-material primitive) - (render-state-matrix-current state) + (render-state-world-model-matrix state) (render-state-view-matrix state))) @@ -162,29 +143,31 @@ ;; A tree of meshes with their own transformation matrices. (define-record-type - (%make-model-node name mesh matrix children) + (%make-model-node name mesh matrix world-matrix children) model-node? (name model-node-name) (mesh model-node-mesh) (matrix model-node-matrix) + (world-matrix model-node-world-matrix) (children model-node-children)) (define* (make-model-node #:key (name "anonymous") mesh (matrix (make-identity-matrix4)) + (world-matrix (make-identity-matrix4)) (children '())) - (%make-model-node name mesh matrix children)) + (%make-model-node name mesh matrix world-matrix children)) (define (draw-model-node node state) - (render-state-matrix-push-and-mult! state (model-node-matrix node)) (for-each (lambda (child) (draw-model-node child state)) (model-node-children node)) (let ((mesh (model-node-mesh node))) (when mesh - (draw-mesh mesh state))) - (render-state-matrix-pop! state)) + (render-state-world-model-matrix-mult! state + (model-node-world-matrix node)) + (draw-mesh mesh state)))) ;;; @@ -211,7 +194,7 @@ (let ((state (model-render-state model))) (render-state-reset! state) (render-state-view-matrix-mult! state view-matrix) - (render-state-matrix-push-and-mult! state model-matrix) + (render-state-model-matrix-mult! state model-matrix) ;; TODO: Support drawing non-default scenes. (draw-model-node (model-default-scene model) state)))) @@ -1010,57 +993,61 @@ (weights (number-array-ref/optional obj "weights"))) ;; TODO: Support weights. (make-mesh name primitives))) - (define (parse-node obj parse-child meshes) + (define (parse-node obj parse-child parent-matrix meshes) ;; TODO: Parse all fields of nodes. - (let ((name (or (string-ref/optional obj "name") "anonymous")) - ;; TODO: Parse camera. - (camera #f) - ;; TODO: Parse skin. - (skin #f) - (matrix (or (matrix-ref/optional obj "matrix") - (let ((rotation (or (array-ref/optional obj "rotation") - #(0.0 0.0 0.0 1.0))) - (scale (or (array-ref/optional obj "scale") - #(1.0 1.0 1.0))) - (translation (or (array-ref/optional obj "translation") - #(0.0 0.0 0.0)))) - (matrix4* (match scale - (#(x y z) - (matrix4-scale (vec3 x y z)))) - (match rotation - (#(x y z w) - ;; Rotation needs to be negated - ;; for some reason. - (matrix4-rotate - (quaternion (- x) (- y) (- z) w)))) - (match translation - (#(x y z) - (matrix4-translate (vec3 x y z)))))))) - (mesh (match (number-ref/optional obj "mesh") - (#f #f) - (n (vector-ref meshes n)))) - ;; TODO: Parse weights. - (weights #f) - (children (map parse-child - (vector->list - (or (array-ref/optional obj "children") - #()))))) + (let* ((name (or (string-ref/optional obj "name") "anonymous")) + ;; TODO: Parse camera. + (camera #f) + ;; TODO: Parse skin. + (skin #f) + (matrix (or (matrix-ref/optional obj "matrix") + (let ((rotation (or (array-ref/optional obj "rotation") + #(0.0 0.0 0.0 1.0))) + (scale (or (array-ref/optional obj "scale") + #(1.0 1.0 1.0))) + (translation (or (array-ref/optional obj "translation") + #(0.0 0.0 0.0)))) + (matrix4* (match scale + (#(x y z) + (matrix4-scale (vec3 x y z)))) + (match rotation + (#(x y z w) + ;; Rotation needs to be negated + ;; for some reason. + (matrix4-rotate + (quaternion (- x) (- y) (- z) w)))) + (match translation + (#(x y z) + (matrix4-translate (vec3 x y z)))))))) + (world-matrix (matrix4* parent-matrix matrix)) + (mesh (match (number-ref/optional obj "mesh") + (#f #f) + (n (vector-ref meshes n)))) + ;; TODO: Parse weights. + (weights #f) + (children (map (lambda (i) + (parse-child i world-matrix)) + (vector->list + (or (array-ref/optional obj "children") + #()))))) (make-model-node #:name name #:children children #:matrix matrix + #:world-matrix world-matrix #:mesh mesh))) (define (parse-nodes array meshes) (define nodes (make-vector (vector-length array) #f)) - (define (parse-node* i) + (define (parse-node* i matrix) (let ((node (vector-ref nodes i))) (or node (let ((node (parse-node (vector-ref array i) parse-node* + matrix meshes))) (vector-set! nodes i node) node)))) (for-range ((i (vector-length array))) - (parse-node* i)) + (parse-node* i (make-identity-matrix4))) nodes) (define (parse-scene obj nodes) (let ((name (or (string-ref/optional obj "name") "anonymous")) -- cgit v1.2.3