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.world.mesh.utils;
7 
8 import voxelman.math;
9 import voxelman.geometry.cube;
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.world.storage.arraycopy;
55 import voxelman.geometry.box;
56 
57 immutable short[6] sideIndexOffsets = [
58 	-EXTENDED_CHUNK_SIZE, // zneg
59 	 EXTENDED_CHUNK_SIZE, // zpos
60 	 1, // xpos
61 	-1, // xneg
62 	 EXTENDED_CHUNK_SIZE_SQR, // ypos
63 	-EXTENDED_CHUNK_SIZE_SQR, // yneg
64 ];
65 private alias sio = sideIndexOffsets;
66 
67 immutable short[27] sideIndexOffsets27 = [
68 	// 6 adjacent
69 	sio[CubeSide.zneg], // zneg
70 	sio[CubeSide.zpos], // zpos
71 	sio[CubeSide.xpos], // xpos
72 	sio[CubeSide.xneg], // xneg
73 	sio[CubeSide.ypos], // ypos
74 	sio[CubeSide.yneg], // yneg
75 
76 	// bottom 8
77 	sio[CubeSide.xneg] + sio[CubeSide.yneg] + sio[CubeSide.zneg], // xneg_yneg_zneg
78 	                     sio[CubeSide.yneg] + sio[CubeSide.zneg], //      yneg_zneg
79 	sio[CubeSide.xpos] + sio[CubeSide.yneg] + sio[CubeSide.zneg], // xpos_yneg_zneg
80 	sio[CubeSide.xneg] + sio[CubeSide.yneg]                     , // xneg_yneg
81 	sio[CubeSide.xpos] + sio[CubeSide.yneg]                     , // xpos_yneg
82 	sio[CubeSide.xneg] + sio[CubeSide.yneg] + sio[CubeSide.zpos], // xneg_yneg_zpos
83 	                     sio[CubeSide.yneg] + sio[CubeSide.zpos], //      yneg_zpos
84 	sio[CubeSide.xpos] + sio[CubeSide.yneg] + sio[CubeSide.zpos], // xpos_yneg_zpos
85 
86 	// middle 4
87 	sio[CubeSide.xneg] + sio[CubeSide.zneg], // xneg_zneg [-1, 0,-1]
88 	sio[CubeSide.xpos] + sio[CubeSide.zneg], // xpos_zneg [ 1, 0,-1]
89 	sio[CubeSide.xneg] + sio[CubeSide.zpos], // xneg_zpos [-1, 0, 1]
90 	sio[CubeSide.xpos] + sio[CubeSide.zpos], // xpos_zpos [ 1, 0, 1]
91 
92 	// top 8
93 	sio[CubeSide.xneg] + sio[CubeSide.ypos] + sio[CubeSide.zneg], // xneg_ypos_zneg [-1, 1,-1]
94 	                     sio[CubeSide.ypos] + sio[CubeSide.zneg], //      ypos_zneg [ 0, 1,-1]
95 	sio[CubeSide.xpos] + sio[CubeSide.ypos] + sio[CubeSide.zneg], // xpos_ypos_zneg [ 1, 1,-1]
96 	sio[CubeSide.xneg] + sio[CubeSide.ypos]                     , // xneg_ypos      [-1, 1, 0]
97 	sio[CubeSide.xpos] + sio[CubeSide.ypos]                     , // xpos_ypos      [ 1, 1, 0]
98 	sio[CubeSide.xneg] + sio[CubeSide.ypos] + sio[CubeSide.zpos], // xneg_ypos_zpos [-1, 1, 1]
99 	                     sio[CubeSide.ypos] + sio[CubeSide.zpos], //      ypos_zpos [ 0, 1, 1]
100 	sio[CubeSide.xpos] + sio[CubeSide.ypos] + sio[CubeSide.zpos], // xpos_ypos_zpos [ 1, 1, 1]
101 
102 	0 // central
103 ];
104 private alias sio27 = sideIndexOffsets27;
105 
106 // on sides top points in ypos dir
107 enum FaceSide : ubyte {
108 	top, // zneg dir on horizontal faces (top and bottom)
109 	left,
110 	bottom,
111 	right
112 }
113 
114 // for each cube side
115 //   8 index offsets
116 //   first four are offsets to 4 adjacent sides, next 4 are for corner
117 // 4 0 7
118 // 1   3
119 // 5 2 6
120 static immutable short[8][6] faceSideIndexOffset = [
121 	/*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
122 	/*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
123 	/*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
124 	/*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
125 
126 	/*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
127 	/*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
128 ];
129 
130 // maps block side to map of 12 corner ids. 3 corners of adjacent cubes for each face corner.
131 // each corner is a corner of cube adjacent to given face (one of 6 sides). Those cube corners will affect AO of face corners.
132 // 1 | 0  11 | 10
133 // --+-------+----
134 // 2 |*     *|  9
135 //   |       |
136 // 3 |*     *|  8
137 // --+-------+----
138 // 4 | 5   6 |  7
139 // those correspond to 4 face corners (marked as * above)
140 // 0--3 // corner numbering of face verticies
141 // |  |
142 // 1--2
143 // where cube corners are from CubeCorner
144 
145 static immutable ubyte[12][6] faceSideCorners = [
146 	[3, 2, 6,  2, 6, 7,  6, 7, 3,  7, 3, 2], // zneg
147 	[0, 1, 5,  1, 5, 4,  5, 4, 0,  4, 0, 1], // zpos
148 	[2, 0, 4,  0, 4, 6,  4, 6, 2,  6, 2, 0], // xpos
149 	[1, 3, 7,  3, 7, 5,  7, 5, 1,  5, 1, 3], // xneg
150 	[2, 3, 1,  3, 1, 0,  1, 0, 2,  0, 2, 3], // ypos
151 	[7, 6, 4,  6, 4, 5,  4, 5, 7,  5, 7, 6], // yneg
152 ];
153 
154 // maps block side to map of 12 corner ids. 3 corners of adjacent cubes for each face corner.
155 // each corner is a corner of cube adjacent to given face (one of 6 sides). Those cube corners will affect AO of face corners.
156 // 2 | 1  15 | 14
157 // --+-------+----
158 // 3 | 0  12 | 13
159 //   |       |
160 // 5 | 4   8 | 11
161 // --+-------+----
162 // 6 | 7   9 | 10
163 // those correspond to 4 face corners (marked as * above)
164 // 0--3 // corner numbering of face verticies
165 // |  |
166 // 1--2
167 // where cube corners are from CubeCorner
168 
169 static immutable ubyte[16][6] faceSideCorners4 = [
170 	[7,3,2,6, 3,2,6,7, 2,6,7,3, 6,7,3,2], // zneg
171 	[4,0,1,5, 0,1,5,4, 1,5,4,0, 5,4,0,1], // zpos
172 	[6,2,0,4, 2,0,4,6, 0,4,6,2, 1,6,2,0], // xpos
173 	[5,1,3,7, 1,3,7,5, 3,7,5,1, 7,5,1,3], // xneg
174 	[0,2,3,1, 2,3,1,0, 3,1,0,2, 1,0,2,3], // ypos
175 	[5,7,6,4, 7,6,4,5, 6,4,5,7, 4,5,7,6], // yneg
176 ];