73 lines
3 KiB
Common Lisp
73 lines
3 KiB
Common Lisp
#|
|
|
This file is a part of stoe project.
|
|
Copyright (c) 2015 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
|
|#
|
|
|
|
(uiop:define-package :stoe/engine/model
|
|
(:use :cl :maths
|
|
:stoe/core/utils
|
|
:stoe/core/entity
|
|
:stoe/core/resources
|
|
:stoe/engine/scene-graph
|
|
:stoe/engine/mesh
|
|
:stoe/engine/scene
|
|
:stoe/engine/render)
|
|
(:export #:model-node #:mesh-indexes #:make-model-node
|
|
#:model-resource #:root-node #:meshes #:meshref
|
|
#:mesh-component #:model #:make-mesh-component
|
|
#:create-model))
|
|
(in-package :stoe/engine/model)
|
|
|
|
(defclass model-node (node)
|
|
((name :initarg :name :accessor name)
|
|
(mesh-indexes :initarg :mesh-indexes :accessor mesh-indexes)
|
|
(transform :initarg :transform :reader transform :type float44)))
|
|
|
|
(defun make-model-node (name mesh-indexes &optional parent (transform (mat-id 4 'single-float)))
|
|
(make-instance 'model-node :parent parent :name name :mesh-indexes mesh-indexes :transform transform))
|
|
|
|
(defclass model-resource (shared-resource)
|
|
((root-node :initarg :root-node :accessor root-node :type model-node)
|
|
(meshes :initarg :meshes :accessor meshes))
|
|
(:documentation "Resource class containing the actual model data."))
|
|
|
|
(defmethod root-node ((res resource-proxy))
|
|
(with-slots (resource) res
|
|
(when (tg:weak-pointer-value resource)
|
|
(root-node (tg:weak-pointer-value resource)))))
|
|
|
|
(defmethod meshes ((res resource-proxy))
|
|
(with-slots (resource) res
|
|
(when (tg:weak-pointer-value resource)
|
|
(meshes (tg:weak-pointer-value resource)))))
|
|
|
|
(defun meshref (model-proxy subscript)
|
|
(aref (meshes model-proxy) subscript))
|
|
|
|
(defmethod resource-initialize ((res model-resource))
|
|
(with-slots (meshes) res
|
|
(on-render-thread (meshes)
|
|
(loop for mesh across meshes
|
|
do (mesh-initialize mesh)))))
|
|
|
|
(defcomponent mesh-component (graph-node-component)
|
|
((model :initarg :model :reader model)
|
|
(model-node :initarg :model-node :reader model-node :type model-node))
|
|
(:needs graph-node-component)
|
|
(:documentation "A graph node component that contains a single mesh."))
|
|
|
|
(defun create-model (name path &optional (parent-entity (current-scene)))
|
|
"Create a model from a resource file and attach it to the parent entity or root."
|
|
(ret entity (create-entity name
|
|
(graph-node-component :parent parent-entity))
|
|
(with-resource (path model)
|
|
(with-components ((node graph-node-component)) entity
|
|
(labels ((clone-mesh (node parent)
|
|
(setf parent (make-instance 'mesh-component :owner entity :parent parent
|
|
:transform (transform node) :model model :model-node node))
|
|
(mapc (lambda (child) (clone-mesh child parent)) (children node))))
|
|
(mapc (lambda (child) (clone-mesh child node)) (children (root-node model))))))))
|
|
|
|
(defmethod render ((mesh mesh-component))
|
|
(loop for mesh-idx in (mesh-indexes (model-node mesh))
|
|
do (render-single-mesh (meshref (model mesh) mesh-idx) (transform mesh))))
|