1 /**
2 Copyright: Copyright (c) 2016-2017 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module voxelman.geometry.cube;
7 
8 enum CubeSide : ubyte
9 {
10 	zneg = 0,
11 	zpos = 1,
12 
13 	xpos = 2,
14 	xneg = 3,
15 
16 	ypos = 4,
17 	yneg = 5,
18 }
19 
20 enum SideMask : ubyte
21 {
22 	zneg = 0b_00_0001,
23 	zpos = 0b_00_0010,
24 
25 	xpos = 0b_00_0100,
26 	xneg = 0b_00_1000,
27 
28 	ypos = 0b_01_0000,
29 	yneg = 0b_10_0000,
30 }
31 
32 enum CubeCorner : ubyte
33 {
34 	xneg_yneg_zneg,
35 	xpos_yneg_zneg,
36 	xneg_yneg_zpos,
37 	xpos_yneg_zpos,
38 
39 	xneg_ypos_zneg,
40 	xpos_ypos_zneg,
41 	xneg_ypos_zpos,
42 	xpos_ypos_zpos,
43 }
44 
45 // In the same order as CubeSide, sideOffsets26
46 enum Dir27 : ubyte
47 {
48 	// 6 adjacent
49 	zneg, // [ 0, 0,-1]
50 	zpos, // [ 0, 0, 1]
51 	xpos, // [ 1, 0, 0]
52 	xneg, // [-1, 0, 0]
53 	ypos, // [ 0, 1, 0]
54 	yneg, // [ 0,-1, 0]
55 
56 	// bottom 8
57 	xneg_yneg_zneg,	// [-1,-1,-1]
58 	     yneg_zneg, // [ 0,-1,-1]
59 	xpos_yneg_zneg, // [ 1,-1,-1]
60 	xneg_yneg     , // [-1,-1, 0]
61 	xpos_yneg     , // [ 1,-1, 0]
62 	xneg_yneg_zpos, // [-1,-1, 1]
63 	     yneg_zpos, // [ 0,-1, 1]
64 	xpos_yneg_zpos, // [ 1,-1, 1]
65 
66 	// middle 4
67 	xneg_zneg, // [-1, 0,-1]
68 	xpos_zneg, // [ 1, 0,-1]
69 	xneg_zpos, // [-1, 0, 1]
70 	xpos_zpos, // [ 1, 0, 1]
71 
72 	// top 8
73 	xneg_ypos_zneg,	// [-1, 1,-1]
74 	     ypos_zneg,	// [ 0, 1,-1]
75 	xpos_ypos_zneg,	// [ 1, 1,-1]
76 	xneg_ypos     ,	// [-1, 1, 0]
77 	xpos_ypos     ,	// [ 1, 1, 0]
78 	xneg_ypos_zpos,	// [-1, 1, 1]
79 	     ypos_zpos,	// [ 0, 1, 1]
80 	xpos_ypos_zpos,	// [ 1, 1, 1]
81 
82 	central
83 }
84 
85 immutable Dir27[27] dirs3by3 = [
86 	// bottom 9
87 	Dir27.xneg_yneg_zneg, // [-1,-1,-1]
88 	Dir27.yneg_zneg     , // [ 0,-1,-1]
89 	Dir27.xpos_yneg_zneg, // [ 1,-1,-1]
90 
91 	Dir27.xneg_yneg     , // [-1,-1, 0]
92 	Dir27.     yneg     , // [ 0,-1, 0]
93 	Dir27.xpos_yneg     , // [ 1,-1, 0]
94 
95 	Dir27.xneg_yneg_zpos, // [-1,-1, 1]
96 	Dir27.     yneg_zpos, // [ 0,-1, 1]
97 	Dir27.xpos_yneg_zpos, // [ 1,-1, 1]
98 
99 	// middle 9
100 	Dir27.xneg_zneg     , // [-1, 0,-1]
101 	Dir27.          zneg, // [ 0, 0,-1]
102 	Dir27.xpos_zneg     , // [ 1, 0,-1]
103 
104 	Dir27.xneg          , // [-1, 0, 0]
105 	Dir27.   central    , // [ 0, 0, 0]
106 	Dir27.xpos          , // [ 1, 0, 0]
107 
108 	Dir27.xneg_zpos     , // [-1, 0, 1]
109 	Dir27.          zpos, // [ 0, 0, 1]
110 	Dir27.xpos_zpos     , // [ 1, 0, 1]
111 
112 	// top 9
113 	Dir27.xneg_ypos_zneg, // [-1, 1,-1]
114 	Dir27.     ypos_zneg, // [ 0, 1,-1]
115 	Dir27.xpos_ypos_zneg, // [ 1, 1,-1]
116 
117 	Dir27.xneg_ypos     , // [-1, 1, 0]
118 	Dir27.     ypos     , // [ 0, 1, 0]
119 	Dir27.xpos_ypos     , // [ 1, 1, 0]
120 
121 	Dir27.xneg_ypos_zpos, // [-1, 1, 1]
122 	Dir27.     ypos_zpos, // [ 0, 1, 1]
123 	Dir27.xpos_ypos_zpos, // [ 1, 1, 1]
124 ];
125 
126 immutable CubeSide[6] oppSide = [
127 	CubeSide.zpos,
128 	CubeSide.zneg,
129 	CubeSide.xneg,
130 	CubeSide.xpos,
131 	CubeSide.yneg,
132 	CubeSide.ypos];
133 
134 template sideOffsets(size_t numAdjacent) {
135 	static if (numAdjacent == 6)
136 		alias sideOffsets = sideOffsets6;
137 	else static if (numAdjacent == 26)
138 		alias sideOffsets = sideOffsets26;
139 }
140 
141 // does not include center
142 immutable byte[3][26] sideOffsets26 = [
143 	// 6 adjacent
144 	[ 0, 0,-1],
145 	[ 0, 0, 1],
146 	[ 1, 0, 0],
147 	[-1, 0, 0],
148 	[ 0, 1, 0],
149 	[ 0,-1, 0],
150 
151 	// bottom 8
152 	[-1,-1,-1],
153 	[ 0,-1,-1],
154 	[ 1,-1,-1],
155 	[-1,-1, 0],
156 	[ 1,-1, 0],
157 	[-1,-1, 1],
158 	[ 0,-1, 1],
159 	[ 1,-1, 1],
160 
161 	// middle 4
162 	[-1, 0,-1],
163 	[ 1, 0,-1],
164 	[-1, 0, 1],
165 	[ 1, 0, 1],
166 
167 	// top 8
168 	[-1, 1,-1],
169 	[ 0, 1,-1],
170 	[ 1, 1,-1],
171 	[-1, 1, 0],
172 	[ 1, 1, 0],
173 	[-1, 1, 1],
174 	[ 0, 1, 1],
175 	[ 1, 1, 1],
176 ];
177 
178 immutable byte[3][27] offsets3by3 = [
179 	// bottom 9
180 	[-1,-1,-1],
181 	[ 0,-1,-1],
182 	[ 1,-1,-1],
183 
184 	[-1,-1, 0],
185 	[ 0,-1, 0],
186 	[ 1,-1, 0],
187 
188 	[-1,-1, 1],
189 	[ 0,-1, 1],
190 	[ 1,-1, 1],
191 
192 	// middle 9
193 	[-1, 0,-1],
194 	[ 0, 0,-1],
195 	[ 1, 0,-1],
196 
197 	[-1, 0, 0],
198 	[ 0, 0, 0],
199 	[ 1, 0, 0],
200 
201 	[-1, 0, 1],
202 	[ 0, 0, 1],
203 	[ 1, 0, 1],
204 
205 	// top 9
206 	[-1, 1,-1],
207 	[ 0, 1,-1],
208 	[ 1, 1,-1],
209 
210 	[-1, 1, 0],
211 	[ 0, 1, 0],
212 	[ 1, 1, 0],
213 
214 	[-1, 1, 1],
215 	[ 0, 1, 1],
216 	[ 1, 1, 1],
217 ];
218 
219 // does not include center and other 20 adjacent
220 immutable byte[3][6] sideOffsets6 = sideOffsets26[0..6];
221 immutable byte[3][20] sideOffsets20 = sideOffsets26[6..26];
222 
223 // mesh for single block
224 immutable ubyte[18 * 6] cubeFaces =
225 [
226 	1, 0, 0, // triangle 1 : begin // zneg
227 	0, 1, 0,
228 	1, 1, 0, // triangle 1 : end
229 	1, 0, 0, // triangle 2 : begin
230 	0, 0, 0,
231 	0, 1, 0, // triangle 2 : end
232 
233 	0, 0, 1, // zpos
234 	1, 1, 1,
235 	0, 1, 1,
236 	0, 0, 1,
237 	1, 0, 1,
238 	1, 1, 1,
239 
240 	1, 0, 1, // xpos
241 	1, 1, 0,
242 	1, 1, 1,
243 	1, 0, 1,
244 	1, 0, 0,
245 	1, 1, 0,
246 
247 	0, 0, 0, // xneg
248 	0, 1, 1,
249 	0, 1, 0,
250 	0, 0, 0,
251 	0, 0, 1,
252 	0, 1, 1,
253 
254 	0, 1, 1, // ypos
255 	1, 1, 0,
256 	0, 1, 0,
257 	0, 1, 1,
258 	1, 1, 1,
259 	1, 1, 0,
260 
261 	1, 0, 1, // yneg
262 	0, 0, 0,
263 	1, 0, 0,
264 	1, 0, 1,
265 	0, 0, 1,
266 	0, 0, 0,
267 ];
268 
269 immutable ubyte[6] faceCornerIndexes = [1, 3, 0, 1, 2, 3];
270 immutable ubyte[6] flippedFaceCornerIndexes = [1, 2, 0, 0, 2, 3];
271 
272 // the "Y" of 1 and 3 vertex are inversed
273 immutable ubyte[18 * 6] flippedCubeFaces =
274 [
275 	1, 0, 0, // triangle 1 : begin // zneg
276 	0, 0, 0,
277 	1, 1, 0, // triangle 1 : end
278 	1, 1, 0, // triangle 2 : begin
279 	0, 0, 0,
280 	0, 1, 0, // triangle 2 : end
281 
282 	0, 0, 1, // zpos
283 	1, 0, 1,
284 	0, 1, 1,
285 	0, 1, 1,
286 	1, 0, 1,
287 	1, 1, 1,
288 
289 	1, 0, 1, // xpos
290 	1, 0, 0,
291 	1, 1, 1,
292 	1, 1, 1,
293 	1, 0, 0,
294 	1, 1, 0,
295 
296 	0, 0, 0, // xneg
297 	0, 0, 1,
298 	0, 1, 0,
299 	0, 1, 0,
300 	0, 0, 1,
301 	0, 1, 1,
302 
303 	0, 1, 1, // ypos
304 	1, 1, 1,
305 	0, 1, 0,
306 	0, 1, 0,
307 	1, 1, 1,
308 	1, 1, 0,
309 
310 	1, 0, 1, // yneg
311 	0, 0, 1,
312 	1, 0, 0,
313 	1, 0, 0,
314 	0, 0, 1,
315 	0, 0, 0,
316 ];
317 
318 immutable ubyte[3][8] cubeVerticies = [
319 	[0,0,0], // 0
320 	[1,0,0], // 1
321 	[0,0,1], // 2
322 	[1,0,1], // 3
323 	[0,1,0], // 4
324 	[1,1,0], // 5
325 	[0,1,1], // 6
326 	[1,1,1], // 7
327 ];
328 
329 // 6 sides by 4 indices per side
330 immutable ubyte[4][6] cubeSideVertIndices = [
331 	[5,1,0,4], // zneg
332 	[6,2,3,7], // zpos
333 	[7,3,1,5], // xpos
334 	[4,0,2,6], // xneg
335 	[4,6,7,5], // ypos
336 	[1,3,2,0], // yneg
337 ];