1 /** 2 Copyright: Copyright (c) 2015-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module voxelman.world.storage.worldbox; 7 8 import std.experimental.logger; 9 import voxelman.math; 10 11 import voxelman.core.config; 12 import voxelman.world.storage.coordinates; 13 14 import voxelman.graphics; 15 import voxelman.geometry.box; 16 17 void putCube(ref Batch batch, Box box, Color3ub color, bool fill, bool offset = true) 18 { 19 vec3 pos = box.position; 20 vec3 size = box.size; 21 if (offset) { 22 pos -= vec3(0.01, 0.01, 0.01); 23 size += vec3(0.02, 0.02, 0.02); 24 } 25 batch.putCube(pos, size, color, fill); 26 } 27 28 WorldBox calcBox(ChunkWorldPos cwp, int viewRadius) 29 { 30 int size = viewRadius*2 + 1; 31 return WorldBox(cast(ivec3)(cwp.ivector3 - viewRadius), 32 ivec3(size, size, size), cwp.w); 33 } 34 35 WorldBox worldBoxFromCorners(ivec3 a, ivec3 b, ushort dimention) 36 { 37 return WorldBox(boxFromCorners(a, b), dimention); 38 } 39 40 WorldBox blockBoxToChunkBox(WorldBox blockBox) 41 { 42 auto startPosition = blockToChunkPosition(blockBox.position); 43 auto endPosition = blockToChunkPosition(blockBox.endPosition); 44 return worldBoxFromCorners(startPosition, endPosition, blockBox.dimention); 45 } 46 47 // makes block box in chunk-local space out of world space 48 WorldBox blockBoxToChunkLocalBox(WorldBox blockBox) 49 { 50 blockBox.position -= chunkStartBlockPos(blockBox.position); 51 return blockBox; 52 } 53 54 /// Returns chunks if their mesh may have changed after specified modification 55 /// WorldBox is specified in block space 56 WorldBox calcModifiedMeshesBox(WorldBox modificationBox) 57 { 58 // We increase size by 1 in every direction. 59 // After rounding chunks on the border of modification will be included 60 WorldBox expandedBox = modificationBox; 61 expandedBox.position -= ivec3(1,1,1); 62 expandedBox.size += ivec3(2,2,2); 63 WorldBox chunkBox = blockBoxToChunkBox(expandedBox); 64 return chunkBox; 65 } 66 67 WorldBox chunkToBlockBox(ChunkWorldPos cwp) { 68 return chunkToBlockBox(cwp.ivector3, cwp.dimention); 69 } 70 71 WorldBox chunkToBlockBox(ivec3 cwp, ushort dimention) { 72 ivec3 startPosition = chunkToBlockPosition(cwp); 73 return WorldBox(startPosition, CHUNK_SIZE_VECTOR, dimention); 74 } 75 76 Box chunkToBlockBox(ivec3 cwp) { 77 ivec3 startPosition = chunkToBlockPosition(cwp); 78 return Box(startPosition, CHUNK_SIZE_VECTOR); 79 } 80 81 struct WorldBox 82 { 83 Box box; 84 alias box this; 85 ushort dimention; 86 87 this(ivec3 pos, ivec3 size, ushort dim) 88 { 89 box = Box(pos, size); 90 dimention = dim; 91 } 92 93 this(Box box, ushort dim) 94 { 95 this.box = box; 96 dimention = dim; 97 } 98 99 bool contains(ivec3 point, ushort dimention) const 100 { 101 if (this.dimention != dimention) return false; 102 return box.contains(point); 103 } 104 105 import std.algorithm : cartesianProduct, map, joiner, equal, canFind; 106 import std.range : iota, walkLength; 107 import std.array : array; 108 109 // generates all positions within box. 110 auto positions4d() const @property 111 { 112 return cartesianProduct( 113 iota(position.x, position.x + size.x), 114 iota(position.z, position.z + size.z), 115 iota(position.y, position.y + size.y),) 116 .map!((a)=>ivec4(a[0], a[2], a[1], dimention)); 117 } 118 119 bool opEquals()(auto const ref WorldBox other) const 120 { 121 return box == other.box && dimention == other.dimention; 122 } 123 } 124 125 TrisectResult trisect4d(WorldBox a, WorldBox b) 126 { 127 WorldBox intersection = worldBoxIntersection(a, b); 128 129 // no intersection 130 if (intersection.empty) 131 { 132 return TrisectResult([a], Box(), [b]); 133 } 134 135 auto result = trisectIntersecting(a, b); 136 result.intersection = intersection; 137 return result; 138 } 139 140 unittest 141 { 142 assert(WorldBox(Box(), 0) != WorldBox(Box(), 1)); 143 assert(WorldBox(Box(), 0) == WorldBox(Box(), 0)); 144 } 145 146 WorldBox worldBoxIntersection(WorldBox a, WorldBox b) 147 { 148 if (a.dimention != b.dimention) 149 { 150 return WorldBox(); 151 } 152 153 auto box = boxIntersection(a.box, b.box); 154 return WorldBox(box, a.dimention); 155 }