Updated for new cl-tuples
[mixamesh.git] / mesh.lisp
blob8cd797468c6b127be4e17768cd76ed3cca308308
1 (in-package :mixamesh)
3 ;; -- define a few common types of mesh for luck --------------------------
5 ;; abstract base mesh
7 ;; simple mesh w vertices
8 (def-mesh-type simple-mesh (base-mesh) ((vertex vertices-of vertex3d)))
10 ;; simple mesh with normals for lighting
11 (def-mesh-type mesh (simple-mesh) ((normal normals-of vector3d) (face-normals face-normals-of vector3d)))
13 ;; mesh with textures
14 (def-mesh-type textured-mesh (simple-mesh) ((texcoord uvs-of vector2d)))
16 ;; mesh with vertex colours or other attributes
17 (def-mesh-type coloured-mesh (simple-mesh) ((colour colours-of colour)))
20 ;; -- operations on normals et al --------------------
22 (def-tuple-op calc-face-normal*
23 ((vertex-a vertex3d (ax ay az aw))
24 (vertex-b vertex3d (bx by bz bw))
25 (vertex-c vertex3d (cx cy cz cw)))
26 "return the normal of a face"
27 (:return vector3d
28 (vector3d-normal*
29 (vector3d-cross*
30 (delta-vector3d* vertex-a vertex-b)
31 (delta-vector3d* vertex-a vertex-c)))))
33 (def-tuple-op vector3d-sum*
34 ((vector-a vector3d (ax ay az))
35 (vector-b vector3d (bx by bz)))
36 "return the sum of two vectors"
37 (:return vector3d
38 (vector3d-values* (+ ax bx) (+ ay by) (+ az bz))))
40 ;; declarations to allow the iterate macro to iterate over the
41 ;; triangles in a mesh or the vertices
42 (defclause-sequence in-triangles* index-of-triangle
43 :access-fn 'triangle-aref*
44 :size-fn 'triangle-array-dimensions
45 :sequence-type 'vector
46 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
49 (defclause-sequence in-vertices* index-of-vertex
50 :access-fn 'vertex3d-aref*
51 :size-fn 'vertex3d-array-dimensions
52 :sequence-type 'vector
53 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
55 (defgeneric calc-face-normals (mesh))
57 (defmethod calc-face-normals ((self mesh))
58 "Calculate the face normals of a mesh."
59 (let* ((face-normals (make-vector3d-array (triangle-array-dimensions (faces-of self)))))
60 (iterate
61 (for (values a b c) in-triangles* (faces-of self))
62 (for triangle-index upfrom 0)
63 (setf (vector3d-aref* face-normals triangle-index)
64 (calc-face-normal*
65 (vertex3d-aref* (vertices-of self) a)
66 (vertex3d-aref* (vertices-of self) b)
67 (vertex3d-aref* (vertices-of self) c))))
68 (setf (face-normals-of self) face-normals)))
70 (defgeneric calc-vertex-normals (mesh))
72 (defmethod calc-vertex-normals ((self mesh))
73 "Calculate the vertex normals of a mesh."
74 (let ((vertex-normals (make-vector3d-array (length (vertices-of self)))))
75 (iterate
76 (for index index-of-vertex (vertices-of self))
77 (let ((normal (new-vector3d)))
78 (iterate
79 (for (values a b c) in-triangles* (faces-of self))
80 (for face-index upfrom 0)
81 (when (or (= a index) (= b index) (= c index))
82 (setf (vector3d* normal)
83 (vector3d-sum* (vector3d* normal)
84 (vector3d-aref* (face-normals-of self) face-index))))
85 (setf (vector3d-aref vertex-normals index) normal))))
86 (setf (normals-of self) vertex-normals)))
89 ;; mesh geometry calculation ---------------------------------------------
91 (defgeneric box-of (mesh))
93 (defmethod box-of ((self simple-mesh))
94 "Return a bounding box for the mesh."
95 (let ((maxx most-negative-single-float)
96 (minx most-positive-single-float)
97 (maxy most-negative-single-float)
98 (miny most-positive-single-float)
99 (maxz most-negative-single-float)
100 (minz most-positive-single-float))
101 (iterate
102 (for (values x y z nil) in-vertices* (vertices-of self))
103 (cond
104 ((< x minx) (setf minx x))
105 ((> x maxx) (setf maxx x))
106 ((< y miny) (setf miny y))
107 ((> y maxy) (setf maxy y))
108 ((< z minz) (setf minz z))
109 ((> z maxz) (setf maxz z))))
110 (make-aabb minx maxx miny maxy minz maxz)))
112 (defun bound-mesh (mesh)
113 (setf (gethash mesh *bounding-boxes*) (box-of (gethash mesh *meshes*))))
115 ;; squeeze into unit bounds (for brushes?) ---------------------------------
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-values* (* x scale) (* y scale) (* z scale) w)))))))
147 ;; to do -- this hierarchy should mirror the def-mesh hierarchy and
148 ;; be automatically expanded out by def-mesh
150 ;; compiled mesh -- methods defined elsehwhere
151 (defclass compiled-mesh ()
152 ((vertex-buffer :initform 0 :type (unsigned-byte 32) :reader vertex-buffer-of)
153 (triangle-buffer :initform 0 :type (unsigned-byte 32) :reader triangle-buffer-of)
154 (element-count :initform 0 :type fixnum :reader element-count-of)))
156 (defclass textured-compiled-mesh ()
157 ((vertex-buffer :initform 0 :type (unsigned-byte 32) :reader vertex-buffer-of)
158 (uv-buffer :initform 0 :type (unsigned-byte 32) :reader uv-buffer-of)
159 (texture :accessor texture-of :initform nil)
160 (element-count :initform 0 :type fixnum :reader element-count-of)))