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