Add a way to import graphic assets from various sources

This commit is contained in:
Renaud Casenave-Péré 2015-08-20 14:25:22 +02:00
parent 4e974ad8a2
commit ab0698bef1
4 changed files with 121 additions and 30 deletions

View file

@ -8,9 +8,8 @@
(:use-reexport
:stoe/engine/gl-utils
:stoe/engine/scene
:stoe/engine/object
:stoe/engine/mesh
:stoe/engine/camera
#+stoe-foreign-assets
:stoe/engine/import
:stoe/engine/render
:stoe/engine/shaders
:stoe/engine/shader/all))

66
engine/import.lisp Normal file
View file

@ -0,0 +1,66 @@
#|
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/engine/scene)
(:export #:import-graphic-assets))
(in-package :stoe/engine/import)
(defun import-stream (stream)
(let ((len (array-total-size stream)))
(when (> len 0)
(let* ((dim-x len)
(dim-y (array-total-size (aref stream 0)))
(array (make-array (list (* dim-x dim-y)) :element-type 'single-float)))
(loop for i below dim-x
do (let ((row (aref stream i)))
(loop for j below dim-y
do (setf (aref array (+ j (* i dim-y))) (aref row j)))))
(make-stream-array array dim-x dim-y)))))
(defun import-faces (faces)
(let* ((dim-x (array-total-size faces))
(dim-y (array-total-size (aref faces 0)))
(array (make-array (list (* dim-x dim-y)) :element-type 'fixnum)))
(loop for i below dim-x
do (let ((row (aref faces i)))
(loop for j below dim-y
do (setf (aref array (+ j (* i dim-y))) (aref row j)))))
array))
(defun import-transform (trans)
(let ((mat (mat-null 4 'single-float)))
(loop for i below (first (dimension mat))
do (loop for j below (second (dimension mat))
do (setf (mref mat i j) (aref trans (+ j (* i (second (dimension mat))))))))
mat))
(defun import-nodes (node)
(labels ((rec (node parent)
(let ((len (array-total-size (classimp:children node))))
(loop for i below len
for child = (aref (classimp:children node) i)
do (let ((scene-node (make-scene-node (classimp:name child) parent
(import-transform (classimp:transform child))
(coerce (classimp:meshes child) 'list))))
(rec child scene-node))))))
(when node
(let ((root-node (make-scene-node (classimp:name node) nil (classimp:transform node))))
(rec node root-node)
root-node))))
(defun import-graphic-assets (filename)
(let ((ai-scene (classimp:import-into-lisp filename)))
(make-instance 'scene
:meshes
(coerce (loop for i below (array-total-size (classimp:meshes ai-scene))
for mesh = (aref (classimp:meshes ai-scene) i)
collect (make-instance 'mesh
:vertices (import-stream (classimp:vertices mesh))
:colors (import-stream (classimp:colors mesh))
:faces (import-faces (classimp:faces mesh))))
'vector)
:root-node (import-nodes (classimp:root-node ai-scene)))))

View file

@ -4,39 +4,63 @@
|#
(uiop:define-package :stoe/engine/scene
(:export #:scene-node #:parent #:children
#:attach #:detach
#:walk-graph))
(:use :cl)
(:export #:scene-node #:make-scene-node #:attach-child
#:scene #:make-scene
#:mesh #:make-mesh
#:stream-array
#:make-stream-array))
(in-package :stoe/engine/scene)
(defclass scene-node ()
((parent :initform nil :reader parent)
(children :initform nil :reader children))
((name :initarg :name)
(parent :initform nil)
(transform :initarg :transform)
(children :initarg :children)
(meshes :initarg :meshes))
(:documentation "Base class for a node in the scene graph."))
(defgeneric attach (scene-node parent)
(:documentation "Attach a new node to the scene graph to be rendered."))
(defun make-scene-node (name &optional parent transform meshes)
(let ((node (make-instance 'scene-node :name name :transform transform :meshes meshes)))
(when parent
(attach-child node parent))
node))
(defmethod attach ((scene-node scene-node) (parent scene-node))
(with-slots (children) parent
(with-slots ((new-parent parent)) scene-node
(push scene-node children)
(setf new-parent parent))))
(defun attach-child (node parent)
(with-slots (node-parent) node
(when parent
(with-slots (children) parent
(setf children (append children (list node)))
(setf node-parent parent))))
node)
(defgeneric detach (scene-node)
(:documentation "Detach a node from the scene graph to prevent it and its
children from being rendered."))
(defun detach-child (node)
(with-slots (node-parent) node
(when node-parent
(with-slots (children) node-parent
(delete node children)))))
(defmethod detach ((scene-node scene-node))
(with-slots (parent) scene-node
(with-slots (children) parent
(setf children (remove scene-node children))
(setf parent nil))))
(defclass scene ()
((root-node :initarg :root-node)
(meshes :initarg :meshes))
(:documentation "Class for the current scene."))
(defun walk-scene (fun node)
"Walk through the scene graph and apply `fun' at each node."
(with-slots (children) node
(loop for child in children
do (progn
(apply fun child)
(walk-scene fun child)))))
(defun make-scene ()
(make-instance 'scene))
(defclass mesh ()
((vertices :initarg :vertices)
(colors :initarg :colors)
(faces :initarg :faces))
(:documentation "Class for a single mesh."))
(defun make-mesh (name)
(make-instance 'mesh :name name))
(defclass stream-array ()
((array :initarg :array)
(count :initarg :count)
(stride :initarg :stride)))
(defun make-stream-array (array count stride)
(make-instance 'stream-array :array array :count count :stride stride))

View file

@ -42,6 +42,8 @@
"blackbird"
"cl-opengl"
"glop"
#+stoe-foreign-assets
"classimp"
"stoe/maths/all"
"stoe/core/all"
"stoe/engine/all"