Merge branch 'master' of git+ssh://johnfredcee@repo.or.cz/srv/git/mixamesh
[mixamesh.git] / mesh.lisp
blob97732279f3ce6a184443395aa87899661386d6a0
1 (in-package :mixamesh)
4 ;; -- keep track of every mesh instance ----------------------------------
6 (defparameter *meshes* (make-hash-table :test 'equalp)
7 "A table of meshes.")
9 (unless (find-package :mesh-names)
10 (make-package :mesh-names))
12 ;; -- define a few common types of mesh for luck --------------------------
14 ;; abstract base mesh
16 ;; simple mesh w vertices
17 (def-mesh-type simple-mesh (base-mesh) ((vertex vertices-of vertex3d)))
19 ;; simple mesh with normals for lighting
20 (def-mesh-type mesh (simple-mesh) ((normal normals-of vector3d) (face-normals face-normals-of vector3d)))
22 ;; mesh with textures
23 (def-mesh-type textured-mesh (simple-mesh) ((texcoord uvs-of vector2d)))
25 ;; mesh with vertex colours or other attributes
26 (def-mesh-type coloured-mesh (simple-mesh) ((colour colours-of colour)))
29 ;; -- operations on normals et al --------------------
31 (def-tuple-op calc-face-normal
32 ((vertex-a vertex3d (ax ay az aw))
33 (vertex-b vertex3d (bx by bz bw))
34 (vertex-c vertex3d (cx cy cz cw)))
35 "return the normal of a face"
36 (:return vector3d
37 (vector3d-normal
38 (vector3d-cross
39 (delta-vector3d vertex-a vertex-b)
40 (delta-vector3d vertex-a vertex-c)))))
42 (def-tuple-op vector3d-sum
43 ((vector-a vector3d (ax ay az))
44 (vector-b vector3d (bx by bz)))
45 "return the sum of two vectors"
46 (:return vector3d
47 (vector3d* (+ ax bx) (+ ay by) (+ az bz))))
49 ;; declarations to allow the iterate macro to iterate over the
50 ;; triangles in a mesh or the vertices
51 (defclause-sequence in-triangles index-of-triangle
52 :access-fn 'triangle-aref
53 :size-fn 'triangle-array-dimensions
54 :sequence-type 'vector
55 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
58 (defclause-sequence in-vertices index-of-vertex
59 :access-fn 'vertex3d-aref
60 :size-fn 'vertex3d-array-dimensions
61 :sequence-type 'vector
62 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
64 (defgeneric calc-face-normals (mesh))
66 (defmethod calc-face-normals ((self mesh))
67 "Calculate the face normals of a mesh."
68 (let* ((face-normals (make-vector3d-array (triangle-array-dimensions (faces-of self)))))
69 (iterate
70 (for (values a b c) in-triangles (faces-of self))
71 (for triangle-index upfrom 0)
72 (setf (vector3d-aref face-normals triangle-index)
73 (calc-face-normal
74 (vertex3d-aref (vertices-of self) a)
75 (vertex3d-aref (vertices-of self) b)
76 (vertex3d-aref (vertices-of self) c))))
77 (setf (face-normals-of self) face-normals)))
79 (defgeneric calc-vertex-normals (mesh))
81 (defmethod calc-vertex-normals ((self mesh))
82 "Calculate the vertex normals of a mesh."
83 (let ((vertex-normals (make-vector3d-array (length (vertices-of self)))))
84 (iterate
85 (for index index-of-vertex (vertices-of self))
86 (let ((normal (new-vector3d)))
87 (iterate
88 (for (values a b c) in-triangles (faces-of self))
89 (for face-index upfrom 0)
90 (when (or (= a index) (= b index) (= c index))
91 (setf (vector3d normal)
92 (vector3d-sum (vector3d normal)
93 (vector3d-aref (face-normals-of self) face-index))))
94 (setf (vector3d-aref vertex-normals index) (vector3d normal)))))
95 (setf (normals-of self) vertex-normals)))
98 ;; mesh geometry calculation ---------------------------------------------
100 (defgeneric box-of (mesh))
102 (defmethod box-of ((self mesh))
103 "Return a bounding box for the mesh."
104 (let ((maxx most-negative-single-float)
105 (minx most-positive-single-float)
106 (maxy most-negative-single-float)
107 (miny most-positive-single-float)
108 (maxz most-negative-single-float)
109 (minz most-positive-single-float))
110 (iterate
111 (for index index-of-vertex (vertices-of self))
112 (with-vertex3d
113 (vertex3d-aref (vertices-of self) index)
114 (x y z w)
115 (cond
116 ((< x minx) (setf minx x))
117 ((> x maxx) (setf maxx x))
118 ((< y miny) (setf miny y))
119 ((> y maxy) (setf maxy y))
120 ((< z minz) (setf minz z))
121 ((< z minz) (setf minz z)))))
122 (values minx maxx miny maxy minz maxz)))
124 (defgeneric normalize-scale (mesh))
126 (defmethod normalize-scale ((self mesh))
127 "Rescale geometry to fit into a 1:1:1 bounding box"
128 (multiple-value-bind
129 (minx maxx miny maxy minz maxz)
130 (box-of self)
131 (let ((dx (- maxx minx))
132 (dy (- maxy miny))
133 (dz (- maxz minz))
134 (scale))
135 (cond
136 ((and (> dx dz) (> dx dy))
137 ;; dx is largest dimension
138 (setf scale (/ 1 (- maxx minx))))
139 ;; dy is largest dimension
140 ((and (> dy dz) (> dy dx))
141 (setf scale (/ 1 (- maxy miny))))
142 ;; dz is largest dimension
143 ((and (> dz dy) (> dz dx))
144 (setf scale (/ 1 (- maxy miny)))))
145 (iterate
146 (for index index-of-vertex (vertices-of self))
147 (with-vertex3d
148 (vertex3d-aref (vertices-of self) index)
149 (x y z w)
150 (setf (vertex3d-aref (vertices-of self) index)
151 (vertex3d* (* x scale) (* y scale) (* z scale) w)))))))
154 (defgeneric stripify (mesh))
156 (defmethod stripify ((self mesh))
157 "Stripify mesh")
161 ;; empty base class to specialise on
162 (defclass compiled-mesh ()
166 ;; (defmethod decompilation ((self compiled-mesh))
167 ;; "Create a modifiable mesh from a compiled mesh")
169 (defmethod mesh-compile ((self mesh) &rest args)
170 "Given a mesh return a compiled mesh, which is a non-modifiable mesh optimised for rendering in foreign memory."
171 (declare (ignorable args))