Ready for performance testing
[lambdamundo.git] / mesh-compiler.lisp
blob55e4a8bbffd496787c30055ddf292895d707a1ac
4 (in-package :mixamesh)
6 ;; this is an extension to mixamesh, but as it involves using ogl extensions, we have to compile
7 ;; when OGL is active in order to successfuly aquire extension function vectors and avoid massive
8 ;; warnings and even crashes with some video drivers (ATI, *cough*, *cough*...)
10 ;; as this uses extensions it has to be compiled and loaded with an active gl context
11 (defgeneric compile-mesh (mesh &rest args))
13 (defmethod compile-mesh ((mesh base-mesh) &rest args)
14 (declare (ignorable args))
15 ;; this has only faces!
16 (format t "Stub called ~%")
17 (values))
19 ;; being able to map across tuple arrays would make this a lot easier.
21 (defmethod compile-mesh ((self simple-mesh) &rest args)
22 "Given a mesh return a compiled mesh, which is a non-modifiable mesh optimised for rendering in foreign memory."
23 (declare (ignorable args))
24 (format t "Compiling simple mesh ~%")
25 (flet ((make-buffer ()
26 "Create a buffer-name for an OpenGL vertex buffer object"
27 (let ((buffer-name (make-array 1 :element-type '(unsigned-byte 32))))
28 (gl:gen-buffers-arb 1 buffer-name)
29 (aref buffer-name 0))))
30 (let ((result (make-instance 'compiled-mesh))
31 (triangle-data (cffi::foreign-alloc :uint32 :count (* 3 (triangle-array-dimensions (faces-of self)))))
32 (vertex-data (cffi:foreign-alloc :float :count (* 3 (vertex3d-array-dimensions (vertices-of self)))))
33 (vertex-buffer (make-buffer))
34 (triangle-buffer (make-buffer)))
35 (flet ((copy-triangle-buffer ()
36 "Copy mesh triangle data into vertex buffer"
37 (iterate
38 (with face-index = 0)
39 (for (values a b c) in-triangles (faces-of self))
40 (setf (cffi:mem-aref triangle-data :uint32 face-index) a)
41 (incf face-index)
42 (setf (cffi:mem-aref triangle-data :uint32 face-index) b)
43 (incf face-index)
44 (setf (cffi:mem-aref triangle-data :uint32 face-index) c)
45 (incf face-index))
46 (gl:bind-buffer-arb gl:+element-array-buffer-arb+ triangle-buffer)
47 (gl:buffer-data-arb gl:+element-array-buffer-arb+
48 (* 3 (triangle-array-dimensions (faces-of self)) (cffi:foreign-type-size :uint32))
49 triangle-data
50 gl:+static-draw-arb+))
51 (copy-vertex-buffer ()
52 "Copy mesh vertex data into vertex buffer"
53 (iterate
54 (with vertex-index = 0)
55 (for (values x y z w) in-vertices (vertices-of self))
56 (setf (cffi:mem-aref vertex-data :float vertex-index) x)
57 (incf vertex-index)
58 (setf (cffi:mem-aref vertex-data :float vertex-index) y)
59 (incf vertex-index)
60 (setf (cffi:mem-aref vertex-data :float vertex-index) z)
61 (incf vertex-index))
62 (gl:bind-buffer-arb gl:+array-buffer-arb+ vertex-buffer)
63 (gl:buffer-data-arb gl:+array-buffer-arb+
64 (* 3 (vertex3d-array-dimensions (vertices-of self)) (cffi:foreign-type-size :float))
65 vertex-data
66 gl:+static-draw-arb+)))
67 (copy-vertex-buffer)
68 (setf (slot-value result 'vertex-buffer) vertex-buffer)
69 (copy-triangle-buffer)
70 (setf (slot-value result 'triangle-buffer) triangle-buffer)
71 (setf (slot-value result 'element-count) (* 3 (triangle-array-dimensions (faces-of self))))
72 (cffi:foreign-free vertex-data)
73 (cffi:foreign-free triangle-data))
74 result)))
76 (defun make-texture-from-skin (skin)
77 (let* ((texture (gethash skin *textures*))
78 (result (make-instance 'glrepl:rgba-image :width (width-of texture) :height (height-of texture))))
79 (format *debug-io* "Map size ~A~%" (colour-array-dimensions (map-of texture)))
80 (format *debug-io* "texture size ~A~%" (* (width-of texture) (height-of texture)))
81 (iterate
82 (for index from 0 below (* (width-of texture) (height-of texture)))
83 (cl-tuples:with-colour-aref
84 ((map-of texture)
85 index
86 (r g b a))
87 (setf (glrepl:pixel result index)
88 (glrepl:pixval (coerce (floor (* 255 r)) '(unsigned-byte 8))
89 (coerce (floor (* 255 g)) '(unsigned-byte 8))
90 (coerce (floor (* 255 b)) '(unsigned-byte 8))
91 255))))
92 (glrepl:update-image result)
93 result))
96 (defmethod compile-mesh ((self lodematron:md2-mesh) &rest args)
97 (destructuring-bind
98 (&key skin)
99 args
100 (format t "Compiling md2 mesh with ~D tris and ~D uv tris ~%" (length (faces-of self)) (length (lodematron:uvs-tris-of self)))
101 (flet ((make-buffer ()
102 "Create a buffer-name for an OpenGL vertex buffer object"
103 (let ((buffer-name (make-array 1 :element-type '(unsigned-byte 32))))
104 (gl:gen-buffers-arb 1 buffer-name)
105 (aref buffer-name 0))))
106 (let* ((result (make-instance 'mixamesh:textured-compiled-mesh))
107 (uv-data (cffi::foreign-alloc :float :count (* 2 3 (triangle-array-dimensions (lodematron:uvs-tris-of self)))))
108 (vertex-data (cffi:foreign-alloc :float :count (* 3 3 (triangle-array-dimensions (faces-of self)))))
109 (vertex-buffer (make-buffer))
110 (uv-buffer (make-buffer)))
112 (flet ((copy-uv-buffer ()
113 "Copy uv triangle data into vertex buffer"
114 (iterate
115 (with uv-index = 0)
116 (for (values a b c) in-triangles (lodematron:uvs-tris-of self))
118 (with-vector2d-aref
119 ((uvs-of self)
121 (u v))
123 (setf (cffi:mem-aref uv-data :float uv-index) u)
124 (incf uv-index)
125 (setf (cffi:mem-aref uv-data :float uv-index) v)
126 (incf uv-index))
128 (with-vector2d-aref
129 ((uvs-of self)
131 (u v))
133 (setf (cffi:mem-aref uv-data :float uv-index) u)
134 (incf uv-index)
135 (setf (cffi:mem-aref uv-data :float uv-index) v)
136 (incf uv-index))
138 (with-vector2d-aref
139 ((uvs-of self)
141 (u v))
143 (setf (cffi:mem-aref uv-data :float uv-index) u)
144 (incf uv-index)
145 (setf (cffi:mem-aref uv-data :float uv-index) v)
146 (incf uv-index)))
148 (gl:bind-buffer-arb gl:+array-buffer-arb+ uv-buffer)
149 (gl:buffer-data-arb gl:+array-buffer-arb+
150 (* 2 3 (triangle-array-dimensions (lodematron:uvs-tris-of self)) (cffi:foreign-type-size :float))
151 uv-data
152 gl:+static-draw-arb+))
154 (copy-vertex-buffer ()
155 "Copy mesh vertex data into vertex buffer"
156 (iterate
157 (with vertex-index = 0)
158 (for (values a b c) in-triangles (faces-of self))
160 (with-vertex3d-aref
161 ((vertices-of self)
163 (x y z w))
166 (setf (cffi:mem-aref vertex-data :float vertex-index) x)
167 (incf vertex-index)
168 (setf (cffi:mem-aref vertex-data :float vertex-index) y)
169 (incf vertex-index)
170 (setf (cffi:mem-aref vertex-data :float vertex-index) z)
171 (incf vertex-index))
173 (with-vertex3d-aref
174 ((vertices-of self)
176 (x y z w))
178 (setf (cffi:mem-aref vertex-data :float vertex-index) x)
179 (incf vertex-index)
180 (setf (cffi:mem-aref vertex-data :float vertex-index) y)
181 (incf vertex-index)
182 (setf (cffi:mem-aref vertex-data :float vertex-index) z)
183 (incf vertex-index))
185 (with-vertex3d-aref
186 ((vertices-of self)
188 (x y z w))
190 (setf (cffi:mem-aref vertex-data :float vertex-index) x)
191 (incf vertex-index)
192 (setf (cffi:mem-aref vertex-data :float vertex-index) y)
193 (incf vertex-index)
194 (setf (cffi:mem-aref vertex-data :float vertex-index) z)
195 (incf vertex-index)))
197 (gl:bind-buffer-arb gl:+array-buffer-arb+ vertex-buffer)
198 (gl:buffer-data-arb gl:+array-buffer-arb+
199 (* 3 3 (triangle-array-dimensions (faces-of self)) (cffi:foreign-type-size :float))
200 vertex-data
201 gl:+static-draw-arb+)))
202 (copy-vertex-buffer)
203 (setf (slot-value result 'vertex-buffer) vertex-buffer)
204 (copy-uv-buffer)
205 (setf (slot-value result 'uv-buffer) uv-buffer)
206 (setf (slot-value result 'element-count) (* 3 (triangle-array-dimensions (faces-of self))))
207 (cffi:foreign-free vertex-data)
208 (cffi:foreign-free uv-data)
209 (setf (texture-of result) (make-texture-from-skin skin)))
210 result))))
213 (defun make-compiled-mesh (mesh &key skin)
214 (setf (gethash mesh *compiled-meshes*) (compile-mesh (gethash mesh *meshes*) :skin skin)))
217 (in-package :lambdamundo)
219 ;;(declaim (optimize (compilation-speed 0) (debug 0) (safety 0) (space 0) (speed 3)))
221 (defmethod render ((self compiled-mesh))
223 (gl:enable-client-state gl:+vertex-array+)
224 (gl:enable-client-state gl:+index-array+)
225 (gl:bind-buffer-arb gl:+array-buffer-arb+ (vertex-buffer-of self))
226 (gl:bind-buffer-arb gl:+element-array-buffer-arb+ (triangle-buffer-of self))
227 (gl:vertex-pointer 3 gl:+float+ 0 (cffi::null-pointer))
228 (gl:draw-elements gl:+triangles+ (element-count-of self) gl:+unsigned-int+ (cffi:null-pointer))
229 (gl:disable-client-state gl:+vertex-array+)
230 (gl:disable-client-state gl:+index-array+))
232 (defmethod render ((self textured-compiled-mesh))
233 ;; (format *debug-io* "Redering ..~%")
234 (gl:disable gl:+blend+)
235 (bind (mixamesh:texture-of self) gl:+replace+)
236 (gl:color-3f 1.0 1.0 1.0)
237 (gl:enable-client-state gl:+vertex-array+)
238 (gl:enable-client-state gl:+texture-coord-array+)
239 (gl:bind-buffer-arb gl:+array-buffer-arb+ (vertex-buffer-of self))
240 (gl:bind-buffer-arb gl:+array-buffer-arb+ (uv-buffer-of self))
241 (gl:vertex-pointer 3 gl:+float+ 0 (cffi::null-pointer))
242 (gl:tex-coord-pointer 2 gl:+float+ 0 (cffi:null-pointer))
243 (gl:draw-arrays gl:+triangles+ 0 (element-count-of self))
244 (gl:disable-client-state gl:+texture-coord-array+)
245 (gl:disable-client-state gl:+vertex-array+)
246 (gl:disable gl:+blend+))
248 ;; (format *debug-io* "Redering ..~%")
249 ;; (glrepl::with-opengl
250 ;; (gl:disable gl:+blend+)
251 ;; (gl:enable gl:+texture-2d+)
252 ;; (gl:bind-texture gl:+texture-2d+ (cffi::mem-ref (name-of (mixamesh:texture-of self)) :uint32))
253 ;; (gl:tex-env-f gl:+texture-env+ gl:+texture-env-mode+ gl:+decal+)
254 ;; (gl:color-3f 1.0 1.0 1.0)
255 ;; (gl:enable-client-state gl:+vertex-array+)
257 ;; (gl:bind-buffer-arb gl:+array-buffer-arb+ (vertex-buffer-of self))
258 ;; (gl:bind-buffer-arb gl:+array-buffer-arb+ (uv-buffer-of self))
259 ;; (gl:vertex-pointer 3 gl:+float+ 0 (cffi::null-pointer))
261 ;; (gl:draw-arrays gl:+triangles+ (element-count-of self) 0)
262 ;; (gl:disable-client-state gl:+vertex-array+)
263 ;; (gl:disable-client-state gl:+texture-coord-array+)
264 ;; (gl:enable gl:+blend+))
265 ;; ))
267 (defmethod destroy ((self compiled-mesh))
268 (flet ((delete-buffer (buf)
269 (let ((buf-array (make-array 1)))
270 (setf (aref buf-array 0) buf)
271 (gl:delete-buffers-arb 1 buf-array))))
272 (when (vertex-buffer-of self)
273 (delete-buffer (vertex-buffer-of self))
274 (setf (slot-value 'vertex-buffer self) nil))
275 (setf (slot-value 'vertex-buffer self) nil)
276 (when (triangle-buffer-of self)
277 (delete-buffer (triangle-buffer-of self))
278 (setf (slot-value 'triangle-buffer self) nil))))
281 (defmethod destroy ((self textured-compiled-mesh))
282 (flet ((delete-buffer (buf)
283 (let ((buf-array (make-array 1)))
284 (setf (aref buf-array 0) buf)
285 (gl:delete-buffers-arb 1 buf-array))))
286 (when (texture-of self)
287 (destroy-image (texture-of self))
288 (setf (texture-of self) nil))
289 (when (vertex-buffer-of self)
290 (delete-buffer (vertex-buffer-of self))
291 (setf (slot-value 'vertex-buffer self) nil))))
293 ;; (delete-buffer (uv-buffer-of self)
294 ;; )))