mirror of https://github.com/buggins/dlangui.git
miner example improvements
This commit is contained in:
parent
83072c5254
commit
c8a9d34534
|
@ -5,6 +5,8 @@ import dminer.core.blocks;
|
|||
import dminer.core.world;
|
||||
import dlangui.graphics.scene.mesh;
|
||||
|
||||
|
||||
|
||||
// Y range: 0..CHUNK_DY-1
|
||||
immutable int CHUNK_DY = 128;
|
||||
|
||||
|
@ -25,6 +27,10 @@ interface CellVisitor {
|
|||
void visit(World world, ref Position camPosition, Vector3d pos, cell_t cell, int visibleFaces);
|
||||
}
|
||||
|
||||
interface ChunkVisitor {
|
||||
void visit(World world, SmallChunk * chunk);
|
||||
}
|
||||
|
||||
// vertical stack of chunks with same X, Z, and different Y
|
||||
struct ChunkStack {
|
||||
protected int _minChunkY;
|
||||
|
@ -135,15 +141,15 @@ struct ChunkStack {
|
|||
struct SmallChunk {
|
||||
protected cell_t[8*8*8] cells; // 512 bytes
|
||||
protected ubyte[8*8*8] sunlight; // 512 bytes
|
||||
protected ulong[8] opaquePlanesX; // 64 bytes
|
||||
protected ulong[8] opaquePlanesY; // 64 bytes
|
||||
protected ulong[8] opaquePlanesZ; // 64 bytes
|
||||
protected ulong[8] visiblePlanesX; // 64 bytes
|
||||
protected ulong[8] visiblePlanesY; // 64 bytes
|
||||
protected ulong[8] visiblePlanesZ; // 64 bytes
|
||||
protected ulong[8] canPassPlanesX; // 64 bytes
|
||||
protected ulong[8] canPassPlanesY; // 64 bytes
|
||||
protected ulong[8] canPassPlanesZ; // 64 bytes
|
||||
protected ulong[8] opaquePlanesX; // 64 bytes WEST to EAST
|
||||
protected ulong[8] opaquePlanesY; // 64 bytes DOWN to UP
|
||||
protected ulong[8] opaquePlanesZ; // 64 bytes NORTH to SOUTH
|
||||
protected ulong[8] visiblePlanesX; // 64 bytes WEST to EAST
|
||||
protected ulong[8] visiblePlanesY; // 64 bytes DOWN to UP
|
||||
protected ulong[8] visiblePlanesZ; // 64 bytes NORTH to SOUTH
|
||||
protected ulong[8] canPassPlanesX; // 64 bytes WEST to EAST
|
||||
protected ulong[8] canPassPlanesY; // 64 bytes DOWN to UP
|
||||
protected ulong[8] canPassPlanesZ; // 64 bytes NORTH to SOUTH
|
||||
//ulong[6][6] canPassFromTo; // 288 bytes
|
||||
SmallChunk * [6] nearChunks;
|
||||
protected Vector3d _pos;
|
||||
|
@ -389,6 +395,40 @@ struct SmallChunk {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
/*
|
||||
X planes (WEST EAST): z, y
|
||||
z=0 z=1 z=2 z=3 z=4 z=5 z=6 z=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
|
||||
Y planes (DOWN UP): x, z
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
z=0 0 1 2 3 4 5 6 7
|
||||
z=1 8 9 10 11 12 13 14 15
|
||||
z=2 16 17 18 19 29 21 22 23
|
||||
z=3 24 25 26 27 28 29 30 31
|
||||
z=4 32 33 34 35 36 37 38 39
|
||||
z=5 40 41 42 43 44 45 46 47
|
||||
z=6 48 49 50 51 52 53 54 55
|
||||
z=7 56 57 58 59 60 61 62 63
|
||||
|
||||
Z planes (NORTH SOUTH): x, y
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
*/
|
||||
private void generateMasks() {
|
||||
// x planes: z,y
|
||||
for(int x = 0; x < 8; x++) {
|
||||
|
@ -707,3 +747,334 @@ void testDirMaskToSpreadMask() {
|
|||
Log.d("Source: \n", generateDirMaskSource());
|
||||
}
|
||||
|
||||
|
||||
/// mask for available spread direction for chunk dest visited from camera chunk position origin
|
||||
ubyte calcSpreadMask(Vector3d dest, Vector3d origin) {
|
||||
ubyte res = 0;
|
||||
if (dest.x < origin.x) {
|
||||
res |= DirMask.MASK_WEST;
|
||||
} else if (dest.x > origin.x) {
|
||||
res |= DirMask.MASK_EAST;
|
||||
} else {
|
||||
res |= DirMask.MASK_WEST | DirMask.MASK_EAST;
|
||||
}
|
||||
if (dest.y < origin.y) {
|
||||
res |= DirMask.MASK_DOWN;
|
||||
} else if (dest.y > origin.y) {
|
||||
res |= DirMask.MASK_UP;
|
||||
} else {
|
||||
res |= DirMask.MASK_DOWN | DirMask.MASK_UP;
|
||||
}
|
||||
if (dest.z < origin.z) {
|
||||
res |= DirMask.MASK_NORTH;
|
||||
} else if (dest.z > origin.z) {
|
||||
res |= DirMask.MASK_SOUTH;
|
||||
} else {
|
||||
res |= DirMask.MASK_NORTH | DirMask.MASK_SOUTH;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Z planes (NORTH SOUTH): x, y
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
*/
|
||||
ulong spreadZPlane(ulong mask, ulong canPassMask, ubyte spreadToDirMask) {
|
||||
ulong res = mask & canPassMask;
|
||||
if (!res)
|
||||
return 0;
|
||||
if (spreadToDirMask & DirMask.MASK_WEST) { // x--
|
||||
res |= ((mask & 0xFEFEFEFEFEFEFEFEL) >> 1) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_EAST) { // x++
|
||||
res |= ((mask & 0x7f7f7f7f7f7f7f7fL) << 1) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_UP) { // y++
|
||||
res |= ((mask & 0x00ffffffffffffffL) << 8) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_DOWN) { // y--
|
||||
res |= ((mask & 0xffffffffffffff00L) >> 8) & canPassMask;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
X planes (WEST EAST): z, y
|
||||
z=0 z=1 z=2 z=3 z=4 z=5 z=6 z=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
*/
|
||||
ulong spreadXPlane(ulong mask, ulong canPassMask, ubyte spreadToDirMask) {
|
||||
ulong res = mask & canPassMask;
|
||||
if (!res)
|
||||
return 0;
|
||||
if (spreadToDirMask & DirMask.MASK_NORTH) { // z--
|
||||
res |= ((mask & 0xFEFEFEFEFEFEFEFEL) >> 1) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_SOUTH) { // z++
|
||||
res |= ((mask & 0x7f7f7f7f7f7f7f7fL) << 1) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_UP) { // y++
|
||||
res |= ((mask & 0x00ffffffffffffffL) << 8) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_DOWN) { // y--
|
||||
res |= ((mask & 0xffffffffffffff00L) >> 8) & canPassMask;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Y planes (DOWN UP): x, z
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
z=0 0 1 2 3 4 5 6 7
|
||||
z=1 8 9 10 11 12 13 14 15
|
||||
z=2 16 17 18 19 29 21 22 23
|
||||
z=3 24 25 26 27 28 29 30 31
|
||||
z=4 32 33 34 35 36 37 38 39
|
||||
z=5 40 41 42 43 44 45 46 47
|
||||
z=6 48 49 50 51 52 53 54 55
|
||||
z=7 56 57 58 59 60 61 62 63
|
||||
|
||||
*/
|
||||
|
||||
ulong spreadYPlane(ulong mask, ulong canPassMask, ubyte spreadToDirMask) {
|
||||
ulong res = mask & canPassMask;
|
||||
if (!res)
|
||||
return 0;
|
||||
if (spreadToDirMask & DirMask.MASK_WEST) { // x--
|
||||
res |= ((mask & 0xFEFEFEFEFEFEFEFEL) >> 1) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_EAST) { // x++
|
||||
res |= ((mask & 0x7f7f7f7f7f7f7f7fL) << 1) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_SOUTH) { // z++
|
||||
res |= ((mask & 0x00ffffffffffffffL) << 8) & canPassMask;
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_NORTH) { // z--
|
||||
res |= ((mask & 0xffffffffffffff00L) >> 8) & canPassMask;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Z planes (NORTH SOUTH): x, y
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
|
||||
X planes (WEST EAST): z, y
|
||||
z=0 z=1 z=2 z=3 z=4 z=5 z=6 z=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
*/
|
||||
ulong xPlaneFromZplanes(ref ulong[8] planes, int x) {
|
||||
ulong res = 0;
|
||||
for (int z = 0; z < 8; z++) {
|
||||
ulong n = planes[z]; // one plane == z
|
||||
n = n >> x; // move to low bit
|
||||
n &= 0x0101010101010101L;
|
||||
n = n << z; // move to Z bit
|
||||
res |= n;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Z planes (NORTH SOUTH): x, y
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
|
||||
Y planes (DOWN UP): x, z
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
z=0 0 1 2 3 4 5 6 7
|
||||
z=1 8 9 10 11 12 13 14 15
|
||||
z=2 16 17 18 19 29 21 22 23
|
||||
z=3 24 25 26 27 28 29 30 31
|
||||
z=4 32 33 34 35 36 37 38 39
|
||||
z=5 40 41 42 43 44 45 46 47
|
||||
z=6 48 49 50 51 52 53 54 55
|
||||
z=7 56 57 58 59 60 61 62 63
|
||||
*/
|
||||
ulong yPlaneFromZplanes(ref ulong[8] planes, int y) {
|
||||
ulong res = 0;
|
||||
for (int z = 0; z < 8; z++) {
|
||||
ulong n = planes[z]; // one plane == z
|
||||
n = n >> (y * 3); // move to low byte
|
||||
n &= 0xFF;
|
||||
n = n << (z * 3); // move to Z position
|
||||
res |= n;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct VisibilityCheckChunk {
|
||||
SmallChunk * chunk;
|
||||
ulong[6] maskFrom;
|
||||
ulong[6] maskTo;
|
||||
ubyte visitedFromDirMask;
|
||||
ubyte spreadToDirMask;
|
||||
void setMask(ulong mask, Dir fromDir) {
|
||||
maskFrom[fromDir] |= mask;
|
||||
visitedFromDirMask |= (1 << fromDir);
|
||||
}
|
||||
/*
|
||||
Z planes (NORTH SOUTH): x, y
|
||||
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
|
||||
y=0 0 1 2 3 4 5 6 7
|
||||
y=1 8 9 10 11 12 13 14 15
|
||||
y=2 16 17 18 19 29 21 22 23
|
||||
y=3 24 25 26 27 28 29 30 31
|
||||
y=4 32 33 34 35 36 37 38 39
|
||||
y=5 40 41 42 43 44 45 46 47
|
||||
y=6 48 49 50 51 52 53 54 55
|
||||
y=7 56 57 58 59 60 61 62 63
|
||||
*/
|
||||
void applyZPlanesTrace(ref ulong[8] planes) {
|
||||
if (spreadToDirMask & DirMask.MASK_WEST) { // x--
|
||||
// X planes (WEST EAST): z, y
|
||||
maskTo[Dir.WEST] |= xPlaneFromZplanes(planes, 0);
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_EAST) { // x++
|
||||
// X planes (WEST EAST): z, y
|
||||
maskTo[Dir.EAST] |= xPlaneFromZplanes(planes, 7);
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_DOWN) { // y--
|
||||
// Y planes (DOWN UP): x, z
|
||||
maskTo[Dir.DOWN] |= yPlaneFromZplanes(planes, 0);
|
||||
}
|
||||
if (spreadToDirMask & DirMask.MASK_UP) { // y++
|
||||
// Y planes (DOWN UP): x, z
|
||||
maskTo[Dir.UP] |= yPlaneFromZplanes(planes, 7);
|
||||
}
|
||||
}
|
||||
void tracePaths() {
|
||||
if (auto mask = maskFrom[Dir.NORTH]) {
|
||||
ulong[8] planes;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
mask = spreadZPlane(mask, chunk.canPassPlanesZ[i], spreadToDirMask);
|
||||
if (!mask)
|
||||
break;
|
||||
planes[i] = mask;
|
||||
}
|
||||
maskTo[Dir.NORTH] |= planes[0];
|
||||
applyZPlanesTrace(planes);
|
||||
} else if (auto mask = maskFrom[Dir.SOUTH]) {
|
||||
ulong[8] planes;
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
mask = spreadZPlane(mask, chunk.canPassPlanesZ[i], spreadToDirMask);
|
||||
if (!mask)
|
||||
break;
|
||||
planes[i] = mask;
|
||||
}
|
||||
maskTo[Dir.SOUTH] |= planes[7];
|
||||
applyZPlanesTrace(planes);
|
||||
}
|
||||
if (auto mask = maskFrom[Dir.DOWN]) {
|
||||
} else if (auto mask = maskFrom[Dir.UP]) {
|
||||
}
|
||||
if (auto mask = maskFrom[Dir.WEST]) {
|
||||
} else if (auto mask = maskFrom[Dir.EAST]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Diamond iterator for visibility check
|
||||
struct VisibilityCheckIterator {
|
||||
World world;
|
||||
Vector3d startPos;
|
||||
SmallChunk * startChunk;
|
||||
ChunkVisitor visitor;
|
||||
VisibilityCheckChunk[] plannedChunks;
|
||||
VisibilityCheckChunk[] visitedChunks;
|
||||
VisibilityCheckChunk * getOrAddPlannedChunk(SmallChunk * newChunk) {
|
||||
foreach(ref p; plannedChunks) {
|
||||
if (p.chunk is newChunk)
|
||||
return &p;
|
||||
}
|
||||
VisibilityCheckChunk plan;
|
||||
plan.chunk = newChunk;
|
||||
plannedChunks ~= plan;
|
||||
return &plannedChunks[$ - 1];
|
||||
}
|
||||
// step 1: plan visiting chunk
|
||||
void planVisitChunk(int x, int y, int z, Dir fromDir, ulong mask) {
|
||||
if (!mask)
|
||||
return;
|
||||
SmallChunk * newChunk = world.getCellChunk(x, y, z);
|
||||
if (!newChunk)
|
||||
return;
|
||||
VisibilityCheckChunk * plan = getOrAddPlannedChunk(newChunk);
|
||||
plan.setMask(mask, fromDir);
|
||||
}
|
||||
// step 2: visit all planned chunks: move planned to visited; trace paths; plan new visits
|
||||
void visitPlannedChunks() {
|
||||
import std.algorithm : swap;
|
||||
swap(visitedChunks, plannedChunks);
|
||||
plannedChunks.length = 0;
|
||||
foreach (ref p; visitedChunks) {
|
||||
visitor.visit(world, p.chunk);
|
||||
/// set mask of spread directions
|
||||
p.spreadToDirMask = calcSpreadMask(p.chunk.position, startPos);
|
||||
p.tracePaths;
|
||||
}
|
||||
}
|
||||
void start(World world, Vector3d startPos) {
|
||||
this.world = world;
|
||||
this.startChunk = world.getCellChunk(startPos.x, startPos.y, startPos.z);
|
||||
this.startPos = this.startChunk.position; // position aligned by 8 cells
|
||||
plannedChunks.assumeSafeAppend;
|
||||
plannedChunks.length = 0;
|
||||
visitedChunks.assumeSafeAppend;
|
||||
visitedChunks.length = 0;
|
||||
}
|
||||
void visitVisibleChunks(ChunkVisitor visitor) {
|
||||
this.visitor = visitor;
|
||||
visitor.visit(world, startChunk);
|
||||
if (auto mask = startChunk.getSideCanPassToMask(Dir.NORTH))
|
||||
planVisitChunk(startPos.x, startPos.y, startPos.z, Dir.NORTH, mask);
|
||||
if (auto mask = startChunk.getSideCanPassToMask(Dir.SOUTH))
|
||||
planVisitChunk(startPos.x, startPos.y, startPos.z, Dir.SOUTH, mask);
|
||||
if (auto mask = startChunk.getSideCanPassToMask(Dir.WEST))
|
||||
planVisitChunk(startPos.x, startPos.y, startPos.z, Dir.WEST, mask);
|
||||
if (auto mask = startChunk.getSideCanPassToMask(Dir.EAST))
|
||||
planVisitChunk(startPos.x, startPos.y, startPos.z, Dir.EAST, mask);
|
||||
if (auto mask = startChunk.getSideCanPassToMask(Dir.UP))
|
||||
planVisitChunk(startPos.x, startPos.y, startPos.z, Dir.UP, mask);
|
||||
if (auto mask = startChunk.getSideCanPassToMask(Dir.DOWN))
|
||||
planVisitChunk(startPos.x, startPos.y, startPos.z, Dir.DOWN, mask);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,31 @@ immutable cell_t VISITED_OCCUPIED = 254;
|
|||
immutable cell_t BOUND_BOTTOM = 253;
|
||||
immutable cell_t BOUND_SKY = 252;
|
||||
|
||||
|
||||
/*
|
||||
World coordinates
|
||||
|
||||
A UP
|
||||
|
|
||||
| / NORTH
|
||||
| /
|
||||
WEST |/
|
||||
-----------|-----------> EAST
|
||||
/|
|
||||
/ |
|
||||
SOUTH/ |
|
||||
L |
|
||||
| DOWN
|
||||
*/
|
||||
|
||||
/// World direction
|
||||
enum Dir : ubyte {
|
||||
NORTH = 0,
|
||||
SOUTH,
|
||||
EAST,
|
||||
WEST,
|
||||
UP,
|
||||
DOWN,
|
||||
NORTH = 0, /// z--
|
||||
SOUTH, /// z++
|
||||
EAST, /// x++
|
||||
WEST, /// x--
|
||||
UP, /// y++
|
||||
DOWN, /// y--
|
||||
}
|
||||
|
||||
// 26 direction masks based on Dir
|
||||
|
@ -64,10 +82,15 @@ struct Vector2d {
|
|||
|
||||
immutable Vector2d ZERO2 = Vector2d(0, 0);
|
||||
|
||||
/// Integer 3d vector: x,y,z
|
||||
struct Vector3d {
|
||||
/// WEST-EAST
|
||||
int x;
|
||||
/// DOWN-UP
|
||||
int y;
|
||||
/// NORTH-SOUTH
|
||||
int z;
|
||||
|
||||
this(int xx, int yy, int zz) {
|
||||
x = xx;
|
||||
y = yy;
|
||||
|
@ -249,152 +272,6 @@ alias CellArray = Array!(cell_t);
|
|||
alias Vector2dArray = Array!(Vector2d);
|
||||
alias Vector3dArray = Array!(Vector3d);
|
||||
|
||||
/*
|
||||
/// array with support of both positive and negative indexes
|
||||
struct InfiniteArray(T) {
|
||||
private:
|
||||
T[] dataPlus;
|
||||
T[] dataMinus;
|
||||
int minIdx;
|
||||
int maxIdx;
|
||||
public:
|
||||
@property int minIndex() { return minIdx; }
|
||||
@property int maxIndex() { return maxIdx; }
|
||||
void disposeFunction(T p) {
|
||||
destroy(p);
|
||||
}
|
||||
~this() {
|
||||
foreach(p; dataPlus)
|
||||
if (p !is T.init)
|
||||
disposeFunction(p);
|
||||
foreach(p; dataMinus)
|
||||
if (p !is T.init)
|
||||
disposeFunction(p);
|
||||
}
|
||||
T get(int index) {
|
||||
if (index >= 0) {
|
||||
if (index >= maxIdx)
|
||||
return T.init;
|
||||
return dataPlus[index];
|
||||
} else {
|
||||
if (index <= minIdx)
|
||||
return T.init;
|
||||
return dataMinus[-index];
|
||||
}
|
||||
}
|
||||
void set(int index, T value) {
|
||||
if (index >= 0) {
|
||||
if (index >= maxIdx) {
|
||||
// extend array
|
||||
if (index <= dataPlus.length) {
|
||||
int oldsize = dataPlus.length;
|
||||
int newsize = 1024;
|
||||
while (newsize <= index)
|
||||
newsize <<= 1;
|
||||
dataPlus.length = newsize;
|
||||
dataPlus.assumeSafeAppend;
|
||||
for(int i = oldsize; i < newsize; i++)
|
||||
dataPlus[i] = T.init;
|
||||
}
|
||||
maxIdx = index + 1;
|
||||
}
|
||||
if (dataPlus[index] !is T.init && dataPlus[index] !is value)
|
||||
disposeFunction(dataPlus[index]);
|
||||
dataPlus[index] = value;
|
||||
} else {
|
||||
if (index <= minIdx) {
|
||||
// extend array
|
||||
if (-index <= dataMinus.length) {
|
||||
int oldsize = dataMinus.length;
|
||||
int newsize = 1024;
|
||||
while (newsize <= -index)
|
||||
newsize <<= 1;
|
||||
dataMinus.length = newsize;
|
||||
dataMinus.assumeSafeAppend;
|
||||
for(int i = oldsize; i < newsize; i++)
|
||||
dataMinus[i] = T.init;
|
||||
}
|
||||
maxIdx = index - 1;
|
||||
}
|
||||
if (dataMinus[-index] !is T.init && dataMinus[-index] !is value)
|
||||
disposeFunction(dataMinus[-index]);
|
||||
dataMinus[-index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InfiniteMatrix(T) {
|
||||
private:
|
||||
int _size = 0;
|
||||
int _sizeShift = 0;
|
||||
int _sizeShiftMul2 = 0;
|
||||
int _sizeMask = 0;
|
||||
int _invSizeMask = 0;
|
||||
T[] _data;
|
||||
void resize(int newSizeShift) {
|
||||
int newSize = (1<<newSizeShift);
|
||||
T[] newdata;
|
||||
newdata.length = newSize * 2 * newSize * 2;
|
||||
newdata[0 .. $] = null;
|
||||
for (int y = -_size; y < _size; y++) {
|
||||
for (int x = -_size; x < _size; x++) {
|
||||
T v = get(x, y);
|
||||
if (x < -newSize || x >= newSize || y < -newSize || y >= newSize) {
|
||||
// destory: // outside new size
|
||||
destroy(v);
|
||||
} else {
|
||||
// move
|
||||
newdata[((y + newSize) << (newSizeShift + 1)) | (x + newSize)] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
_data = newdata;
|
||||
_size = newSize;
|
||||
_sizeShift = newSizeShift;
|
||||
_sizeShiftMul2 = _sizeShift + 1;
|
||||
_sizeMask = (1 << _sizeShiftMul2) - 1;
|
||||
_invSizeMask = ~_sizeMask;
|
||||
}
|
||||
int calcIndex(int x, int y) {
|
||||
return (y << _sizeShiftMul2) + x;
|
||||
}
|
||||
public:
|
||||
@property int size() { return _size; }
|
||||
T get(int x, int y) {
|
||||
if (!_data)
|
||||
return null;
|
||||
x += _size;
|
||||
y += _size;
|
||||
if (!((x | y) & ~_sizeMask)) {
|
||||
return _data.ptr[(y << _sizeShiftMul2) + x]; //calcIndex(x, y)
|
||||
}
|
||||
return null;
|
||||
}
|
||||
void set(int x, int y, T v) {
|
||||
if (x < -_size || x >= _size || y < -_size || y >= _size) {
|
||||
int newSizeShift = _sizeShift < 6 ? 6 : _sizeShift + 1;
|
||||
for (; ;newSizeShift++) {
|
||||
int sz = 1 << newSizeShift;
|
||||
if (x < -sz || x >= sz || y < -sz || y >= sz)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
resize(newSizeShift);
|
||||
}
|
||||
x += _size;
|
||||
y += _size;
|
||||
int index = calcIndex(x, y);
|
||||
if (_data.ptr[index])
|
||||
destroy(_data.ptr[index]);
|
||||
_data.ptr[index] = v;
|
||||
}
|
||||
~this() {
|
||||
foreach(ref v; _data)
|
||||
if (v)
|
||||
destroy(v);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
struct Position {
|
||||
|
|
|
@ -219,10 +219,6 @@ private:
|
|||
int maxVisibleRange = MAX_VIEW_DISTANCE;
|
||||
}
|
||||
|
||||
interface ChunkVisitor {
|
||||
void visit(World world, SmallChunk * chunk);
|
||||
}
|
||||
|
||||
struct VisitorCell {
|
||||
SmallChunk * chunk;
|
||||
ulong[6] accessible;
|
||||
|
|
|
@ -430,6 +430,7 @@ class UiWidget : VerticalLayout { //, CellVisitor
|
|||
}
|
||||
|
||||
void updatePositionMessage() {
|
||||
import std.string : format;
|
||||
Widget w = childById("lblPosition");
|
||||
string dir = _world.camPosition.direction.dir.to!string;
|
||||
dstring s = format("pos(%d,%d) h=%d fps:%d %s [F]lying: %s [U]pdateMesh: %s", _world.camPosition.pos.x, _world.camPosition.pos.z, _world.camPosition.pos.y,
|
||||
|
|
Loading…
Reference in New Issue