dminer optimization

This commit is contained in:
Vadim Lopatin 2017-05-15 15:54:04 +03:00
parent 1e14826643
commit a66f93d81a
4 changed files with 380 additions and 161 deletions

View File

@ -6,6 +6,7 @@ import dminer.core.world;
import dlangui.graphics.scene.mesh;
version = FAST_VISIBILITY_PATH;
// Y range: 0..CHUNK_DY-1
immutable int CHUNK_DY = 128;
@ -150,6 +151,7 @@ struct SmallChunk {
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
protected ubyte[6] canPassFromTo; // index is FROM direction, ubyte is DirMask of TO direction; 1 means can pass FROM .. TO
//ulong[6][6] canPassFromTo; // 288 bytes
SmallChunk * [6] nearChunks;
protected Vector3d _pos;
@ -496,11 +498,11 @@ struct SmallChunk {
canPassPlanesZ[z] = canPassFlags;
visiblePlanesZ[z] = visibleFlags;
}
// can pass from to
//for (Dir from = Dir.min; from <= Dir.max; ++from) {
// for (Dir to = Dir.min; to <= Dir.max; ++to) {
// }
//}
for (Dir from = Dir.min; from <= Dir.max; ++from) {
fillCanPassFrom(from);
}
dirty = false;
empty = (visiblePlanesZ[0]|visiblePlanesZ[1]|visiblePlanesZ[2]|visiblePlanesZ[3]|
visiblePlanesZ[4]|visiblePlanesZ[5]|visiblePlanesZ[6]|visiblePlanesZ[7]) == 0;
@ -508,6 +510,128 @@ struct SmallChunk {
dirtyMesh = true;
}
/// returns DirMask of available pass direction for specified FROM direction
ubyte getCanPassFromFlags(Dir dirFrom) {
return canPassFromTo[dirFrom];
}
protected void fillCanPassFrom(Dir dirFrom) {
ulong[8] planes;
ulong mask = 0xFFFFFFFFFFFFFFFFL;
ubyte res = 0;
final switch (dirFrom) {
case Dir.NORTH:
for (int i = 7; i >= 0; i--) {
mask = spreadZPlane(mask, canPassPlanesZ[i], DirMask.MASK_ALL);
if (!mask)
break;
planes[i] = mask;
}
if (planes[0])
res |= DirMask.MASK_NORTH;
if (xPlaneFromZplanes(planes, 0))
res |= DirMask.MASK_WEST;
if (xPlaneFromZplanes(planes, 7))
res |= DirMask.MASK_EAST;
if (yPlaneFromZplanes(planes, 0))
res |= DirMask.MASK_DOWN;
if (yPlaneFromZplanes(planes, 7))
res |= DirMask.MASK_UP;
break;
case Dir.SOUTH:
for (int i = 0; i <= 7; i++) {
mask = spreadZPlane(mask, canPassPlanesZ[i], DirMask.MASK_ALL);
if (!mask)
break;
planes[i] = mask;
}
if (planes[7])
res |= DirMask.MASK_SOUTH;
if (xPlaneFromZplanes(planes, 0))
res |= DirMask.MASK_WEST;
if (xPlaneFromZplanes(planes, 7))
res |= DirMask.MASK_EAST;
if (yPlaneFromZplanes(planes, 0))
res |= DirMask.MASK_DOWN;
if (yPlaneFromZplanes(planes, 7))
res |= DirMask.MASK_UP;
break;
case Dir.WEST: // x--
for (int i = 7; i >= 0; i--) {
mask = spreadXPlane(mask, canPassPlanesX[i], DirMask.MASK_ALL);
if (!mask)
break;
planes[i] = mask;
}
if (planes[0])
res |= DirMask.MASK_WEST;
if (zPlaneFromXplanes(planes, 0))
res |= DirMask.MASK_NORTH;
if (zPlaneFromXplanes(planes, 7))
res |= DirMask.MASK_SOUTH;
if (yPlaneFromXplanes(planes, 0))
res |= DirMask.MASK_DOWN;
if (yPlaneFromXplanes(planes, 7))
res |= DirMask.MASK_UP;
break;
case Dir.EAST: // x++
for (int i = 0; i <= 7; i++) {
mask = spreadXPlane(mask, canPassPlanesX[i], DirMask.MASK_ALL);
if (!mask)
break;
planes[i] = mask;
}
if (planes[7])
res |= DirMask.MASK_EAST;
if (zPlaneFromXplanes(planes, 0))
res |= DirMask.MASK_NORTH;
if (zPlaneFromXplanes(planes, 7))
res |= DirMask.MASK_SOUTH;
if (yPlaneFromXplanes(planes, 0))
res |= DirMask.MASK_DOWN;
if (yPlaneFromXplanes(planes, 7))
res |= DirMask.MASK_UP;
break;
case Dir.DOWN: // y--
for (int i = 7; i >= 0; i--) {
mask = spreadYPlane(mask, canPassPlanesY[i], DirMask.MASK_ALL);
if (!mask)
break;
planes[i] = mask;
}
if (planes[0])
res |= DirMask.MASK_DOWN;
if (zPlaneFromYplanes(planes, 0))
res |= DirMask.MASK_NORTH;
if (zPlaneFromYplanes(planes, 7))
res |= DirMask.MASK_SOUTH;
if (xPlaneFromYplanes(planes, 0))
res |= DirMask.MASK_WEST;
if (xPlaneFromYplanes(planes, 7))
res |= DirMask.MASK_EAST;
break;
case Dir.UP: // y--
for (int i = 0; i <= 7; i++) {
mask = spreadYPlane(mask, canPassPlanesY[i], DirMask.MASK_ALL);
if (!mask)
break;
planes[i] = mask;
}
if (planes[7])
res |= DirMask.MASK_UP;
if (zPlaneFromYplanes(planes, 0))
res |= DirMask.MASK_NORTH;
if (zPlaneFromYplanes(planes, 7))
res |= DirMask.MASK_SOUTH;
if (xPlaneFromYplanes(planes, 0))
res |= DirMask.MASK_WEST;
if (xPlaneFromYplanes(planes, 7))
res |= DirMask.MASK_EAST;
break;
}
canPassFromTo[dirFrom] = res;
}
static void spreadFlags(ulong src, ref ulong[8] planes, ref ulong[8] dst, int start, int end, ubyte spreadMask) {
if (start < end) {
for (int i = start; i <= end; ++i) {
@ -1206,19 +1330,53 @@ void testPlanes() {
v.testPlanesExtract();
}
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);
version(FAST_VISIBILITY_PATH) {
struct VisibilityCheckChunk {
SmallChunk * chunk;
ulong[6] maskFrom;
ulong[6] maskTo;
Vector3d pos;
ubyte visitedFromDirMask;
ubyte spreadToDirMask;
void setMask(ulong mask, Dir fromDir) {
maskFrom[fromDir] |= mask;
visitedFromDirMask |= (1 << fromDir);
}
void traceFrom(Dir fromDir) {
ubyte m = chunk ? chunk.getCanPassFromFlags(fromDir) : DirMask.MASK_ALL;
for (ubyte dir = 0; dir < 6; dir++) {
ubyte flag = cast(ubyte)(1 << dir);
if (flag & spreadToDirMask)
if (m & flag)
maskTo[dir] |= 0xFFFFFFFFFFFFFFFFL;
}
}
void tracePaths() {
for (Dir dirFrom = Dir.min; dirFrom <= Dir.max; dirFrom++) {
if ((visitedFromDirMask & (1 << dirFrom)))
traceFrom(dirFrom);
}
}
}
/*
Z planes (NORTH SOUTH): x, y
x=0 x=1 x=2 x=3 x=4 x=5 x=6 x=7
} else {
struct VisibilityCheckChunk {
SmallChunk * chunk;
ulong[6] maskFrom;
ulong[6] maskTo;
Vector3d pos;
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
@ -1227,158 +1385,183 @@ struct VisibilityCheckChunk {
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);
*/
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);
}
}
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 applyYPlanesTrace(ref ulong[8] planes) {
if (spreadToDirMask & DirMask.MASK_WEST) { // x--
// X planes (WEST EAST): z, y
maskTo[Dir.WEST] |= xPlaneFromYplanes(planes, 0);
void applyYPlanesTrace(ref ulong[8] planes) {
if (spreadToDirMask & DirMask.MASK_WEST) { // x--
// X planes (WEST EAST): z, y
maskTo[Dir.WEST] |= xPlaneFromYplanes(planes, 0);
}
if (spreadToDirMask & DirMask.MASK_EAST) { // x++
// X planes (WEST EAST): z, y
maskTo[Dir.EAST] |= xPlaneFromYplanes(planes, 7);
}
if (spreadToDirMask & DirMask.MASK_NORTH) { // z--
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.NORTH] |= zPlaneFromYplanes(planes, 0);
}
if (spreadToDirMask & DirMask.MASK_SOUTH) { // z++
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.SOUTH] |= zPlaneFromYplanes(planes, 7);
}
}
if (spreadToDirMask & DirMask.MASK_EAST) { // x++
// X planes (WEST EAST): z, y
maskTo[Dir.EAST] |= xPlaneFromYplanes(planes, 7);
}
if (spreadToDirMask & DirMask.MASK_NORTH) { // z--
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.NORTH] |= zPlaneFromYplanes(planes, 0);
}
if (spreadToDirMask & DirMask.MASK_SOUTH) { // z++
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.SOUTH] |= zPlaneFromYplanes(planes, 7);
}
}
void applyXPlanesTrace(ref ulong[8] planes) {
if (spreadToDirMask & DirMask.MASK_NORTH) { // z--
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.NORTH] |= zPlaneFromXplanes(planes, 0);
void applyXPlanesTrace(ref ulong[8] planes) {
if (spreadToDirMask & DirMask.MASK_NORTH) { // z--
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.NORTH] |= zPlaneFromXplanes(planes, 0);
}
if (spreadToDirMask & DirMask.MASK_SOUTH) { // z++
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.SOUTH] |= zPlaneFromXplanes(planes, 7);
}
if (spreadToDirMask & DirMask.MASK_DOWN) { // y--
// Y planes (DOWN UP): x, z
maskTo[Dir.DOWN] |= yPlaneFromXplanes(planes, 0);
}
if (spreadToDirMask & DirMask.MASK_UP) { // y++
// Y planes (DOWN UP): x, z
maskTo[Dir.UP] |= yPlaneFromXplanes(planes, 7);
}
}
if (spreadToDirMask & DirMask.MASK_SOUTH) { // z++
// Z planes (NORTH SOUTH): x, y
maskTo[Dir.SOUTH] |= zPlaneFromXplanes(planes, 7);
}
if (spreadToDirMask & DirMask.MASK_DOWN) { // y--
// Y planes (DOWN UP): x, z
maskTo[Dir.DOWN] |= yPlaneFromXplanes(planes, 0);
}
if (spreadToDirMask & DirMask.MASK_UP) { // y++
// Y planes (DOWN UP): x, z
maskTo[Dir.UP] |= yPlaneFromXplanes(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;
void tracePaths() {
if (!chunk) {
// empty chunk - assuming transparent
for (ubyte dir = 0; dir < 6; dir++) {
if (spreadToDirMask & (1 << dir))
maskTo[dir] |= 0xFFFFFFFFFFFFFFFFL;
}
return;
}
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;
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];
applyYPlanesTrace(planes);
}
maskTo[Dir.SOUTH] |= planes[7];
applyYPlanesTrace(planes);
}
if (auto mask = maskFrom[Dir.DOWN]) {
ulong[8] planes;
for (int i = 7; i >= 0; i--) {
mask = spreadYPlane(mask, chunk.canPassPlanesY[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
if (auto mask = maskFrom[Dir.DOWN]) {
ulong[8] planes;
for (int i = 7; i >= 0; i--) {
mask = spreadYPlane(mask, chunk.canPassPlanesY[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
}
maskTo[Dir.DOWN] |= planes[0];
applyYPlanesTrace(planes);
} else if (auto mask = maskFrom[Dir.UP]) {
ulong[8] planes;
for (int i = 0; i <= 7; i++) {
mask = spreadYPlane(mask, chunk.canPassPlanesY[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
}
maskTo[Dir.UP] |= planes[7];
applyYPlanesTrace(planes);
}
maskTo[Dir.DOWN] |= planes[0];
applyYPlanesTrace(planes);
} else if (auto mask = maskFrom[Dir.UP]) {
ulong[8] planes;
for (int i = 0; i <= 7; i++) {
mask = spreadYPlane(mask, chunk.canPassPlanesY[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
if (auto mask = maskFrom[Dir.WEST]) {
ulong[8] planes;
for (int i = 7; i >= 0; i--) {
mask = spreadXPlane(mask, chunk.canPassPlanesX[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
}
maskTo[Dir.WEST] |= planes[0];
applyXPlanesTrace(planes);
} else if (auto mask = maskFrom[Dir.EAST]) {
ulong[8] planes;
for (int i = 0; i <= 7; i++) {
mask = spreadXPlane(mask, chunk.canPassPlanesX[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
}
maskTo[Dir.EAST] |= planes[7];
applyXPlanesTrace(planes);
}
maskTo[Dir.UP] |= planes[7];
applyYPlanesTrace(planes);
}
if (auto mask = maskFrom[Dir.WEST]) {
ulong[8] planes;
for (int i = 7; i >= 0; i--) {
mask = spreadXPlane(mask, chunk.canPassPlanesX[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
}
maskTo[Dir.WEST] |= planes[0];
applyXPlanesTrace(planes);
} else if (auto mask = maskFrom[Dir.EAST]) {
ulong[8] planes;
for (int i = 0; i <= 7; i++) {
mask = spreadXPlane(mask, chunk.canPassPlanesX[i], spreadToDirMask);
if (!mask)
break;
planes[i] = mask;
}
maskTo[Dir.EAST] |= planes[7];
applyXPlanesTrace(planes);
}
}
}
/// Diamond iterator for visibility check
struct VisibilityCheckIterator {
World world;
Vector3d startPos;
Vector3d camPos;
SmallChunk * startChunk;
ChunkVisitor visitor;
int maxDistance;
int maxDistanceSquared;
VisibilityCheckChunk[] plannedChunks;
VisibilityCheckChunk[] visitedChunks;
VisibilityCheckChunk * getOrAddPlannedChunk(SmallChunk * newChunk) {
/// get or add planned chunk by position
VisibilityCheckChunk * getOrAddPlannedChunk(Vector3d pos) {
foreach(ref p; plannedChunks) {
if (p.chunk is newChunk)
if (p.pos == pos)
return &p;
}
VisibilityCheckChunk plan;
plan.chunk = newChunk;
plan.pos = pos;
plannedChunks ~= plan;
return &plannedChunks[$ - 1];
}
// step 1: plan visiting chunk
void planVisitingChunk(int x, int y, int z, Dir fromDir, ulong mask) {
void planVisitingChunk(Vector3d p, Dir fromDir, ulong mask) {
// mask test
if (!mask)
return;
SmallChunk * newChunk = world.getCellChunk(x, y, z);
if (!newChunk)
// distance test
Vector3d diff = p - camPos;
if (diff.squaredLength() > maxDistanceSquared)
return;
VisibilityCheckChunk * plan = getOrAddPlannedChunk(newChunk);
// direction test (TODO)
int dot = diff.dot(cameraDirection);
if (dot < 3000)
return;
//....
// plan visiting
VisibilityCheckChunk * plan = getOrAddPlannedChunk(p);
if (!plan.chunk) {
plan.chunk = world.getCellChunk(p.x, p.y, p.z);
}
plan.setMask(mask, fromDir);
}
// step 2: visit all planned chunks: move planned to visited; trace paths; plan new visits
@ -1389,54 +1572,75 @@ struct VisibilityCheckIterator {
foreach (ref p; visitedChunks) {
visitor.visit(world, p.chunk);
/// set mask of spread directions
p.spreadToDirMask = calcSpreadMask(p.chunk.position, startPos);
p.spreadToDirMask = calcSpreadMask(p.pos, startPos);
p.tracePaths();
ubyte mask = p.spreadToDirMask;
Vector3d pos = p.chunk.position;
Vector3d pos = p.pos;
if ((mask & DirMask.MASK_NORTH) && p.maskTo[Dir.NORTH]) { // z--
planVisitingChunk(pos.x, pos.y, pos.z - 8, Dir.NORTH, p.maskTo[Dir.NORTH]);
planVisitingChunk(Vector3d(pos.x, pos.y, pos.z - 8), Dir.NORTH, p.maskTo[Dir.NORTH]);
}
if ((mask & DirMask.MASK_SOUTH) && p.maskTo[Dir.SOUTH]) { // z++
planVisitingChunk(pos.x, pos.y, pos.z + 8, Dir.SOUTH, p.maskTo[Dir.SOUTH]);
planVisitingChunk(Vector3d(pos.x, pos.y, pos.z + 8), Dir.SOUTH, p.maskTo[Dir.SOUTH]);
}
if ((mask & DirMask.MASK_WEST) && p.maskTo[Dir.WEST]) { // x--
planVisitingChunk(pos.x - 8, pos.y, pos.z, Dir.WEST, p.maskTo[Dir.WEST]);
planVisitingChunk(Vector3d(pos.x - 8, pos.y, pos.z), Dir.WEST, p.maskTo[Dir.WEST]);
}
if ((mask & DirMask.MASK_EAST) && p.maskTo[Dir.EAST]) { // x++
planVisitingChunk(pos.x + 8, pos.y, pos.z, Dir.EAST, p.maskTo[Dir.EAST]);
planVisitingChunk(Vector3d(pos.x + 8, pos.y, pos.z), Dir.EAST, p.maskTo[Dir.EAST]);
}
if ((mask & DirMask.MASK_DOWN) && p.maskTo[Dir.DOWN]) { // y--
planVisitingChunk(pos.x, pos.y - 8, pos.z, Dir.DOWN, p.maskTo[Dir.DOWN]);
planVisitingChunk(Vector3d(pos.x, pos.y - 8, pos.z), Dir.DOWN, p.maskTo[Dir.DOWN]);
}
if ((mask & DirMask.MASK_UP) && p.maskTo[Dir.UP]) { // y++
planVisitingChunk(pos.x, pos.y + 8, pos.z, Dir.UP, p.maskTo[Dir.UP]);
planVisitingChunk(Vector3d(pos.x, pos.y + 8, pos.z), Dir.UP, p.maskTo[Dir.UP]);
}
}
}
void start(World world, Vector3d startPos) {
void start(World world, Vector3d startPos, int maxDistance) {
this.world = world;
this.startChunk = world.getCellChunk(startPos.x, startPos.y, startPos.z);
this.startPos = this.startChunk.position; // position aligned by 8 cells
//if (!startChunk)
// return;
startPos.x &= ~7;
startPos.y &= ~7;
startPos.z &= ~7;
this.startPos = startPos; // position aligned by 8 cells
plannedChunks.assumeSafeAppend;
plannedChunks.length = 0;
visitedChunks.assumeSafeAppend;
visitedChunks.length = 0;
maxDistanceSquared = maxDistance * maxDistance;
this.maxDistance = maxDistance;
}
void visitVisibleChunks(ChunkVisitor visitor) {
Vector3d cameraDirection;
void visitVisibleChunks(ChunkVisitor visitor, Vector3d cameraDirection) {
this.visitor = visitor;
this.cameraDirection = cameraDirection;
Vector3d cameraOffset = cameraDirection;
cameraOffset.x /= 16;
cameraOffset.y /= 16;
cameraOffset.z /= 16;
this.camPos = startPos - cameraOffset;
//if (!startChunk)
// return;
visitor.visit(world, startChunk);
if (auto mask = startChunk.getSideCanPassToMask(Dir.NORTH))
planVisitingChunk(startPos.x, startPos.y, startPos.z - 8, Dir.NORTH, mask);
if (auto mask = startChunk.getSideCanPassToMask(Dir.SOUTH))
planVisitingChunk(startPos.x, startPos.y, startPos.z + 8, Dir.SOUTH, mask);
if (auto mask = startChunk.getSideCanPassToMask(Dir.WEST))
planVisitingChunk(startPos.x - 8, startPos.y, startPos.z, Dir.WEST, mask);
if (auto mask = startChunk.getSideCanPassToMask(Dir.EAST))
planVisitingChunk(startPos.x + 8, startPos.y, startPos.z, Dir.EAST, mask);
if (auto mask = startChunk.getSideCanPassToMask(Dir.DOWN))
planVisitingChunk(startPos.x, startPos.y - 8, startPos.z, Dir.DOWN, mask);
if (auto mask = startChunk.getSideCanPassToMask(Dir.UP))
planVisitingChunk(startPos.x, startPos.y + 8, startPos.z, Dir.UP, mask);
if (auto mask = startChunk ? startChunk.getSideCanPassToMask(Dir.NORTH) : 0xFFFFFFFFFFFFFFFFL)
planVisitingChunk(Vector3d(startPos.x, startPos.y, startPos.z - 8), Dir.NORTH, mask);
if (auto mask = startChunk ? startChunk.getSideCanPassToMask(Dir.SOUTH) : 0xFFFFFFFFFFFFFFFFL)
planVisitingChunk(Vector3d(startPos.x, startPos.y, startPos.z + 8), Dir.SOUTH, mask);
if (auto mask = startChunk ? startChunk.getSideCanPassToMask(Dir.WEST) : 0xFFFFFFFFFFFFFFFFL)
planVisitingChunk(Vector3d(startPos.x - 8, startPos.y, startPos.z), Dir.WEST, mask);
if (auto mask = startChunk ? startChunk.getSideCanPassToMask(Dir.EAST) : 0xFFFFFFFFFFFFFFFFL)
planVisitingChunk(Vector3d(startPos.x + 8, startPos.y, startPos.z), Dir.EAST, mask);
if (auto mask = startChunk ? startChunk.getSideCanPassToMask(Dir.DOWN) : 0xFFFFFFFFFFFFFFFFL)
planVisitingChunk(Vector3d(startPos.x, startPos.y - 8, startPos.z), Dir.DOWN, mask);
if (auto mask = startChunk ? startChunk.getSideCanPassToMask(Dir.UP) : 0xFFFFFFFFFFFFFFFFL)
planVisitingChunk(Vector3d(startPos.x, startPos.y + 8, startPos.z), Dir.UP, mask);
for (int d = 0; d < maxDistance; d += 5) {
if (!plannedChunks.length)
break;
visitPlannedChunks();
}
}
}

View File

@ -180,6 +180,14 @@ struct Vector3d {
}
return res;
}
int dot(ref Vector3d v) {
return x * v.x + y * v.y + z * v.z;
}
int squaredLength() {
return x*x + y*y + z*z;
}
}
__gshared const Vector3d ZERO3 = Vector3d(0, 0, 0);

View File

@ -7,7 +7,7 @@ import dminer.core.chunk;
version (Android) {
const int MAX_VIEW_DISTANCE = 60;
} else {
const int MAX_VIEW_DISTANCE = 90;
const int MAX_VIEW_DISTANCE = 120;
}

View File

@ -65,6 +65,7 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
import dlangui.graphics.scene.node;
private World _world;
private ChunkDiamondVisitor _chunkVisitor;
private VisibilityCheckIterator _chunkIterator;
private Vector3d _pos;
private Node3d _node;
private Camera _cam;
@ -82,14 +83,20 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
/// override it
_node = node;
//Log.d("drawing Miner scene");
_chunkVisitor.init(_world, MAX_VIEW_DISTANCE, this);
_chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE);
//_chunkVisitor.init(_world, MAX_VIEW_DISTANCE, this);
_pos = _world.camPosition.pos;
_camPosition = _cam.translation;
_camForwardVector = _cam.forwardVectorWorld;
_camPosition -= _camForwardVector * 8;
_skippedCount = _drawnCount = 0;
long ts = currentTimeMillis();
_chunkVisitor.visitChunks(_pos);
//_chunkVisitor.visitChunks(_pos);
Vector3d camVector;
camVector.x = cast(int)(_camForwardVector.x * 256);
camVector.y = cast(int)(_camForwardVector.y * 256);
camVector.z = cast(int)(_camForwardVector.z * 256);
_chunkIterator.visitVisibleChunks(this, camVector);
long duration = currentTimeMillis() - ts;
Log.d("drawing of Miner scene finished in ", duration, " ms skipped:", _skippedCount, " drawn:", _drawnCount);
}
@ -99,7 +106,7 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
vec3 chunkPos = vec3(p.x + 4, p.y + 4, p.z + 4);
vec3 chunkDirection = (chunkPos - _camPosition).normalized;
float dot = _camForwardVector.dot(chunkDirection);
//Log.d("chunkPos ", chunkPos, " chunkDir ", chunkDirection, " camDir ");
//Log.d("visit() chunkPos ", chunkPos, " chunkDir ", chunkDirection, " camDir ");
if (dot < 0.7) { // cos(45)
_skippedCount++;
return;