stoe/engine/import.lisp
Renaud Casenave-Péré 8838362c26 Implement an entity-component system and a scene graph
Use entities and components to define objects in the game world
and represent the game scene as a graph
2016-04-04 22:46:46 +02:00

99 lines
4.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/import
(:use :cl :maths
:stoe/core/utils
:stoe/core/jobs
:stoe/core/resources
:stoe/engine/gl-utils
:stoe/engine/mesh
:stoe/engine/scene
:stoe/engine/model)
(:export #:import-graphic-assets))
(in-package :stoe/engine/import)
(defun import-stream (stream attrib)
(let* ((len (array-total-size stream)))
(when (> len 0)
(let* ((count len)
(stride (array-total-size (aref stream 0)))
(elt-type (array-element-type (aref stream 0)))
(ctype (ltype-to-ctype elt-type (* count stride)))
(array (make-array (list (* count stride)) :element-type elt-type)))
(loop for i below count
do (let ((row (aref stream i)))
(loop for j below stride
do (setf (aref array (+ j (* i stride))) (aref row j)))))
(make-vertex-stream array ctype count attrib stride)))))
(defun import-faces (faces mode)
(let* ((count (array-total-size faces))
(stride (array-total-size (aref faces 0)))
(elt-type (array-element-type (aref faces 0)))
(ctype (ltype-to-ctype elt-type (* count stride)))
(array (make-array (list (* count stride)) :element-type 'fixnum)))
(loop for i below count
do (let ((row (aref faces i)))
(loop for j below stride
do (setf (aref array (+ j (* i stride))) (aref row j)))))
(make-index-stream array ctype count mode)))
(defun import-transform (trans)
(let ((mat (mat-null 4 'single-float)))
(loop for i below (first (dimensions mat))
do (loop for j below (second (dimensions mat))
do (setf (mref mat i j) (aref trans (+ j (* i (second (dimensions mat))))))))
mat))
(defun import-nodes (node)
(let ((len (length (classimp:children node)))
model-node)
(loop for i below len
for child = (aref (classimp:children node) i)
do (let ((child-node (import-nodes child)))
(when child-node
(unless model-node
(setf model-node
(make-model-node
(classimp:name node) (coerce (classimp:meshes node) 'list)
nil (import-transform (classimp:transform node)))))
(attach-node child-node model-node))))
(when (and (null model-node) (> (length (classimp:meshes node)) 0))
(setf model-node (make-model-node
(classimp:name node) (coerce (classimp:meshes node) 'list)
nil (import-transform (classimp:transform node)))))
model-node))
(defun import-modes (mesh)
(when (classimp:mesh-has-multiple-primitive-types mesh)
(error "Multiple primitive types are not yet supported"))
(cond
((classimp:mesh-has-points mesh) :points)
((classimp:mesh-has-lines mesh) :lines)
((classimp:mesh-has-triangles mesh) :triangles)
((classimp:mesh-has-polygons mesh) (error "Polygons mode is not supported."))))
(eval-when (:compile-toplevel :load-toplevel :execute)
(defun import-graphic-assets (path)
(async-job (path)
(classimp:import-into-lisp path))))
(defrestype "dae" model-resource
((:load (path (ai-scene (import-graphic-assets path)) res)
(with-slots (root-node meshes) res
(setf meshes
(coerce (loop for i below (array-total-size (classimp:meshes ai-scene))
for mesh = (aref (classimp:meshes ai-scene) i)
collect (make-mesh
(remove nil
(list (import-stream (classimp:vertices mesh)
:position)
(when (> (length (classimp:colors mesh)) 0)
(import-stream (aref (classimp:colors mesh) 0)
:color))))
(import-faces (classimp:faces mesh) (import-modes mesh))))
'vector)
root-node (import-nodes (classimp:root-node ai-scene)))))))