summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2021-05-05 20:20:11 -0400
committerDavid Thompson <dthompson2@worcester.edu>2021-05-05 20:20:11 -0400
commit1a36cd13c97e2648f8f8bcfb261d9ead13f55976 (patch)
tree65bf232b4dea722c71611d412f0d38552df567bb
parent1fdb28d1f1b8743a05d8f5bf377d65c9c0d3ce64 (diff)
graphics: model: Add support for scene node transforms in glTF models.
-rw-r--r--chickadee/graphics/model.scm81
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