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.world.mesh.utils;
7 
8 import voxelman.math;
9 import voxelman.geometry;
10 import voxelman.core.config;
11 import voxelman.world.block;
12 
13 enum EXTENDED_CHUNK_SIZE = CHUNK_SIZE + 2;
14 enum EXTENDED_CHUNK_SIZE_SQR = EXTENDED_CHUNK_SIZE * EXTENDED_CHUNK_SIZE;
15 enum EXTENDED_CHUNK_SIZE_CUBE = EXTENDED_CHUNK_SIZE * EXTENDED_CHUNK_SIZE * EXTENDED_CHUNK_SIZE;
16 enum EXTENDED_SIZE_VECTOR = ivec3(EXTENDED_CHUNK_SIZE, EXTENDED_CHUNK_SIZE, EXTENDED_CHUNK_SIZE);
17 
18 size_t extendedChunkIndex(int x, int y, int z) {
19 	return x + y * EXTENDED_CHUNK_SIZE_SQR + z * EXTENDED_CHUNK_SIZE;
20 }
21 
22 size_t chunkFromExtIndex(size_t index)
23 {
24 	int x = index % EXTENDED_CHUNK_SIZE;
25 	int y = (index / EXTENDED_CHUNK_SIZE_SQR) % EXTENDED_CHUNK_SIZE;
26 	int z = (index / EXTENDED_CHUNK_SIZE) % EXTENDED_CHUNK_SIZE;
27 
28 	ubyte cx = target_chunk[x];
29 	ubyte cy = target_chunk[y];
30 	ubyte cz = target_chunk[z];
31 
32 	return dirs3by3[cx + cz * 3 + cy * 9];
33 }
34 
35 ChunkAndBlockAt chunkAndBlockAt27FromExt(ushort index)
36 {
37 	int x = index % EXTENDED_CHUNK_SIZE;
38 	int y = (index / EXTENDED_CHUNK_SIZE_SQR) % EXTENDED_CHUNK_SIZE;
39 	int z = (index / EXTENDED_CHUNK_SIZE) % EXTENDED_CHUNK_SIZE;
40 
41 	ubyte bx = position_in_target_chunk[x];
42 	ubyte by = position_in_target_chunk[y];
43 	ubyte bz = position_in_target_chunk[z];
44 
45 	ubyte cx = target_chunk[x];
46 	ubyte cy = target_chunk[y];
47 	ubyte cz = target_chunk[z];
48 
49 	ubyte chunk_index = dirs3by3[cx + cz * 3 + cy * 9];
50 
51 	return ChunkAndBlockAt(chunk_index, bx, by, bz);
52 }
53 
54 import voxelman.algorithm.arraycopy3d;
55 
56 immutable short[6] sideIndexOffsets = [
57 	-EXTENDED_CHUNK_SIZE, // zneg
58 	 EXTENDED_CHUNK_SIZE, // zpos
59 	 1, // xpos
60 	-1, // xneg
61 	 EXTENDED_CHUNK_SIZE_SQR, // ypos
62 	-EXTENDED_CHUNK_SIZE_SQR, // yneg
63 ];
64 private alias sio = sideIndexOffsets;
65 
66 immutable short[27] sideIndexOffsets27 = [
67 	// 6 adjacent
68 	sio[CubeSide.zneg], // zneg
69 	sio[CubeSide.zpos], // zpos
70 	sio[CubeSide.xpos], // xpos
71 	sio[CubeSide.xneg], // xneg
72 	sio[CubeSide.ypos], // ypos
73 	sio[CubeSide.yneg], // yneg
74 
75 	// bottom 8
76 	sio[CubeSide.xneg] + sio[CubeSide.yneg] + sio[CubeSide.zneg], // xneg_yneg_zneg
77 	                     sio[CubeSide.yneg] + sio[CubeSide.zneg], //      yneg_zneg
78 	sio[CubeSide.xpos] + sio[CubeSide.yneg] + sio[CubeSide.zneg], // xpos_yneg_zneg
79 	sio[CubeSide.xneg] + sio[CubeSide.yneg]                     , // xneg_yneg
80 	sio[CubeSide.xpos] + sio[CubeSide.yneg]                     , // xpos_yneg
81 	sio[CubeSide.xneg] + sio[CubeSide.yneg] + sio[CubeSide.zpos], // xneg_yneg_zpos
82 	                     sio[CubeSide.yneg] + sio[CubeSide.zpos], //      yneg_zpos
83 	sio[CubeSide.xpos] + sio[CubeSide.yneg] + sio[CubeSide.zpos], // xpos_yneg_zpos
84 
85 	// middle 4
86 	sio[CubeSide.xneg] + sio[CubeSide.zneg], // xneg_zneg [-1, 0,-1]
87 	sio[CubeSide.xpos] + sio[CubeSide.zneg], // xpos_zneg [ 1, 0,-1]
88 	sio[CubeSide.xneg] + sio[CubeSide.zpos], // xneg_zpos [-1, 0, 1]
89 	sio[CubeSide.xpos] + sio[CubeSide.zpos], // xpos_zpos [ 1, 0, 1]
90 
91 	// top 8
92 	sio[CubeSide.xneg] + sio[CubeSide.ypos] + sio[CubeSide.zneg], // xneg_ypos_zneg [-1, 1,-1]
93 	                     sio[CubeSide.ypos] + sio[CubeSide.zneg], //      ypos_zneg [ 0, 1,-1]
94 	sio[CubeSide.xpos] + sio[CubeSide.ypos] + sio[CubeSide.zneg], // xpos_ypos_zneg [ 1, 1,-1]
95 	sio[CubeSide.xneg] + sio[CubeSide.ypos]                     , // xneg_ypos      [-1, 1, 0]
96 	sio[CubeSide.xpos] + sio[CubeSide.ypos]                     , // xpos_ypos      [ 1, 1, 0]
97 	sio[CubeSide.xneg] + sio[CubeSide.ypos] + sio[CubeSide.zpos], // xneg_ypos_zpos [-1, 1, 1]
98 	                     sio[CubeSide.ypos] + sio[CubeSide.zpos], //      ypos_zpos [ 0, 1, 1]
99 	sio[CubeSide.xpos] + sio[CubeSide.ypos] + sio[CubeSide.zpos], // xpos_ypos_zpos [ 1, 1, 1]
100 
101 	0 // central
102 ];
103 private alias sio27 = sideIndexOffsets27;
104 
105 // on sides top points in ypos dir
106 enum FaceSide : ubyte {
107 	top, // zneg dir on horizontal faces (top and bottom)
108 	left,
109 	bottom,
110 	right
111 }
112 
113 FaceSide[4] oppFaceSides = [
114 	FaceSide.bottom,
115 	FaceSide.right,
116 	FaceSide.top,
117 	FaceSide.left,
118 ];
119 
120 // for each cube side
121 //   8 index offsets
122 //   first four are offsets to 4 adjacent sides, next 4 are for corner
123 // 4 0 7
124 // 1   3
125 // 5 2 6
126 static immutable short[8][6] faceSideIndexOffset = [
127 	/*0-3*/ [sio27[Dir27.ypos], sio27[Dir27.xpos], sio27[Dir27.yneg], sio27[Dir27.xneg], /*4-7*/ sio27[Dir27.xpos_ypos], sio27[Dir27.xpos_yneg], sio27[Dir27.xneg_yneg], sio27[Dir27.xneg_ypos]], // zneg
128 	/*0-3*/ [sio27[Dir27.ypos], sio27[Dir27.xneg], sio27[Dir27.yneg], sio27[Dir27.xpos], /*4-7*/ sio27[Dir27.xneg_ypos], sio27[Dir27.xneg_yneg], sio27[Dir27.xpos_yneg], sio27[Dir27.xpos_ypos]], // zpos
129 	/*0-3*/ [sio27[Dir27.ypos], sio27[Dir27.zpos], sio27[Dir27.yneg], sio27[Dir27.zneg], /*4-7*/ sio27[Dir27.ypos_zpos], sio27[Dir27.yneg_zpos], sio27[Dir27.yneg_zneg], sio27[Dir27.ypos_zneg]], // xpos
130 	/*0-3*/ [sio27[Dir27.ypos], sio27[Dir27.zneg], sio27[Dir27.yneg], sio27[Dir27.zpos], /*4-7*/ sio27[Dir27.ypos_zneg], sio27[Dir27.yneg_zneg], sio27[Dir27.yneg_zpos], sio27[Dir27.ypos_zpos]], // xneg
131 
132 	/*0-3*/ [sio27[Dir27.zneg], sio27[Dir27.xneg], sio27[Dir27.zpos], sio27[Dir27.xpos], /*4-7*/ sio27[Dir27.xneg_zneg], sio27[Dir27.xneg_zpos], sio27[Dir27.xpos_zpos], sio27[Dir27.xpos_zneg]], // ypos
133 	/*0-3*/ [sio27[Dir27.zneg], sio27[Dir27.xpos], sio27[Dir27.zpos], sio27[Dir27.xneg], /*4-7*/ sio27[Dir27.xpos_zneg], sio27[Dir27.xpos_zpos], sio27[Dir27.xneg_zpos], sio27[Dir27.xneg_zneg]], // yneg
134 ];
135 
136 // maps block side to map of 12 corner ids. 3 corners of adjacent cubes for each face corner.
137 // each corner is a corner of cube adjacent to given face (one of 6 sides). Those cube corners will affect AO of face corners.
138 // 1 | 0  11 | 10
139 // --+-------+----
140 // 2 |*     *|  9
141 //   |       |
142 // 3 |*     *|  8
143 // --+-------+----
144 // 4 | 5   6 |  7
145 // those correspond to 4 face corners (marked as * above)
146 // 0--3 // corner numbering of face verticies
147 // |  |
148 // 1--2
149 // where cube corners are from CubeCorner
150 
151 static immutable ubyte[12][6] faceSideCorners = [
152 	[3, 2, 6,  2, 6, 7,  6, 7, 3,  7, 3, 2], // zneg
153 	[0, 1, 5,  1, 5, 4,  5, 4, 0,  4, 0, 1], // zpos
154 	[2, 0, 4,  0, 4, 6,  4, 6, 2,  6, 2, 0], // xpos
155 	[1, 3, 7,  3, 7, 5,  7, 5, 1,  5, 1, 3], // xneg
156 	[2, 3, 1,  3, 1, 0,  1, 0, 2,  0, 2, 3], // ypos
157 	[7, 6, 4,  6, 4, 5,  4, 5, 7,  5, 7, 6], // yneg
158 ];
159 
160 // maps block side to map of 12 corner ids. 3 corners of adjacent cubes for each face corner.
161 // each corner is a corner of cube adjacent to given face (one of 6 sides). Those cube corners will affect AO of face corners.
162 // 2 | 1  15 | 14
163 // --+-------+----
164 // 3 | 0  12 | 13
165 //   |       |
166 // 5 | 4   8 | 11
167 // --+-------+----
168 // 6 | 7   9 | 10
169 // those correspond to 4 face corners (marked as * above)
170 // 0--3 // corner numbering of face verticies
171 // |  |
172 // 1--2
173 // where cube corners are from CubeCorner
174 
175 static immutable ubyte[16][6] faceSideCorners4 = [
176 	[7,3,2,6, 3,2,6,7, 2,6,7,3, 6,7,3,2], // zneg
177 	[4,0,1,5, 0,1,5,4, 1,5,4,0, 5,4,0,1], // zpos
178 	[6,2,0,4, 2,0,4,6, 0,4,6,2, 1,6,2,0], // xpos
179 	[5,1,3,7, 1,3,7,5, 3,7,5,1, 7,5,1,3], // xneg
180 	[0,2,3,1, 2,3,1,0, 3,1,0,2, 1,0,2,3], // ypos
181 	[5,7,6,4, 7,6,4,5, 6,4,5,7, 4,5,7,6], // yneg
182 ];