dminer fixes

This commit is contained in:
Vadim Lopatin 2016-04-27 09:58:17 +03:00
parent f77ed053cb
commit 416b519f39
2 changed files with 108 additions and 29 deletions

View File

@ -2,6 +2,8 @@ module dminer.core.chunk;
import dminer.core.minetypes; import dminer.core.minetypes;
import dminer.core.blocks; import dminer.core.blocks;
import dminer.core.world;
import dlangui.graphics.scene.mesh;
// Y range: 0..CHUNK_DY-1 // Y range: 0..CHUNK_DY-1
immutable int CHUNK_DY = 128; immutable int CHUNK_DY = 128;
@ -16,21 +18,16 @@ immutable int CHUNKS_X_MASK = (CHUNKS_X << 1) - 1;
immutable int CHUNKS_Z_MASK = (CHUNKS_Z << 1) - 1; immutable int CHUNKS_Z_MASK = (CHUNKS_Z << 1) - 1;
interface CellVisitor { interface CellVisitor {
import dminer.core.world;
//void newDirection(ref Position camPosition); //void newDirection(ref Position camPosition);
//void visitFace(World world, ref Position camPosition, Vector3d pos, cell_t cell, Dir face); //void visitFace(World world, ref Position camPosition, Vector3d pos, cell_t cell, Dir face);
void visit(World world, ref Position camPosition, Vector3d pos, cell_t cell, int visibleFaces); void visit(World world, ref Position camPosition, Vector3d pos, cell_t cell, int visibleFaces);
} }
interface ChunkCellVisitor {
void visit(int x, int y, int z, cell_t cell, int visibleFaces);
}
// vertical stack of chunks with same X, Z, and different Y // vertical stack of chunks with same X, Z, and different Y
struct ChunkStack { struct ChunkStack {
protected int _minChunkY; protected int _minChunkY;
protected int _chunkCount; protected int _chunkCount;
SmallChunk ** _chunks; protected SmallChunk ** _chunks;
/// get chunk from stack by chunk Y index /// get chunk from stack by chunk Y index
SmallChunk * get(int chunkY) { SmallChunk * get(int chunkY) {
int idx = chunkY - _minChunkY; int idx = chunkY - _minChunkY;
@ -47,7 +44,7 @@ struct ChunkStack {
if (_chunks[idx]) { if (_chunks[idx]) {
if (_chunks[idx] is item) if (_chunks[idx] is item)
return; return;
SmallChunk.release(_chunks[idx]); _chunks[idx].release;
} }
_chunks[idx] = item; _chunks[idx] = item;
return; return;
@ -100,7 +97,7 @@ struct ChunkStack {
void clear() { void clear() {
if (_chunkCount) { if (_chunkCount) {
for(int i = 0; i < _chunkCount; i++) { for(int i = 0; i < _chunkCount; i++) {
SmallChunk.release(_chunks[i]); _chunks[i].release;
} }
freeChunks(_chunks); freeChunks(_chunks);
} }
@ -115,22 +112,24 @@ struct ChunkStack {
/// 8x8x8 chunk /// 8x8x8 chunk
struct SmallChunk { struct SmallChunk {
cell_t[8*8*8] cells; // 512 bytes protected cell_t[8*8*8] cells; // 512 bytes
ubyte[8*8*8] sunlight; // 512 bytes protected ubyte[8*8*8] sunlight; // 512 bytes
ulong[8] opaquePlanesX; // 64 bytes protected ulong[8] opaquePlanesX; // 64 bytes
ulong[8] opaquePlanesY; // 64 bytes protected ulong[8] opaquePlanesY; // 64 bytes
ulong[8] opaquePlanesZ; // 64 bytes protected ulong[8] opaquePlanesZ; // 64 bytes
ulong[8] visiblePlanesX; // 64 bytes protected ulong[8] visiblePlanesX; // 64 bytes
ulong[8] visiblePlanesY; // 64 bytes protected ulong[8] visiblePlanesY; // 64 bytes
ulong[8] visiblePlanesZ; // 64 bytes protected ulong[8] visiblePlanesZ; // 64 bytes
ulong[8] canPassPlanesX; // 64 bytes protected ulong[8] canPassPlanesX; // 64 bytes
ulong[8] canPassPlanesY; // 64 bytes protected ulong[8] canPassPlanesY; // 64 bytes
ulong[8] canPassPlanesZ; // 64 bytes protected ulong[8] canPassPlanesZ; // 64 bytes
//ulong[6][6] canPassFromTo; // 288 bytes //ulong[6][6] canPassFromTo; // 288 bytes
SmallChunk * [6] nearChunks; SmallChunk * [6] nearChunks;
bool dirty; protected Vector3d pos;
bool empty; private Mesh _minerMesh;
Vector3d pos; protected bool dirty;
protected bool dirtyMesh;
protected bool empty;
static SmallChunk * alloc(int x, int y, int z) nothrow @nogc { static SmallChunk * alloc(int x, int y, int z) nothrow @nogc {
import core.stdc.stdlib : malloc; import core.stdc.stdlib : malloc;
@ -142,13 +141,26 @@ struct SmallChunk {
return res; return res;
} }
static void release(SmallChunk * obj) { void release() {
if (!obj) if (!(&this))
return; return;
compact();
import core.stdc.stdlib : free; import core.stdc.stdlib : free;
free(obj); free(&this);
} }
/// destroys mesh
void compact() {
if (_minerMesh) {
destroy(_minerMesh);
_minerMesh = null;
dirtyMesh = true;
}
}
static int calcIndex(int x, int y, int z) {
return ((((y&7) << 3) | (z&7)) << 3) | (x&7);
}
cell_t getCell(int x, int y, int z) const { cell_t getCell(int x, int y, int z) const {
return cells[((((y&7) << 3) | (z&7)) << 3) | (x&7)]; return cells[((((y&7) << 3) | (z&7)) << 3) | (x&7)];
} }
@ -186,7 +198,61 @@ struct SmallChunk {
return chunk.getSideCanPassToMask(opposite(dir)); return chunk.getSideCanPassToMask(opposite(dir));
} }
private void findVisibleFaces(ChunkCellVisitor visitor) { void visitVisibleFaces(World world, CellVisitor visitor) {
if (dirty)
generateMasks();
if (empty)
return;
ubyte[64] visibleFaceFlags;
findVisibleFaces(visibleFaceFlags);
int index = 0;
for (int y = 0; y < 8; y++) {
for (int z = 0; z < 8; z++) {
for (int x = 0; x < 8; x++) {
int visibleFaces = visibleFaceFlags[index];
if (visibleFaces) {
visitor.visit(world, world.camPosition, Vector3d(pos.x + x, pos.y + y, pos.z + z), cells[index], visibleFaces);
}
index++;
}
}
}
}
/// get mesh for chunk (generate if not exists)
Mesh getMesh(World world) {
if (dirty)
generateMasks();
if (empty)
return null;
if (!_minerMesh) {
_minerMesh = new Mesh(VertexFormat(VertexElementType.POSITION, VertexElementType.NORMAL, VertexElementType.COLOR, VertexElementType.TEXCOORD0));
dirtyMesh = true;
}
if (dirtyMesh) {
_minerMesh.reset();
ubyte[64] visibleFaceFlags;
findVisibleFaces(visibleFaceFlags);
int index = 0;
for (int y = 0; y < 8; y++) {
for (int z = 0; z < 8; z++) {
for (int x = 0; x < 8; x++) {
int visibleFaces = visibleFaceFlags[index];
if (visibleFaces) {
BlockDef def = BLOCK_DEFS[cells[index]];
def.createFaces(world, world.camPosition, Vector3d(pos.x + x, pos.y + y, pos.z + z), visibleFaces, _minerMesh);
}
index++;
}
}
}
}
if (!_minerMesh.vertexCount)
return null;
return _minerMesh;
}
private void findVisibleFaces(ref ubyte[64] visibleFaceFlags) {
ulong[8] visibleFacesNorth; ulong[8] visibleFacesNorth;
ulong canPass = getSideCanPassFromMask(Dir.NORTH); ulong canPass = getSideCanPassFromMask(Dir.NORTH);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
@ -246,9 +312,10 @@ struct SmallChunk {
visibleFaces |= DirMask.MASK_UP; visibleFaces |= DirMask.MASK_UP;
if (visibleFacesDown[y] & yplanemask) if (visibleFacesDown[y] & yplanemask)
visibleFaces |= DirMask.MASK_DOWN; visibleFaces |= DirMask.MASK_DOWN;
if (visibleFaces) { visibleFaceFlags[calcIndex(x, y, z)] = cast(ubyte)visibleFaces;
visitor.visit(x, y, z, getCell(x, y, z), visibleFaces); //if (visibleFaces) {
} // visitor.visit(pos.x + x, pos.y + y, pos.z + z, getCell(x, y, z), visibleFaces);
//}
} }
} }
} }
@ -328,7 +395,9 @@ struct SmallChunk {
dirty = false; dirty = false;
empty = (visiblePlanesZ[0]|visiblePlanesZ[1]|visiblePlanesZ[2]|visiblePlanesZ[3]| empty = (visiblePlanesZ[0]|visiblePlanesZ[1]|visiblePlanesZ[2]|visiblePlanesZ[3]|
visiblePlanesZ[4]|visiblePlanesZ[5]|visiblePlanesZ[6]|visiblePlanesZ[7]) == 0; visiblePlanesZ[4]|visiblePlanesZ[5]|visiblePlanesZ[6]|visiblePlanesZ[7]) == 0;
dirtyMesh = true;
} }
static void spreadFlags(ulong src, ref ulong[8] planes, ref ulong[8] dst, int start, int end, ubyte spreadMask) { static void spreadFlags(ulong src, ref ulong[8] planes, ref ulong[8] dst, int start, int end, ubyte spreadMask) {
if (start < end) { if (start < end) {
for (int i = start; i <= end; ++i) { for (int i = start; i <= end; ++i) {

View File

@ -18,11 +18,21 @@ class World {
_camPosition = Position(Vector3d(0, 13, 0), Vector3d(0, 0, 1)); _camPosition = Position(Vector3d(0, 13, 0), Vector3d(0, 0, 1));
} }
~this() { ~this() {
clear();
}
void clear() {
for(int index = 0; index < _chunkStacks.length; index++) {
if (_chunkStacks[index]) {
destroy(_chunkStacks[index]);
_chunkStacks[index] = null;
}
}
} }
@property final ref Position camPosition() { return _camPosition; } @property final ref Position camPosition() { return _camPosition; }
protected ChunkStack*[CHUNKS_X * 2 * CHUNKS_Z * 2] _chunkStacks; protected ChunkStack*[CHUNKS_X * 2 * CHUNKS_Z * 2] _chunkStacks;
//pragma(msg, "stack pointers array size, Kb:"); //pragma(msg, "stack pointers array size, Kb:");
//pragma(msg, _chunkStacks.sizeof / 1024); //pragma(msg, _chunkStacks.sizeof / 1024);
final cell_t getCell(int x, int y, int z) { final cell_t getCell(int x, int y, int z) {