summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2021-05-10 07:07:10 -0400
committerDavid Thompson <dthompson2@worcester.edu>2021-05-10 07:07:10 -0400
commitfe0bfc56cde0ee8fed2e45aaa5a3f11a102e476b (patch)
tree84ec674ee3af6d8ef58dd5782a28b51247f95d13
parentae4c14ce01aeacea1db35d269832a20fc3925b91 (diff)
graphics: model: Pre-compute world matrices for model nodes.
-rw-r--r--chickadee/graphics/model.scm139
1 files 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 <render-state>
- (%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 <model-node>
- (%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"))