#| 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/gl-utils :stoe/engine/mesh :stoe/engine/scene) (: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) (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 (import-transform (classimp:transform node))))) (rec node root-node) root-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.")))) (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-mesh (remove nil (list (import-stream (classimp:vertices mesh) :position) (import-stream (classimp:colors mesh) :color))) (import-faces (classimp:faces mesh) (import-modes mesh)))) 'vector) :root-node (import-nodes (classimp:root-node ai-scene)))))