diff options
author | David Thompson <dthompson2@worcester.edu> | 2021-05-05 20:20:11 -0400 |
---|---|---|
committer | David Thompson <dthompson2@worcester.edu> | 2021-05-05 20:20:11 -0400 |
commit | 1a36cd13c97e2648f8f8bcfb261d9ead13f55976 (patch) | |
tree | 65bf232b4dea722c71611d412f0d38552df567bb | |
parent | 1fdb28d1f1b8743a05d8f5bf377d65c9c0d3ce64 (diff) |
graphics: model: Add support for scene node transforms in glTF models.
-rw-r--r-- | chickadee/graphics/model.scm | 81 |
1 files changed, 61 insertions, 20 deletions
diff --git a/chickadee/graphics/model.scm b/chickadee/graphics/model.scm index 7abd352..b0150af 100644 --- a/chickadee/graphics/model.scm +++ b/chickadee/graphics/model.scm @@ -26,6 +26,7 @@ #:use-module (chickadee base64) #:use-module (chickadee json) #:use-module (chickadee math matrix) + #:use-module (chickadee math quaternion) #:use-module (chickadee math vector) #:use-module (chickadee graphics buffer) #:use-module (chickadee graphics color) @@ -61,29 +62,55 @@ ;;; (define-record-type <render-state> - (%make-render-state renderer world-matrix view-matrix) + (%make-render-state renderer view-matrix + matrix-stack matrix-pool) render-state? (renderer render-state-renderer) - (world-matrix render-state-world-matrix) - (view-matrix render-state-view-matrix)) + (view-matrix render-state-view-matrix) + (matrix-stack render-state-matrix-stack) + (matrix-pool render-state-matrix-pool)) (define (make-render-state renderer) (%make-render-state renderer (make-identity-matrix4) - (make-identity-matrix4))) + (make-array-list) + (array-list (make-identity-matrix4)))) -(define (render-state-reset! state) - (matrix4-identity! (render-state-world-matrix state)) - (matrix4-identity! (render-state-view-matrix state))) +(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)))) -(define (render-state-world-matrix-mult! state matrix) - (let ((world (render-state-world-matrix state))) - (matrix4-mult! world world matrix))) +(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)))) (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-matrix-pop! state) + (array-list-push! (render-state-matrix-pool state) + (array-list-pop! (render-state-matrix-stack state)))) + ;;; ;;; Primitive @@ -100,13 +127,13 @@ (define (draw-primitive/phong primitive state) (shader-apply/phong (primitive-vertex-array primitive) (primitive-material primitive) - (render-state-world-matrix state) + (render-state-matrix-current state) (render-state-view-matrix state))) (define (draw-primitive/pbr primitive state) (shader-apply/pbr (primitive-vertex-array primitive) (primitive-material primitive) - (render-state-world-matrix state) + (render-state-matrix-current state) (render-state-view-matrix state))) @@ -148,13 +175,14 @@ (%make-scene-node name mesh matrix children)) (define (draw-scene-node node state) - ;; TODO: Apply push/pop model matrix stuff. + (render-state-matrix-push-and-mult! state (scene-node-matrix node)) (for-each (lambda (child) (draw-scene-node child state)) (scene-node-children node)) (let ((mesh (scene-node-mesh node))) (when mesh - (draw-mesh mesh state)))) + (draw-mesh mesh state))) + (render-state-matrix-pop! state)) ;;; @@ -181,7 +209,7 @@ (let ((state (model-render-state model))) (render-state-reset! state) (render-state-view-matrix-mult! state view-matrix) - (render-state-world-matrix-mult! state model-matrix) + (render-state-matrix-push-and-mult! state model-matrix) ;; TODO: Support drawing non-default scenes. (draw-scene-node (model-default-scene model) state)))) @@ -977,14 +1005,27 @@ ;; TODO: Parse skin. (skin #f) (matrix (or (matrix-ref/optional obj "matrix") - (make-identity-matrix4))) + (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 rotation, scale, translation - (rotation #f) - (scale #f) - (translation #f) ;; TODO: Parse weights. (weights #f) (children (map parse-child |