Use entities and components to define objects in the game world and represent the game scene as a graph
101 lines
4.1 KiB
Common Lisp
101 lines
4.1 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/mesh
|
|
(:use :cl :cffi :maths :shader
|
|
:stoe/core/utils
|
|
:stoe/engine/gl-utils)
|
|
(:export #:mesh #:vertex-streams #:faces #:make-mesh
|
|
#:stream-array #:ctype
|
|
#:vertex-stream #:attrib
|
|
#:index-stream #:mode
|
|
#:make-stream-array #:make-vertex-stream #:make-index-stream #:bsize
|
|
#:mesh-initialize
|
|
#:render-mesh))
|
|
(in-package :stoe/engine/mesh)
|
|
|
|
(defclass mesh ()
|
|
((streams :initarg :streams :reader vertex-streams)
|
|
(faces :initarg :faces :reader faces)
|
|
(material :initarg :material :reader material)
|
|
(vertex-buffers :initform nil :accessor vertex-buffers)
|
|
(index-buffer :initform nil :accessor index-buffer))
|
|
(:documentation "Class for a single mesh."))
|
|
|
|
(defun make-mesh (&optional streams faces)
|
|
(make-instance 'mesh :streams streams :faces faces :material nil))
|
|
|
|
(defclass stream-array ()
|
|
((array :initarg :array :reader raw-data)
|
|
(ctype :initarg :ctype :reader ctype)
|
|
(count :initarg :count)))
|
|
|
|
(defclass vertex-stream (stream-array)
|
|
((attrib :initarg :attrib :reader attrib)
|
|
(stride :initarg :stride :reader stride)))
|
|
|
|
(defclass index-stream (stream-array)
|
|
((mode :initarg :mode :reader mode)))
|
|
|
|
(defun make-stream-array (array ctype count stride)
|
|
(make-instance 'stream-array :array array :ctype ctype :count count :stride stride))
|
|
|
|
(defun make-vertex-stream (array ctype count attrib stride)
|
|
(make-instance 'vertex-stream :array array :ctype ctype :count count :attrib attrib :stride stride))
|
|
|
|
(defun make-index-stream (array ctype count mode)
|
|
(make-instance 'index-stream :array array :ctype ctype :count count :mode mode))
|
|
|
|
(defmethod size ((stream stream-array))
|
|
(length (raw-data stream)))
|
|
|
|
(defgeneric bsize (object))
|
|
(defmethod bsize ((stream stream-array))
|
|
(* (ctype-size (ctype stream)) (length (raw-data stream))))
|
|
|
|
(defun mesh-initialize (mesh)
|
|
(let ((vertex-buffers (gl:gen-buffers (length (vertex-streams mesh))))
|
|
(index-buffer (gl:gen-buffer)))
|
|
(loop for stream in (vertex-streams mesh)
|
|
for buffer-object in vertex-buffers
|
|
do (let* ((ctype (ctype stream)) (size (size stream)) (bsize (bsize stream))
|
|
(data (raw-data stream))
|
|
(ptr (foreign-alloc ctype :count size)))
|
|
(dotimes (i (length data))
|
|
(setf (mem-aref ptr ctype i) (aref data i)))
|
|
(gl:bind-buffer :array-buffer buffer-object)
|
|
(%gl:buffer-data :array-buffer bsize ptr :static-draw)
|
|
(foreign-free ptr)))
|
|
(gl:bind-buffer :array-buffer 0)
|
|
(let* ((faces (faces mesh)) (data (raw-data faces))
|
|
(size (size faces)) (bsize (bsize faces))
|
|
(ptr (foreign-alloc (ctype faces) :initial-contents data :count size)))
|
|
(gl:bind-buffer :element-array-buffer index-buffer)
|
|
(%gl:buffer-data :element-array-buffer bsize ptr :static-draw)
|
|
(foreign-free ptr)
|
|
(gl:bind-buffer :element-array-buffer 0))
|
|
(setf (vertex-buffers mesh) vertex-buffers
|
|
(index-buffer mesh) index-buffer)))
|
|
|
|
(defun render-mesh (mesh program)
|
|
(with-accessors ((vertex-buffers vertex-buffers) (streams vertex-streams)
|
|
(index-buffer index-buffer) (faces faces)) mesh
|
|
(loop for i below (length vertex-buffers)
|
|
for vertex in vertex-buffers
|
|
for stream in streams
|
|
with offset = 0
|
|
do (let* ((ctype (ctype stream)) (attrib (attrib stream))
|
|
(bsize (bsize stream)) (stride (stride stream))
|
|
(loc (get-location program attrib)))
|
|
(gl:bind-buffer :array-buffer vertex)
|
|
(gl-assert (gl:enable-vertex-attrib-array loc)
|
|
(gl:vertex-attrib-pointer loc stride ctype
|
|
:false 0 offset))
|
|
(incf offset bsize)))
|
|
(gl:bind-buffer :element-array-buffer index-buffer)
|
|
(gl-assert (%gl:draw-elements (mode faces) (bsize faces)
|
|
(ctype-to-gltype (ctype faces)) 0))
|
|
(gl:bind-buffer :element-array-buffer 0)
|
|
(gl:bind-buffer :array-buffer 0)))
|