gamnit: extract Cuboid as super class to cube and intro Boxed3d::to_mesh
[nit.git] / lib / gamnit / depth / more_meshes.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # More simple geometric meshes
16 module more_meshes
17
18 import geometry
19 import depth_core
20 import model_dimensions
21
22 # Simple flat mesh, sits on the axes X and Z, normal on Y
23 class Plane
24 super Mesh
25
26 # TODO allow for complex rotation, either at creation or in Actor
27
28 # Modifier to `texture_coords` to repeat the texture on the X axis
29 #
30 # At 1.0, the texture is stretched to cover the whole plane.
31 # If greater than 1.0, the texture is repeated.
32 #
33 # This value must be set before using `texture_coords` or drawing this plane.
34 var repeat_x = 1.0 is writable
35
36 # Modifier to `texture_coords` to repeat the texture on the Y axis
37 #
38 # At 1.0, the texture is stretched to cover the whole plane.
39 # If greater than 1.0, the texture is repeated.
40 #
41 # This value must be set before using `texture_coords` or drawing this plane.
42 var repeat_y = 1.0 is writable
43
44 redef var vertices is lazy do
45 var a = [-0.5, 0.0, -0.5]
46 var b = [ 0.5, 0.0, -0.5]
47 var c = [-0.5, 0.0, 0.5]
48 var d = [ 0.5, 0.0, 0.5]
49
50 var vertices = new Array[Float]
51 for v in [c, d, a, b] do vertices.add_all v
52 return vertices
53 end
54
55 redef var normals: Array[Float] is lazy do
56 var normals = new Array[Float]
57 for i in 4.times do normals.add_all([0.0, 1.0, 0.0])
58 return normals
59 end
60
61 redef var texture_coords: Array[Float] is lazy do
62 var offset_left = 0.0
63 var offset_top = 0.0
64 var offset_right = 1.0*repeat_x
65 var offset_bottom = 1.0*repeat_y
66 var a = [offset_left, offset_bottom]
67 var b = [offset_right, offset_bottom]
68 var c = [offset_left, offset_top]
69 var d = [offset_right, offset_top]
70
71 var texture_coords = new Array[Float]
72 for v in [c, d, a, b] do texture_coords.add_all v
73 return texture_coords
74 end
75
76 redef var center = new Point3d[Float](0.0, 0.0, 0.0) is lazy
77
78 init do indices.add_all([0, 1, 2, 2, 1, 3])
79 # TODO use gl_TRIANGLE_FAN instead
80 end
81
82 # Cuboid, or rectangular prism, with 6 faces and right angles
83 #
84 # Can be created from a `Boxed3d` using `to_mesh`.
85 class Cuboid
86 super Mesh
87
88 # Width, on the X axis
89 var width: Float
90
91 # Height, on the Y axis
92 var height: Float
93
94 # Depth, on the Z axis
95 var depth: Float
96
97 redef var vertices is lazy do
98 var a = [-0.5*width, -0.5*height, -0.5*depth]
99 var b = [ 0.5*width, -0.5*height, -0.5*depth]
100 var c = [-0.5*width, 0.5*height, -0.5*depth]
101 var d = [ 0.5*width, 0.5*height, -0.5*depth]
102
103 var e = [-0.5*width, -0.5*height, 0.5*depth]
104 var f = [ 0.5*width, -0.5*height, 0.5*depth]
105 var g = [-0.5*width, 0.5*height, 0.5*depth]
106 var h = [ 0.5*width, 0.5*height, 0.5*depth]
107
108 var vertices = new Array[Float]
109 for v in [a, c, d, a, d, b, # front
110 f, h, g, f, g, e, # back
111 b, d, h, b, h, f, # right
112 e, g, c, e, c, a, # left
113 e, a, b, e, b, f, # bottom
114 c, g, h, c, h, d # top
115 ] do vertices.add_all v
116 return vertices
117 end
118
119 redef var normals is lazy do
120 var normals = new Array[Float]
121 var faces_normals = [
122 [0.0, 0.0, -1.0],
123 [0.0, 0.0, 1.0],
124 [ 1.0, 0.0, 0.0],
125 [-1.0, 0.0, 0.0],
126 [0.0, -1.0, 0.0],
127 [0.0, 1.0, 0.0]]
128 for f in faces_normals do for i in 6.times do normals.add_all f
129 return normals
130 end
131
132 redef var texture_coords: Array[Float] is lazy do
133 var a = [0.0, 1.0]
134 var b = [1.0, 1.0]
135 var c = [0.0, 0.0]
136 var d = [1.0, 0.0]
137
138 var texture_coords = new Array[Float]
139 var face = [a, c, d, a, d, b]
140 for i in 6.times do for v in face do texture_coords.add_all v
141 return texture_coords
142 end
143
144 redef var center = new Point3d[Float](0.0, 0.0, 0.0) is lazy
145 end
146
147 # Cube, with 6 faces, edges of equal length and square angles
148 #
149 # Occupies `[-0.5..0.5]` on all three axes.
150 class Cube
151 super Cuboid
152
153 noautoinit
154
155 init
156 do
157 width = 1.0
158 height = 1.0
159 depth = 1.0
160 end
161 end
162
163 redef class Boxed3d[N]
164 # Create a `Cuboid` mesh with the dimension of `self`
165 #
166 # Does not use the position of `self`, but it can be given to an `Actor`.
167 fun to_mesh: Cuboid
168 do
169 var width = right.to_f-left.to_f
170 var height = top.to_f-bottom.to_f
171 var depth = front.to_f-back.to_f
172 return new Cuboid(width, height, depth)
173 end
174 end
175
176 # Sphere with `radius` and a number of faces set by `n_meridians` and `n_parallels`
177 class UVSphere
178 super Mesh
179
180 # Distance between the center and the vertices
181 var radius: Float
182
183 # Number of vertices on a full circle around the Z axis
184 var n_meridians: Int
185
186 # Number of vertices on an arc between both poles
187 var n_parallels: Int
188
189 init
190 do
191 var w = n_meridians
192 var h = n_parallels
193
194 var vertices = new Array[Float].with_capacity(w*h*3)
195 self.vertices = vertices
196
197 var texture_coords = new Array[Float].with_capacity(w*h*2)
198 self.texture_coords = texture_coords
199
200 var normals = new Array[Float].with_capacity(w*h*3)
201 self.normals = normals
202
203 # Build vertices
204 for m in [0..w[ do
205 for p in [0..h[ do
206 var u = m.to_f * 2.0 * pi / (w-1).to_f
207 var v = p.to_f * pi / (h-1).to_f
208
209 vertices.add radius * u.cos * v.sin
210 vertices.add radius * v.cos
211 vertices.add radius * u.sin * v.sin
212
213 texture_coords.add (1.0 - m.to_f/(w-1).to_f)
214 texture_coords.add(p.to_f/(h-1).to_f)
215
216 normals.add u.cos * v.sin
217 normals.add v.cos
218 normals.add u.sin * v.sin
219 end
220 end
221
222 # Build faces
223 var indices = new Array[Int].with_capacity((w-1)*(h-1)*6)
224 self.indices = indices
225 for m in [0..w-1[ do
226 for p in [0..h-1[ do
227 var a = m*h + p
228
229 indices.add a
230 indices.add a+h
231 indices.add a+1
232
233 indices.add a+h
234 indices.add a+h+1
235 indices.add a+1
236 end
237 end
238 end
239 end