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 ];