Implementing make-mesh
[mixamesh.git] / mesh.lisp
blob5791e72f780f1dc041244b1d84a723ce591f5100
1 (in-package :mixamesh)
5 ;; -- define a few common types of mesh for luck --------------------------
7 ;; abstract base mesh
9 ;; simple mesh w vertices
10 (def-mesh-type simple-mesh (base-mesh) ((vertex vertices-of vertex3d)))
12 ;; simple mesh with normals for lighting
13 (def-mesh-type mesh (simple-mesh) ((normal normals-of vector3d) (face-normals face-normals-of vector3d)))
15 ;; mesh with textures
16 (def-mesh-type textured-mesh (simple-mesh) ((texcoord uvs-of vector2d)))
18 ;; mesh with vertex colours or other attributes
19 (def-mesh-type coloured-mesh (simple-mesh) ((colour colours-of colour)))
22 ;; -- operations on normals et al --------------------
24 (def-tuple-op calc-face-normal
25 ((vertex-a vertex3d (ax ay az aw))
26 (vertex-b vertex3d (bx by bz bw))
27 (vertex-c vertex3d (cx cy cz cw)))
28 "return the normal of a face"
29 (:return vector3d
30 (vector3d-normal
31 (vector3d-cross
32 (delta-vector3d vertex-a vertex-b)
33 (delta-vector3d vertex-a vertex-c)))))
35 (def-tuple-op vector3d-sum
36 ((vector-a vector3d (ax ay az))
37 (vector-b vector3d (bx by bz)))
38 "return the sum of two vectors"
39 (:return vector3d
40 (vector3d* (+ ax bx) (+ ay by) (+ az bz))))
42 ;; declarations to allow the iterate macro to iterate over the
43 ;; triangles in a mesh or the vertices
44 (defclause-sequence in-triangles index-of-triangle
45 :access-fn 'triangle-aref
46 :size-fn 'triangle-array-dimensions
47 :sequence-type 'vector
48 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
51 (defclause-sequence in-vertices index-of-vertex
52 :access-fn 'vertex3d-aref
53 :size-fn 'vertex3d-array-dimensions
54 :sequence-type 'vector
55 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
57 (defgeneric calc-face-normals (mesh))
59 (defmethod calc-face-normals ((self mesh))
60 "Calculate the face normals of a mesh."
61 (let* ((face-normals (make-vector3d-array (triangle-array-dimensions (faces-of self)))))
62 (iterate
63 (for (values a b c) in-triangles (faces-of self))
64 (for triangle-index upfrom 0)
65 (setf (vector3d-aref face-normals triangle-index)
66 (calc-face-normal
67 (vertex3d-aref (vertices-of self) a)
68 (vertex3d-aref (vertices-of self) b)
69 (vertex3d-aref (vertices-of self) c))))
70 (setf (face-normals-of self) face-normals)))
72 (defgeneric calc-vertex-normals (mesh))
74 (defmethod calc-vertex-normals ((self mesh))
75 "Calculate the vertex normals of a mesh."
76 (let ((vertex-normals (make-vector3d-array (length (vertices-of self)))))
77 (iterate
78 (for index index-of-vertex (vertices-of self))
79 (let ((normal (new-vector3d)))
80 (iterate
81 (for (values a b c) in-triangles (faces-of self))
82 (for face-index upfrom 0)
83 (when (or (= a index) (= b index) (= c index))
84 (setf (vector3d normal)
85 (vector3d-sum (vector3d normal)
86 (vector3d-aref (face-normals-of self) face-index))))
87 (setf (vector3d-aref vertex-normals index) (vector3d normal)))))
88 (setf (normals-of self) vertex-normals)))
91 ;; mesh geometry calculation ---------------------------------------------
93 (defgeneric box-of (mesh))
95 (defmethod box-of ((self mesh))
96 "Return a bounding box for the mesh."
97 (let ((maxx most-negative-single-float)
98 (minx most-positive-single-float)
99 (maxy most-negative-single-float)
100 (miny most-positive-single-float)
101 (maxz most-negative-single-float)
102 (minz most-positive-single-float))
103 (iterate
104 (for index index-of-vertex (vertices-of self))
105 (with-vertex3d
106 (vertex3d-aref (vertices-of self) index)
107 (x y z w)
108 (cond
109 ((< x minx) (setf minx x))
110 ((> x maxx) (setf maxx x))
111 ((< y miny) (setf miny y))
112 ((> y maxy) (setf maxy y))
113 ((< z minz) (setf minz z))
114 ((< z minz) (setf minz z)))))
115 (values minx maxx miny maxy minz maxz)))
117 (defgeneric normalize-scale (mesh))
119 (defmethod normalize-scale ((self mesh))
120 "Rescale geometry to fit into a 1:1:1 bounding box"
121 (multiple-value-bind
122 (minx maxx miny maxy minz maxz)
123 (box-of self)
124 (let ((dx (- maxx minx))
125 (dy (- maxy miny))
126 (dz (- maxz minz))
127 (scale))
128 (cond
129 ((and (> dx dz) (> dx dy))
130 ;; dx is largest dimension
131 (setf scale (/ 1 (- maxx minx))))
132 ;; dy is largest dimension
133 ((and (> dy dz) (> dy dx))
134 (setf scale (/ 1 (- maxy miny))))
135 ;; dz is largest dimension
136 ((and (> dz dy) (> dz dx))
137 (setf scale (/ 1 (- maxy miny)))))
138 (iterate
139 (for index index-of-vertex (vertices-of self))
140 (with-vertex3d
141 (vertex3d-aref (vertices-of self) index)
142 (x y z w)
143 (setf (vertex3d-aref (vertices-of self) index)
144 (vertex3d* (* x scale) (* y scale) (* z scale) w)))))))
147 (defgeneric stripify (mesh))
149 (defmethod stripify ((self mesh))
150 "Stripify mesh")
154 ;; empty base class to specialise on
155 (defclass compiled-mesh ()
159 ;; (defmethod decompilation ((self compiled-mesh))
160 ;; "Create a modifiable mesh from a compiled mesh")
162 (defmethod mesh-compile ((self mesh) &rest args)
163 "Given a mesh return a compiled mesh, which is a non-modifiable mesh optimised for rendering in foreign memory."
164 (declare (ignorable args))