Migrated mesh type to cl-tuples.
[mixamesh.git] / mesh.lisp
bloba2b86870cc8cc3d34bfa8284d300aebcb6d17aaa
2 (in-package :mixamesh)
4 (defparameter *meshes* (make-hash-table :test 'equalp)
5 "A table of loaded meshes to use as brushes.")
7 (unless (find-package :mesh-names)
8 (make-package :mesh-names))
11 (def-mesh-type wire-mesh base-mesh (colours colours-of colour))
12 (def-mesh-type textured-mesh mesh (texcoord uvs-of vector2d))
13 (def-mesh-type coloured-mesh mesh (colour colours-of colour))
16 ;; mesh - building protocol
17 (defgeneric mesh-builder (mesh op data))
19 ;; constructor
20 (defmethod initialize-instance :after ((self base-mesh) &rest args)
21 (declare (ignore args))
22 ;; treat the object as a function
23 (closer-mop:set-funcallable-instance-function
24 self
25 #'(lambda (op data) (mesh-builder self op data))))
29 (def-tuple-op calc-face-normal
30 ((vertex-a vertex3d (ax ay az aw))
31 (vertex-b vertex3d (bx by bz bw))
32 (vertex-c vertex3d (cx cy cz cw)))
33 "return the normal of a face"
34 (:return vector3d
35 (vector3d-normal
36 (vector3d-cross
37 (delta-vector3d vertex-a vertex-b)
38 (delta-vector3d vertex-a vertex-c)))))
40 (def-tuple-op vector3d-sum
41 ((vector-a vector3d (ax ay az))
42 (vector-b vector3d (bx by bz)))
43 "return the sum of two vectors"
44 (:return vector3d
45 (vector3d-tuple (+ ax bx) (+ ay by) (+ az bz))))
47 ;; declarations to allow the iterate macro to iterate over the
48 ;; triangles in a mesh or the vertices
49 (defclause-sequence in-triangles index-of-triangle
50 :access-fn 'triangle-aref
51 :size-fn 'triangle-array-dimensions
52 :sequence-type 'vector
53 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
56 (defclause-sequence in-vertices index-of-vertex
57 :access-fn 'vertex3d-aref
58 :size-fn 'vertex3d-array-dimensions
59 :sequence-type 'vector
60 :element-type '(values (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16) (unsigned-byte 16)))
63 (defmethod calc-face-normals ((self mesh))
64 "Calculate the face normals of a mesh."
65 (let* ((face-normals (make-vector3d-array (triangle-array-dimensions (faces-of self)))))
66 (iterate
67 (for (values a b c) in-triangles (faces-of self))
68 (for triangle-index upfrom 0)
69 (setf (vector3d-aref face-normals triangle-index)
70 (calc-face-normal
71 (vertex3d-aref (vertices-of self) a)
72 (vertex3d-aref (vertices-of self) b)
73 (vertex3d-aref (vertices-of self) c))))
74 (setf (face-normals-of self) face-normals)))
76 (defmethod calc-vertex-normals ((self mesh))
77 "Calculate the vertex normals of a mesh."
78 (let ((vertex-normals (make-vector3d-array (length (vertices-of self)))))
79 (iterate
80 (for index index-of-vertex (vertices-of self))
81 (let ((normal (new-vector3d)))
82 (iterate
83 (for (values a b c) in-triangles (faces-of self))
84 (for face-index upfrom 0)
85 (when (or (= a index) (= b index) (= c index))
86 (setf (vector3d normal)
87 (vector3d-sum (vector3d normal)
88 (vector3d-aref (face-normals-of self) face-index))))
89 (setf (vector3d-aref vertex-normals index) (vertex3d normal)))))
90 (setf (normals-of self) vertex-normals)))
93 ;; mesh geometry calculation ---------------------------------------------
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 (defmethod normalize-scale ((self mesh))
118 "Rescale geometry to fit into a 1:1:1 bounding box"
119 (multiple-value-bind
120 (minx maxx miny maxy minz maxz)
121 (box-of self)
122 (let ((dx (- maxx minx))
123 (dy (- maxy miny))
124 (dz (- maxz minz))
125 (scale))
126 (cond
127 ((and (> dx dz) (> dx dy))
128 ;; dx is largest dimension
129 (setf scale (/ 1 (- maxx minx))))
130 ;; dy is largest dimension
131 ((and (> dy dz) (> dy dx))
132 (setf scale (/ 1 (- maxy miny))))
133 ;; dz is largest dimension
134 ((and (> dz dy) (> dz dx))
135 (setf scale (/ 1 (- maxy miny)))))
136 (iterate
137 (for index index-of-vertex (vertices-of self))
138 (with-vertex3d
139 (vertex3d-aref (vertices-of self) index)
140 (x y z w)
141 (setf (vertex3d-aref (vertices-of self) index) (vertex3d-tuple (* x scale) (* y scale) (* z scale) w)))))))
144 (defmethod stripify ((self mesh))
145 "Stripify mesh")
147 ;; (defmethod decompilation ((self compiled-mesh))
148 ;; "Create a modifiable mesh from a compiled mesh")
150 ;; (defmethod compilation ((self mesh))
151 ;; "Given a mesh return a compiled mesh, which is a non-modifiable mesh optimised for rendering in foreign memory."
152 ;; )