mirror of https://github.com/buggins/dlangui.git
porting minecraft-like voxel engine implementation for d3d example
This commit is contained in:
parent
e525e13e73
commit
73f63090f5
|
@ -10,6 +10,10 @@ import dlangui.graphics.gldrawbuf;
|
|||
import derelict.opengl3.gl3;
|
||||
import derelict.opengl3.gl;
|
||||
|
||||
import dminer.core.world;
|
||||
import dminer.core.minetypes;
|
||||
import dminer.core.blocks;
|
||||
|
||||
mixin APP_ENTRY_POINT;
|
||||
|
||||
/// entry point for dlangui based application
|
||||
|
@ -117,11 +121,15 @@ class UiWidget : VerticalLayout {
|
|||
_mesh.addCubeMesh(vec3(-i * 2 - 1.0f, -i * 2 - 1.0f, -i * 2 - 1.0f), 0.2f, vec4(1 - i / 12, i / 12, i / 12, 1));
|
||||
}
|
||||
|
||||
import dminer.core.world;
|
||||
World w = new World();
|
||||
for (int x = -100; x < 100; x++)
|
||||
for (int z = -100; z < 100; z++)
|
||||
w.setCell(x, 10, z, 1);
|
||||
Position position = Position(Vector3d(0, 13, 0), Vector3d(0, 1, 0));
|
||||
CellVisitor visitor = new TestVisitor();
|
||||
Log.d("Testing cell visitor");
|
||||
w.visitVisibleCells(position, visitor);
|
||||
destroy(w);
|
||||
}
|
||||
|
||||
/// returns true is widget is being animated - need to call animate() and redraw
|
||||
|
@ -202,6 +210,17 @@ class UiWidget : VerticalLayout {
|
|||
}
|
||||
}
|
||||
|
||||
class TestVisitor : CellVisitor {
|
||||
void newDirection(ref Position camPosition) {
|
||||
Log.d("TestVisitor.newDirection");
|
||||
}
|
||||
void visitFace(World world, ref Position camPosition, Vector3d pos, cell_t cell, Dir face) {
|
||||
Log.d("TestVisitor.visitFace ", pos, " cell=", cell, " face=", face);
|
||||
}
|
||||
void visit(World world, ref Position camPosition, Vector3d pos, cell_t cell, int visibleFaces) {
|
||||
Log.d("TestVisitor.visit ", pos, " cell=", cell);
|
||||
}
|
||||
}
|
||||
|
||||
// Simple texture + color shader
|
||||
class MyGLProgram : GLProgram {
|
||||
|
|
|
@ -2,67 +2,65 @@ module dminer.core.blocks;
|
|||
|
||||
import dminer.core.minetypes;
|
||||
|
||||
/*
|
||||
#define BLOCK_TEXTURE_FILENAME "res/png/blocks.png"
|
||||
#define BLOCK_TEXTURE_DX 1024
|
||||
#define BLOCK_TEXTURE_DY 1024
|
||||
#define BLOCK_SPRITE_SIZE 16
|
||||
#define BLOCK_SPRITE_STEP 20
|
||||
#define BLOCK_SPRITE_OFFSET 21
|
||||
#define BLOCK_TEXTURE_SPRITES_PER_LINE 50
|
||||
immutable string BLOCK_TEXTURE_FILENAME = "blocks";
|
||||
immutable int BLOCK_TEXTURE_DX = 1024;
|
||||
immutable int BLOCK_TEXTURE_DY = 1024;
|
||||
immutable int BLOCK_SPRITE_SIZE = 16;
|
||||
immutable int BLOCK_SPRITE_STEP = 20;
|
||||
immutable int BLOCK_SPRITE_OFFSET = 21;
|
||||
immutable int BLOCK_TEXTURE_SPRITES_PER_LINE = 50;
|
||||
|
||||
*/
|
||||
enum BlockVisibility {
|
||||
INVISIBLE,
|
||||
OPAQUE, // completely opaque (cells covered by this block are invisible)
|
||||
OPAQUE_SEPARATE_TX,
|
||||
HALF_OPAQUE, // partially paque, cells covered by this block can be visible, render as normal block
|
||||
HALF_OPAQUE_SEPARATE_TX,
|
||||
HALF_TRANSPARENT, // should be rendered last (semi transparent texture)
|
||||
};
|
||||
INVISIBLE,
|
||||
OPAQUE, // completely opaque (cells covered by this block are invisible)
|
||||
OPAQUE_SEPARATE_TX,
|
||||
HALF_OPAQUE, // partially paque, cells covered by this block can be visible, render as normal block
|
||||
HALF_OPAQUE_SEPARATE_TX,
|
||||
HALF_TRANSPARENT, // should be rendered last (semi transparent texture)
|
||||
}
|
||||
|
||||
class BlockDef {
|
||||
public:
|
||||
cell_t id;
|
||||
string name;
|
||||
BlockVisibility visibility = BlockVisibility.INVISIBLE;
|
||||
int txIndex;
|
||||
this() {
|
||||
}
|
||||
this(cell_t blockId, string blockName, BlockVisibility v, int tx) {
|
||||
cell_t id;
|
||||
string name;
|
||||
BlockVisibility visibility = BlockVisibility.INVISIBLE;
|
||||
int txIndex;
|
||||
this() {
|
||||
}
|
||||
this(cell_t blockId, string blockName, BlockVisibility v, int tx) {
|
||||
id = blockId;
|
||||
name = blockName;
|
||||
visibility = v;
|
||||
txIndex = tx;
|
||||
}
|
||||
~this() {
|
||||
}
|
||||
// blocks behind this block can be visible
|
||||
@property bool canPass() {
|
||||
return visibility == BlockVisibility.INVISIBLE
|
||||
|| visibility == BlockVisibility.HALF_OPAQUE
|
||||
|| visibility == BlockVisibility.HALF_OPAQUE_SEPARATE_TX
|
||||
|| visibility == BlockVisibility.HALF_TRANSPARENT;
|
||||
}
|
||||
// block is fully opaque (all blocks behind are invisible)
|
||||
@property bool isOpaque() {
|
||||
return visibility == BlockVisibility.OPAQUE
|
||||
|| visibility == BlockVisibility.OPAQUE_SEPARATE_TX;
|
||||
}
|
||||
// block is visible
|
||||
@property bool isVisible() {
|
||||
return visibility != BlockVisibility.INVISIBLE;
|
||||
}
|
||||
~this() {
|
||||
}
|
||||
// blocks behind this block can be visible
|
||||
@property bool canPass() {
|
||||
return visibility == BlockVisibility.INVISIBLE
|
||||
|| visibility == BlockVisibility.HALF_OPAQUE
|
||||
|| visibility == BlockVisibility.HALF_OPAQUE_SEPARATE_TX
|
||||
|| visibility == BlockVisibility.HALF_TRANSPARENT;
|
||||
}
|
||||
// block is fully opaque (all blocks behind are invisible)
|
||||
@property bool isOpaque() {
|
||||
return visibility == BlockVisibility.OPAQUE
|
||||
|| visibility == BlockVisibility.OPAQUE_SEPARATE_TX;
|
||||
}
|
||||
// block is visible
|
||||
@property bool isVisible() {
|
||||
return visibility != BlockVisibility.INVISIBLE;
|
||||
}
|
||||
|
||||
@property bool terrainSmoothing() {
|
||||
return false;
|
||||
}
|
||||
@property bool terrainSmoothing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// create cube face
|
||||
//void createFace(World * world, Position & camPosition, Vector3d pos, Dir face, FloatArray & vertices, IntArray & indexes) {
|
||||
/// create cube face
|
||||
//void createFace(World * world, Position & camPosition, Vector3d pos, Dir face, FloatArray & vertices, IntArray & indexes) {
|
||||
//}
|
||||
/// create faces
|
||||
//void createFaces(World * world, Position & camPosition, Vector3d pos, int visibleFaces, FloatArray & vertices, IntArray & indexes) {
|
||||
/// create faces
|
||||
//void createFaces(World * world, Position & camPosition, Vector3d pos, int visibleFaces, FloatArray & vertices, IntArray & indexes) {
|
||||
//}
|
||||
}
|
||||
|
||||
|
@ -105,5 +103,26 @@ __gshared static this() {
|
|||
BLOCK_TYPE_VISIBLE[BOUND_SKY] = false;
|
||||
BLOCK_TYPE_CAN_PASS[BOUND_BOTTOM] = false;
|
||||
BLOCK_TYPE_VISIBLE[BOUND_BOTTOM] = true;
|
||||
}
|
||||
|
||||
// empty cell
|
||||
registerBlockType(new BlockDef(0, "empty", BlockVisibility.INVISIBLE, 0));
|
||||
// standard block types
|
||||
registerBlockType(new BlockDef(1, "gray_brick", BlockVisibility.OPAQUE, 0));
|
||||
registerBlockType(new BlockDef(2, "brick", BlockVisibility.OPAQUE, 1));
|
||||
registerBlockType(new BlockDef(3, "bedrock", BlockVisibility.OPAQUE, 2));
|
||||
registerBlockType(new BlockDef(4, "clay", BlockVisibility.OPAQUE, 3));
|
||||
registerBlockType(new BlockDef(5, "cobblestone", BlockVisibility.OPAQUE, 4));
|
||||
registerBlockType(new BlockDef(6, "gravel", BlockVisibility.OPAQUE, 5));
|
||||
registerBlockType(new BlockDef(7, "red_sand", BlockVisibility.OPAQUE, 6));
|
||||
registerBlockType(new BlockDef(8, "sand", BlockVisibility.OPAQUE, 7));
|
||||
|
||||
registerBlockType(new BlockDef(50, "box", BlockVisibility.HALF_OPAQUE, 50));
|
||||
|
||||
//registerBlockType(new TerrainBlock(100, "terrain_bedrock", 2));
|
||||
//registerBlockType(new TerrainBlock(101, "terrain_clay", 3));
|
||||
//registerBlockType(new TerrainBlock(102, "terrain_cobblestone", 4));
|
||||
//registerBlockType(new TerrainBlock(103, "terrain_gravel", 5));
|
||||
//registerBlockType(new TerrainBlock(104, "terrain_red_sand", 6));
|
||||
//registerBlockType(new TerrainBlock(105, "terrain_sand", 7));
|
||||
|
||||
}
|
||||
|
|
|
@ -173,8 +173,8 @@ struct Vector3d {
|
|||
int opBinary(string op : "*")(const Vector3d v) const {
|
||||
return x*v.x + y*v.y + z*v.z;
|
||||
}
|
||||
///
|
||||
int opBinary(string op : "*")(int n) const {
|
||||
/// multiply vector elements by constant
|
||||
Vector3d opBinary(string op : "*")(int n) const {
|
||||
return Vector3d(x * n, y * n, z * n);
|
||||
}
|
||||
|
||||
|
@ -183,21 +183,21 @@ struct Vector3d {
|
|||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
///
|
||||
ref Vector3d opOpAssign(string op : "-")(const Vector3d v) {
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
z -= v.z;
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
///
|
||||
ref Vector3d opOpAssign(string op : "*")(int n) {
|
||||
x *= n;
|
||||
y *= n;
|
||||
z *= n;
|
||||
return *this;
|
||||
return this;
|
||||
}
|
||||
Vector3d turnLeft() {
|
||||
return Vector3d(z, y, -x);
|
||||
|
@ -237,7 +237,8 @@ struct Vector3d {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const Vector3d ZERO3 = Vector3d(0, 0, 0);
|
||||
|
||||
struct Array(T) {
|
||||
|
@ -271,14 +272,26 @@ public:
|
|||
@property int length() {
|
||||
return _length;
|
||||
}
|
||||
/// append single item by ref
|
||||
void append(ref const T value) {
|
||||
if (_length >= _data.length)
|
||||
reserve(_data.length == 0 ? 64 : _data.length * 2 - _length);
|
||||
_data[_length++] = value;
|
||||
}
|
||||
/// append single item by value
|
||||
void append(T value) {
|
||||
if (_length >= _data.length)
|
||||
reserve(_data.length == 0 ? 64 : _data.length * 2 - _length);
|
||||
_data[_length++] = value;
|
||||
}
|
||||
/// append single item w/o check
|
||||
void appendNoCheck(ref const T value) {
|
||||
_data[_length++] = value;
|
||||
}
|
||||
/// append single item w/o check
|
||||
void appendNoCheck(T value) {
|
||||
_data[_length++] = value;
|
||||
}
|
||||
/// appends same value several times, return pointer to appended items
|
||||
T* append(ref const T value, int count) {
|
||||
reserve(count);
|
||||
|
@ -287,6 +300,14 @@ public:
|
|||
_data[_length++] = value;
|
||||
return _data.ptr + startLen;
|
||||
}
|
||||
/// appends same value several times, return pointer to appended items
|
||||
T* append(T value, int count) {
|
||||
reserve(count);
|
||||
int startLen = _length;
|
||||
for (int i = 0; i < count; i++)
|
||||
_data[_length++] = value;
|
||||
return _data.ptr + startLen;
|
||||
}
|
||||
void clear() {
|
||||
_length = 0;
|
||||
}
|
||||
|
@ -443,221 +464,33 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/+
|
||||
template<typename T, T initValue, void(*disposeFunction)(T value) > struct InfiniteArray {
|
||||
private:
|
||||
T * data;
|
||||
int size;
|
||||
int minIdx;
|
||||
int maxIdx;
|
||||
void resize(int sz) {
|
||||
if (sz < 128)
|
||||
sz = 128;
|
||||
else
|
||||
sz = sz * 2;
|
||||
if (size < sz) {
|
||||
data = (T*)realloc(data, sizeof(T) * sz);
|
||||
for (int i = size; i < sz; i++)
|
||||
data[i] = initValue;
|
||||
size = sz;
|
||||
}
|
||||
}
|
||||
public:
|
||||
int minIndex() {
|
||||
return minIdx;
|
||||
}
|
||||
int maxIndex() {
|
||||
return maxIdx;
|
||||
}
|
||||
void set(int index, T value) {
|
||||
int idx = index < 0 ? (-index) * 2 - 1 : index * 2;
|
||||
resize(idx + 1);
|
||||
T oldData = data[idx];
|
||||
if (oldData != initValue)
|
||||
disposeFunction(oldData);
|
||||
data[idx] = value;
|
||||
if (minIdx > index)
|
||||
minIdx = index;
|
||||
if (maxIdx < index + 1)
|
||||
maxIdx = index + 1;
|
||||
}
|
||||
T get(int index) {
|
||||
if (index < minIdx || index >= maxIdx)
|
||||
return initValue;
|
||||
int idx = index < 0 ? (-index) * 2 - 1 : index * 2;
|
||||
return data[idx];
|
||||
}
|
||||
InfiniteArray() : data(NULL), size(0), minIdx(0), maxIdx(0) {
|
||||
}
|
||||
~InfiniteArray() {
|
||||
if (data) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (data[i] != initValue)
|
||||
disposeFunction(data[i]);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
data = NULL;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// returns opposite direction to specified direction
|
||||
Dir opposite(Dir d) {
|
||||
return (Dir)(d ^ 1);
|
||||
}
|
||||
|
||||
Dir turnLeft(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return SOUTH;
|
||||
case EAST:
|
||||
return NORTH;
|
||||
default:
|
||||
case NORTH:
|
||||
return WEST;
|
||||
case SOUTH:
|
||||
return EAST;
|
||||
case UP:
|
||||
return SOUTH;
|
||||
case DOWN:
|
||||
return NORTH;
|
||||
}
|
||||
}
|
||||
|
||||
Dir turnRight(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return NORTH;
|
||||
case EAST:
|
||||
return SOUTH;
|
||||
default:
|
||||
case NORTH:
|
||||
return EAST;
|
||||
case SOUTH:
|
||||
return WEST;
|
||||
case UP:
|
||||
return NORTH;
|
||||
case DOWN:
|
||||
return SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
Dir turnUp(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return UP;
|
||||
case EAST:
|
||||
return UP;
|
||||
default:
|
||||
case NORTH:
|
||||
return UP;
|
||||
case SOUTH:
|
||||
return UP;
|
||||
case UP:
|
||||
return SOUTH;
|
||||
case DOWN:
|
||||
return NORTH;
|
||||
}
|
||||
}
|
||||
|
||||
Dir turnDown(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return DOWN;
|
||||
case EAST:
|
||||
return DOWN;
|
||||
default:
|
||||
case NORTH:
|
||||
return DOWN;
|
||||
case SOUTH:
|
||||
return DOWN;
|
||||
case UP:
|
||||
return NORTH;
|
||||
case DOWN:
|
||||
return SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Direction {
|
||||
this(int x, int y, int z) {
|
||||
set(x, y, z);
|
||||
}
|
||||
this(Vector3d v) {
|
||||
set(v);
|
||||
}
|
||||
this(Dir d) {
|
||||
set(d);
|
||||
}
|
||||
this() {
|
||||
set(0, 0, -1);
|
||||
}
|
||||
/// set by direction code
|
||||
void set(Dir d);
|
||||
/// set by vector
|
||||
void set(int x, int y, int z);
|
||||
/// set by vector
|
||||
void set(Vector3d v) { set(v.x, v.y, v.z); }
|
||||
|
||||
void turnLeft() {
|
||||
set(::turnLeft(dir));
|
||||
}
|
||||
void turnRight() {
|
||||
set(::turnRight(dir));
|
||||
}
|
||||
void turnUp() {
|
||||
set(::turnUp(dir));
|
||||
}
|
||||
void turnDown() {
|
||||
set(::turnDown(dir));
|
||||
}
|
||||
|
||||
Dir dir;
|
||||
Vector3d forward;
|
||||
Vector3d up;
|
||||
Vector3d right;
|
||||
Vector3d left;
|
||||
Vector3d down;
|
||||
Vector3d forwardUp;
|
||||
Vector3d forwardDown;
|
||||
Vector3d forwardLeft;
|
||||
Vector3d forwardLeftUp;
|
||||
Vector3d forwardLeftDown;
|
||||
Vector3d forwardRight;
|
||||
Vector3d forwardRightUp;
|
||||
Vector3d forwardRightDown;
|
||||
};
|
||||
|
||||
struct Position {
|
||||
Vector3d pos;
|
||||
Direction direction;
|
||||
Position() {
|
||||
|
||||
this(ref Position p) {
|
||||
pos = p.pos;
|
||||
direction = p.direction;
|
||||
}
|
||||
Position(Position & p) : pos(p.pos), direction(p.direction) {
|
||||
|
||||
}
|
||||
Position(Vector3d position, Vector3d dir) : pos(position), direction(dir) {
|
||||
|
||||
this(Vector3d position, Vector3d dir) {
|
||||
pos = position;
|
||||
direction = dir;
|
||||
}
|
||||
Vector2d calcPlaneCoords(Vector3d v) {
|
||||
v = v - pos;
|
||||
switch (direction.dir) {
|
||||
default:
|
||||
case NORTH:
|
||||
return Vector2d(v.x, v.y);
|
||||
case SOUTH:
|
||||
return Vector2d(-v.x, v.y);
|
||||
case EAST:
|
||||
return Vector2d(v.z, v.y);
|
||||
case WEST:
|
||||
return Vector2d(-v.z, v.y);
|
||||
case UP:
|
||||
return Vector2d(-v.z, v.x);
|
||||
case DOWN:
|
||||
return Vector2d(v.z, v.x);
|
||||
default:
|
||||
case NORTH:
|
||||
return Vector2d(v.x, v.y);
|
||||
case SOUTH:
|
||||
return Vector2d(-v.x, v.y);
|
||||
case EAST:
|
||||
return Vector2d(v.z, v.y);
|
||||
case WEST:
|
||||
return Vector2d(-v.z, v.y);
|
||||
case UP:
|
||||
return Vector2d(-v.z, v.x);
|
||||
case DOWN:
|
||||
return Vector2d(v.z, v.x);
|
||||
}
|
||||
}
|
||||
void turnLeft() {
|
||||
|
@ -678,154 +511,220 @@ struct Position {
|
|||
void backward(int step = 1) {
|
||||
pos -= direction.forward * step;
|
||||
}
|
||||
};
|
||||
|
||||
struct CellToVisit {
|
||||
union {
|
||||
struct {
|
||||
int index;
|
||||
cell_t cell;
|
||||
ubyte dir;
|
||||
};
|
||||
ulong data;
|
||||
};
|
||||
CellToVisit() : data(0) {}
|
||||
CellToVisit(int idx, cell_t cellValue, DirEx direction) : index(idx), cell(cellValue), dir(direction) {}
|
||||
CellToVisit(const CellToVisit & v) : data(v.data) {}
|
||||
CellToVisit(lUInt64 v) : data(v) {}
|
||||
inline CellToVisit& operator = (CellToVisit v) {
|
||||
data = v.data;
|
||||
return *this;
|
||||
}
|
||||
inline CellToVisit& operator = (lUInt64 v) {
|
||||
data = v;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct VolumeData {
|
||||
int MAX_DIST_BITS;
|
||||
int ROW_BITS;
|
||||
int MAX_DIST;
|
||||
int ROW_SIZE;
|
||||
int DATA_SIZE;
|
||||
int ROW_MASK;
|
||||
cell_t * _data;
|
||||
int directionDelta[64];
|
||||
int directionExDelta[26];
|
||||
int mainDirectionDeltas[6][9];
|
||||
int mainDirectionDeltasNoForward[6][9];
|
||||
VolumeData(int distBits);
|
||||
~VolumeData() {
|
||||
delete[] _data;
|
||||
}
|
||||
int size() { return MAX_DIST; }
|
||||
void clear() {
|
||||
memset(_data, 0, sizeof(cell_t) * DATA_SIZE);
|
||||
}
|
||||
|
||||
cell_t * ptr() { return _data; }
|
||||
|
||||
/// put cell w/o bounds checking, (0,0,0) is center of array
|
||||
inline void put(Vector3d v, cell_t cell) {
|
||||
_data[((v.y + MAX_DIST) << (ROW_BITS * 2)) | ((v.z + MAX_DIST) << ROW_BITS) | (v.x + MAX_DIST)] = cell;
|
||||
}
|
||||
|
||||
/// v is zero based destination coordinates
|
||||
void putLayer(Vector3d v, cell_t * layer, int dx, int dz, int stripe);
|
||||
|
||||
/// put cell w/o bounds checking
|
||||
inline void put(int index, cell_t cell) {
|
||||
_data[index] = cell;
|
||||
}
|
||||
|
||||
/// read w/o bounds checking, (0,0,0) is center of array
|
||||
inline cell_t get(Vector3d v) {
|
||||
return _data[((v.y + MAX_DIST) << (ROW_BITS * 2)) | ((v.z + MAX_DIST) << ROW_BITS) | (v.x + MAX_DIST)];
|
||||
}
|
||||
|
||||
inline cell_t get(int index) {
|
||||
return _data[index];
|
||||
}
|
||||
|
||||
/// get array index for point - (0,0,0) is center
|
||||
inline int getIndex(Vector3d v) {
|
||||
return ((v.y + MAX_DIST) << (ROW_BITS * 2)) | ((v.z + MAX_DIST) << ROW_BITS) | (v.x + MAX_DIST);
|
||||
}
|
||||
|
||||
inline Vector3d indexToPoint(int index) {
|
||||
return Vector3d((index & ROW_MASK) - MAX_DIST,
|
||||
((index >> (ROW_BITS * 2)) & ROW_MASK) - MAX_DIST,
|
||||
((index >> (ROW_BITS)) & ROW_MASK) - MAX_DIST);
|
||||
}
|
||||
|
||||
inline int moveIndex(int oldIndex, DirMask direction) {
|
||||
return oldIndex + directionDelta[direction];
|
||||
}
|
||||
|
||||
inline int moveIndex(int oldIndex, DirEx direction) {
|
||||
return oldIndex + directionExDelta[direction];
|
||||
}
|
||||
|
||||
inline CellToVisit getNext(int index, DirEx direction, DirEx baseDir) {
|
||||
int nextIndex = index + directionExDelta[direction];
|
||||
return CellToVisit(nextIndex, _data[nextIndex], baseDir);
|
||||
}
|
||||
|
||||
void getNearCellsForDirection(int index, DirEx direction, CellToVisit cells[9]);
|
||||
void getNearCellsForDirectionNoForward(int index, DirEx direction, CellToVisit cells[9]);
|
||||
void getNearCellsForDirection(int index, DirEx direction, cell_t cells[9]);
|
||||
void getNearCellsForDirectionNoForward(int index, DirEx direction, cell_t cells[9]);
|
||||
|
||||
void fillLayer(int y, cell_t cell);
|
||||
|
||||
int * thisPlaneDirections(DirEx dir) { return mainDirectionDeltasNoForward[dir]; }
|
||||
int * nextPlaneDirections(DirEx dir) { return mainDirectionDeltas[dir]; }
|
||||
};
|
||||
|
||||
|
||||
struct DirectionHelper {
|
||||
DirEx dir;
|
||||
IntArray oldcells;
|
||||
IntArray newcells;
|
||||
IntArray spreadcells;
|
||||
int forwardCellCount;
|
||||
void start(int index, DirEx direction);
|
||||
void nextDistance();
|
||||
void prepareSpreading();
|
||||
};
|
||||
|
||||
class World;
|
||||
class CellVisitor {
|
||||
public:
|
||||
virtual ~CellVisitor() {}
|
||||
virtual void newDirection(Position & camPosition) { }
|
||||
virtual void visitFace(World * world, Position & camPosition, Vector3d pos, cell_t cell, Dir face) { }
|
||||
virtual void visit(World * world, Position & camPosition, Vector3d pos, cell_t cell, int visibleFaces) { }
|
||||
}
|
||||
|
||||
struct VolumeVisitor {
|
||||
World * world;
|
||||
VolumeData * volume;
|
||||
CellVisitor * visitor;
|
||||
Position * position;
|
||||
DirectionHelper helpers[6];
|
||||
DirEx direction; // camera forward direction
|
||||
DirEx oppdirection; // opposite direction
|
||||
Vector3d dirvector;
|
||||
int distance;
|
||||
VolumeVisitor();
|
||||
void init(World * w, Position * pos, VolumeData * data, CellVisitor * v);
|
||||
~VolumeVisitor();
|
||||
bool visitCell(int index, cell_t cell);
|
||||
void appendNewCell(int index, int distance);
|
||||
void visitPlaneForward(int startIndex, DirEx direction);
|
||||
// move in forward direction
|
||||
void visitPlaneSpread(int startIndex, DirEx direction);
|
||||
|
||||
void visitAll();
|
||||
/// returns opposite direction to specified direction
|
||||
Dir opposite(Dir d) {
|
||||
return cast(Dir)(d ^ 1);
|
||||
}
|
||||
|
||||
Dir turnLeft(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return SOUTH;
|
||||
case EAST:
|
||||
return NORTH;
|
||||
default:
|
||||
case NORTH:
|
||||
return WEST;
|
||||
case SOUTH:
|
||||
return EAST;
|
||||
case UP:
|
||||
return SOUTH;
|
||||
case DOWN:
|
||||
return NORTH;
|
||||
}
|
||||
}
|
||||
|
||||
Dir turnRight(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return NORTH;
|
||||
case EAST:
|
||||
return SOUTH;
|
||||
default:
|
||||
case NORTH:
|
||||
return EAST;
|
||||
case SOUTH:
|
||||
return WEST;
|
||||
case UP:
|
||||
return NORTH;
|
||||
case DOWN:
|
||||
return SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
Dir turnUp(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return UP;
|
||||
case EAST:
|
||||
return UP;
|
||||
default:
|
||||
case NORTH:
|
||||
return UP;
|
||||
case SOUTH:
|
||||
return UP;
|
||||
case UP:
|
||||
return SOUTH;
|
||||
case DOWN:
|
||||
return NORTH;
|
||||
}
|
||||
}
|
||||
|
||||
Dir turnDown(Dir d) {
|
||||
switch (d) {
|
||||
case WEST:
|
||||
return DOWN;
|
||||
case EAST:
|
||||
return DOWN;
|
||||
default:
|
||||
case NORTH:
|
||||
return DOWN;
|
||||
case SOUTH:
|
||||
return DOWN;
|
||||
case UP:
|
||||
return NORTH;
|
||||
case DOWN:
|
||||
return SOUTH;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Direction {
|
||||
this(int x, int y, int z) {
|
||||
set(x, y, z);
|
||||
}
|
||||
this(Vector3d v) {
|
||||
set(v);
|
||||
}
|
||||
this(Dir d) {
|
||||
set(d);
|
||||
}
|
||||
/// set by direction code
|
||||
void set(Dir d) {
|
||||
switch (d) {
|
||||
default:
|
||||
case NORTH:
|
||||
set(0, 0, -1);
|
||||
break;
|
||||
case SOUTH:
|
||||
set(0, 0, 1);
|
||||
break;
|
||||
case WEST:
|
||||
set(-1, 0, 0);
|
||||
break;
|
||||
case EAST:
|
||||
set(1, 0, 0);
|
||||
break;
|
||||
case UP:
|
||||
set(0, 1, 0);
|
||||
break;
|
||||
case DOWN:
|
||||
set(0, -1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/// set by vector
|
||||
void set(Vector3d v) { set(v.x, v.y, v.z); }
|
||||
/// set by vector
|
||||
void set(int x, int y, int z) {
|
||||
forward = Vector3d(x, y, z);
|
||||
if (x) {
|
||||
dir = (x > 0) ? EAST : WEST;
|
||||
}
|
||||
else if (y) {
|
||||
dir = (y > 0) ? UP : DOWN;
|
||||
}
|
||||
else {
|
||||
dir = (z > 0) ? SOUTH : NORTH;
|
||||
}
|
||||
switch (dir) {
|
||||
case UP:
|
||||
up = Vector3d(1, 0, 0);
|
||||
left = Vector3d(0, 0, 1);
|
||||
break;
|
||||
case DOWN:
|
||||
up = Vector3d(1, 0, 0);
|
||||
left = Vector3d(0, 0, -1);
|
||||
break;
|
||||
default:
|
||||
case NORTH:
|
||||
up = Vector3d(0, 1, 0);
|
||||
left = Vector3d(-1, 0, 0);
|
||||
break;
|
||||
case SOUTH:
|
||||
up = Vector3d(0, 1, 0);
|
||||
left = Vector3d(1, 0, 0);
|
||||
break;
|
||||
case EAST:
|
||||
up = Vector3d(0, 1, 0);
|
||||
left = Vector3d(0, 0, -1);
|
||||
break;
|
||||
case WEST:
|
||||
up = Vector3d(0, 1, 0);
|
||||
left = Vector3d(0, 0, 1);
|
||||
break;
|
||||
}
|
||||
down = -up;
|
||||
right = -left;
|
||||
forwardUp = forward + up;
|
||||
forwardDown = forward + down;
|
||||
forwardLeft = forward + left;
|
||||
forwardLeftUp = forward + left + up;
|
||||
forwardLeftDown = forward + left + down;
|
||||
forwardRight = forward + right;
|
||||
forwardRightUp = forward + right + up;
|
||||
forwardRightDown = forward + right + down;
|
||||
}
|
||||
|
||||
void turnLeft() {
|
||||
set(.turnLeft(dir));
|
||||
}
|
||||
void turnRight() {
|
||||
set(.turnRight(dir));
|
||||
}
|
||||
void turnUp() {
|
||||
set(.turnUp(dir));
|
||||
}
|
||||
void turnDown() {
|
||||
set(.turnDown(dir));
|
||||
}
|
||||
|
||||
Dir dir;
|
||||
Vector3d forward;
|
||||
Vector3d up;
|
||||
Vector3d right;
|
||||
Vector3d left;
|
||||
Vector3d down;
|
||||
Vector3d forwardUp;
|
||||
Vector3d forwardDown;
|
||||
Vector3d forwardLeft;
|
||||
Vector3d forwardLeftUp;
|
||||
Vector3d forwardLeftDown;
|
||||
Vector3d forwardRight;
|
||||
Vector3d forwardRightUp;
|
||||
Vector3d forwardRightDown;
|
||||
}
|
||||
|
||||
/// returns number of bits to store integer
|
||||
int bitsFor(int n) {
|
||||
int res;
|
||||
for (res = 0; n > 0; res++)
|
||||
n >>= 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// returns 0 for 0, 1 for negatives, 2 for positives
|
||||
int mySign(int n) {
|
||||
if (n > 0)
|
||||
return 1;
|
||||
else if (n < 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
+/
|
||||
|
||||
immutable ulong RANDOM_MULTIPLIER = ((cast(ulong)1 << 48) - 1);
|
||||
immutable ulong RANDOM_MASK = ((cast(ulong)1 << 48) - 1);
|
||||
|
@ -849,4 +748,11 @@ struct Random {
|
|||
int nextInt(int n);
|
||||
}
|
||||
|
||||
extern const Vector3d DIRECTION_VECTORS[6];
|
||||
const Vector3d DIRECTION_VECTORS[6] = [
|
||||
Vector3d(0, 0, -1),
|
||||
Vector3d(0, 0, 1),
|
||||
Vector3d(-1, 0, 0),
|
||||
Vector3d(1, 0, 0),
|
||||
Vector3d(0, 1, 0),
|
||||
Vector3d(0, -1, 0)
|
||||
];
|
||||
|
|
|
@ -20,115 +20,114 @@ immutable int CHUNK_DY_MASK = (CHUNK_DY - 1);
|
|||
// Layer is 256x16x16 CHUNK_DY layers = CHUNK_DY * (CHUNK_DX_SHIFT x CHUNK_DX_SHIFT) cells
|
||||
struct ChunkLayer {
|
||||
private:
|
||||
cell_t cells[CHUNK_DX * CHUNK_DX];
|
||||
cell_t cells[CHUNK_DX * CHUNK_DX];
|
||||
public:
|
||||
cell_t* ptr(int x, int z) {
|
||||
return &cells[(z << CHUNK_DX_SHIFT) + x];
|
||||
}
|
||||
cell_t get(int x, int z) {
|
||||
return cells[(z << CHUNK_DX_SHIFT) + x];
|
||||
}
|
||||
void set(int x, int z, cell_t cell) {
|
||||
cells[(z << CHUNK_DX_SHIFT) + x] = cell;
|
||||
}
|
||||
cell_t* ptr(int x, int z) {
|
||||
return &cells[(z << CHUNK_DX_SHIFT) + x];
|
||||
}
|
||||
cell_t get(int x, int z) {
|
||||
return cells[(z << CHUNK_DX_SHIFT) + x];
|
||||
}
|
||||
void set(int x, int z, cell_t cell) {
|
||||
cells[(z << CHUNK_DX_SHIFT) + x] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
struct Chunk {
|
||||
private:
|
||||
ChunkLayer * layers[CHUNK_DY];
|
||||
int bottomLayer = - 1;
|
||||
int topLayer = -1;
|
||||
ChunkLayer * layers[CHUNK_DY];
|
||||
int bottomLayer = - 1;
|
||||
int topLayer = -1;
|
||||
public:
|
||||
~this() {
|
||||
for (int i = 0; i < CHUNK_DY; i++)
|
||||
if (layers[i])
|
||||
destroy(layers[i]);
|
||||
}
|
||||
int getMinLayer() { return bottomLayer; }
|
||||
int getMaxLayer() { return topLayer; }
|
||||
void updateMinMaxLayer(ref int minLayer, ref int maxLayer) {
|
||||
if (minLayer == -1 || minLayer > bottomLayer)
|
||||
minLayer = bottomLayer;
|
||||
if (maxLayer == -1 || maxLayer < topLayer)
|
||||
maxLayer = topLayer;
|
||||
}
|
||||
cell_t get(int x, int y, int z) {
|
||||
//if (!this)
|
||||
// return NO_CELL;
|
||||
ChunkLayer * layer = layers[y & CHUNK_DY_MASK];
|
||||
if (!layer)
|
||||
return NO_CELL;
|
||||
return layer.get(x & CHUNK_DX_MASK, z & CHUNK_DY_MASK);
|
||||
}
|
||||
void set(int x, int y, int z, cell_t cell) {
|
||||
int layerIndex = y & CHUNK_DY_MASK;
|
||||
ChunkLayer * layer = layers[layerIndex];
|
||||
if (!layer) {
|
||||
layer = new ChunkLayer();
|
||||
layers[layerIndex] = layer;
|
||||
if (topLayer == -1 || topLayer < layerIndex)
|
||||
topLayer = layerIndex;
|
||||
if (bottomLayer == -1 || bottomLayer > layerIndex)
|
||||
bottomLayer = layerIndex;
|
||||
}
|
||||
layer.set(x & CHUNK_DX_MASK, z & CHUNK_DY_MASK, cell);
|
||||
}
|
||||
~this() {
|
||||
for (int i = 0; i < CHUNK_DY; i++)
|
||||
if (layers[i])
|
||||
destroy(layers[i]);
|
||||
}
|
||||
int getMinLayer() { return bottomLayer; }
|
||||
int getMaxLayer() { return topLayer; }
|
||||
void updateMinMaxLayer(ref int minLayer, ref int maxLayer) {
|
||||
if (minLayer == -1 || minLayer > bottomLayer)
|
||||
minLayer = bottomLayer;
|
||||
if (maxLayer == -1 || maxLayer < topLayer)
|
||||
maxLayer = topLayer;
|
||||
}
|
||||
cell_t get(int x, int y, int z) {
|
||||
//if (!this)
|
||||
// return NO_CELL;
|
||||
ChunkLayer * layer = layers[y & CHUNK_DY_MASK];
|
||||
if (!layer)
|
||||
return NO_CELL;
|
||||
return layer.get(x & CHUNK_DX_MASK, z & CHUNK_DY_MASK);
|
||||
}
|
||||
void set(int x, int y, int z, cell_t cell) {
|
||||
int layerIndex = y & CHUNK_DY_MASK;
|
||||
ChunkLayer * layer = layers[layerIndex];
|
||||
if (!layer) {
|
||||
layer = new ChunkLayer();
|
||||
layers[layerIndex] = layer;
|
||||
if (topLayer == -1 || topLayer < layerIndex)
|
||||
topLayer = layerIndex;
|
||||
if (bottomLayer == -1 || bottomLayer > layerIndex)
|
||||
bottomLayer = layerIndex;
|
||||
}
|
||||
layer.set(x & CHUNK_DX_MASK, z & CHUNK_DY_MASK, cell);
|
||||
}
|
||||
|
||||
/// srcpos coords x, z are in chunk bounds
|
||||
//void getCells(Vector3d srcpos, Vector3d dstpos, Vector3d size, VolumeData & buf);
|
||||
/// srcpos coords x, z are in chunk bounds
|
||||
//void getCells(Vector3d srcpos, Vector3d dstpos, Vector3d size, VolumeData & buf);
|
||||
}
|
||||
|
||||
struct ChunkMatrix {
|
||||
private:
|
||||
int minx;
|
||||
int maxx;
|
||||
int minz;
|
||||
int maxz;
|
||||
InfiniteMatrix!(Chunk *) matrix;
|
||||
int minx;
|
||||
int maxx;
|
||||
int minz;
|
||||
int maxz;
|
||||
InfiniteMatrix!(Chunk *) matrix;
|
||||
public:
|
||||
@property int minX() { return minx; }
|
||||
@property int maxX() { return maxx; }
|
||||
@property int minZ() { return minz; }
|
||||
@property int maxZ() { return maxz; }
|
||||
Chunk * get(int x, int z) {
|
||||
@property int minX() { return minx; }
|
||||
@property int maxX() { return maxx; }
|
||||
@property int minZ() { return minz; }
|
||||
@property int maxZ() { return maxz; }
|
||||
Chunk * get(int x, int z) {
|
||||
return matrix.get(x, z);
|
||||
}
|
||||
void set(int x, int z, Chunk * chunk) {
|
||||
matrix.set(x, z, chunk);
|
||||
}
|
||||
void set(int x, int z, Chunk * chunk) {
|
||||
matrix.set(x, z, chunk);
|
||||
if (minz > z)
|
||||
minz = z;
|
||||
if (maxz < z + 1)
|
||||
maxz = z + 1;
|
||||
if (minx > x)
|
||||
minx = x;
|
||||
if (maxx < x + 1)
|
||||
maxx = x + 1;
|
||||
}
|
||||
if (minx > x)
|
||||
minx = x;
|
||||
if (maxx < x + 1)
|
||||
maxx = x + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Voxel World
|
||||
class World {
|
||||
private:
|
||||
//Position camPosition;
|
||||
int maxVisibleRange = MAX_VIEW_DISTANCE;
|
||||
int lastChunkX = 1000000;
|
||||
int lastChunkZ = 1000000;
|
||||
Chunk * lastChunk;
|
||||
ChunkMatrix chunks;
|
||||
//DiamondVisitor visitorHelper;
|
||||
Position camPosition;
|
||||
int maxVisibleRange = MAX_VIEW_DISTANCE;
|
||||
int lastChunkX = 1000000;
|
||||
int lastChunkZ = 1000000;
|
||||
Chunk * lastChunk;
|
||||
ChunkMatrix chunks;
|
||||
DiamondVisitor visitorHelper;
|
||||
public:
|
||||
this()
|
||||
this()
|
||||
{
|
||||
}
|
||||
~this() {
|
||||
~this() {
|
||||
|
||||
}
|
||||
//void visitVisibleCellsAllDirectionsFast(Position & position, CellVisitor * visitor);
|
||||
//Position & getCamPosition() { return camPosition; }
|
||||
cell_t getCell(Vector3d v) {
|
||||
return getCell(v.x, v.y, v.z);
|
||||
}
|
||||
cell_t getCell(int x, int y, int z) {
|
||||
}
|
||||
ref Position getCamPosition() { return camPosition; }
|
||||
cell_t getCell(Vector3d v) {
|
||||
return getCell(v.x, v.y, v.z);
|
||||
}
|
||||
cell_t getCell(int x, int y, int z) {
|
||||
if (y < 0)
|
||||
return 3;
|
||||
int chunkx = x >> CHUNK_DX_SHIFT;
|
||||
|
@ -146,11 +145,11 @@ public:
|
|||
return NO_CELL;
|
||||
return p.get(x & CHUNK_DX_MASK, y, z & CHUNK_DX_MASK);
|
||||
}
|
||||
bool isOpaque(Vector3d v) {
|
||||
bool isOpaque(Vector3d v) {
|
||||
cell_t cell = getCell(v);
|
||||
return BLOCK_TYPE_OPAQUE[cell] && cell != BOUND_SKY;
|
||||
}
|
||||
void setCell(int x, int y, int z, cell_t value) {
|
||||
void setCell(int x, int y, int z, cell_t value) {
|
||||
int chunkx = x >> CHUNK_DX_SHIFT;
|
||||
int chunkz = z >> CHUNK_DX_SHIFT;
|
||||
Chunk * p;
|
||||
|
@ -172,6 +171,197 @@ public:
|
|||
}
|
||||
p.set(x & CHUNK_DX_MASK, y, z & CHUNK_DX_MASK, value);
|
||||
}
|
||||
//bool canPass(Vector3d pos, Vector3d size) {
|
||||
//bool canPass(Vector3d pos, Vector3d size) {
|
||||
//}
|
||||
void visitVisibleCells(ref Position position, CellVisitor visitor) {
|
||||
visitorHelper.init(this, &position,
|
||||
visitor);
|
||||
visitorHelper.visitAll(MAX_VIEW_DISTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
interface CellVisitor {
|
||||
void newDirection(ref Position camPosition);
|
||||
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);
|
||||
}
|
||||
|
||||
struct DiamondVisitor {
|
||||
int maxDist;
|
||||
int maxDistBits;
|
||||
int dist;
|
||||
World world;
|
||||
Position * position;
|
||||
Vector3d pos0;
|
||||
CellVisitor visitor;
|
||||
CellArray visited;
|
||||
cell_t * visited_ptr;
|
||||
Vector3dArray oldcells;
|
||||
Vector3dArray newcells;
|
||||
ubyte visitedOccupied;
|
||||
ubyte visitedEmpty;
|
||||
int m0;
|
||||
int m0mask;
|
||||
void init(World w, Position * pos, CellVisitor v) {
|
||||
world = w;
|
||||
position = pos;
|
||||
visitor = v;
|
||||
pos0 = position.pos;
|
||||
}
|
||||
void visitCell(Vector3d v) {
|
||||
//CRLog::trace("visitCell(%d %d %d) dist=%d", v.x, v.y, v.z, myAbs(v.x) + myAbs(v.y) + myAbs(v.z));
|
||||
|
||||
//int occupied = visitedOccupied;
|
||||
int index = (v.x + m0) + ((v.z + m0) << (maxDistBits + 1));
|
||||
if (v.y < 0) {
|
||||
// inverse index for lower half
|
||||
index ^= m0mask;
|
||||
//m0--;
|
||||
//x ^= m0;
|
||||
//y ^= m0;
|
||||
}
|
||||
//int index = diamondIndex(v, maxDistBits);
|
||||
if (visited_ptr[index] == visitedOccupied)// || cell == visitedEmpty)
|
||||
return;
|
||||
if (v * position.direction.forward < dist / 3)
|
||||
return;
|
||||
Vector3d pos = pos0 + v;
|
||||
cell_t cell = world.getCell(pos);
|
||||
|
||||
// read cell from world
|
||||
if (BLOCK_TYPE_VISIBLE[cell]) {
|
||||
int visibleFaces = 0;
|
||||
if (v.y <= 0 && v * DIRECTION_VECTORS[DIR_UP] <= 0 &&
|
||||
!world.isOpaque(pos.move(DIR_UP)))
|
||||
visibleFaces |= MASK_UP;
|
||||
if (v.y >= 0 && v * DIRECTION_VECTORS[DIR_DOWN] <= 0 &&
|
||||
!world.isOpaque(pos.move(DIR_DOWN)))
|
||||
visibleFaces |= MASK_DOWN;
|
||||
if (v.x <= 0 && v * DIRECTION_VECTORS[DIR_EAST] <= 0 &&
|
||||
!world.isOpaque(pos.move(DIR_EAST)))
|
||||
visibleFaces |= MASK_EAST;
|
||||
if (v.x >= 0 && v * DIRECTION_VECTORS[DIR_WEST] <= 0 &&
|
||||
!world.isOpaque(pos.move(DIR_WEST)))
|
||||
visibleFaces |= MASK_WEST;
|
||||
if (v.z <= 0 && v * DIRECTION_VECTORS[DIR_SOUTH] <= 0 &&
|
||||
!world.isOpaque(pos.move(DIR_SOUTH)))
|
||||
visibleFaces |= MASK_SOUTH;
|
||||
if (v.z >= 0 && v * DIRECTION_VECTORS[DIR_NORTH] <= 0 &&
|
||||
!world.isOpaque(pos.move(DIR_NORTH)))
|
||||
visibleFaces |= MASK_NORTH;
|
||||
visitor.visit(world, *position, pos, cell, visibleFaces);
|
||||
}
|
||||
// mark as visited
|
||||
if (BLOCK_TYPE_CAN_PASS[cell])
|
||||
newcells.append(v);
|
||||
//cell = BLOCK_TYPE_CAN_PASS[cell] ? visitedEmpty : visitedOccupied;
|
||||
visited_ptr[index] = visitedOccupied; // cell;
|
||||
}
|
||||
|
||||
void visitAll(int maxDistance) {
|
||||
maxDist = maxDistance;
|
||||
maxDistBits = bitsFor(maxDist);
|
||||
|
||||
m0 = 1 << maxDistBits;
|
||||
m0mask = (m0 - 1) + ((m0 - 1) << (maxDistBits + 1));
|
||||
|
||||
oldcells.clear();
|
||||
newcells.clear();
|
||||
oldcells.reserve(maxDist * 4 * 4);
|
||||
newcells.reserve(maxDist * 4 * 4);
|
||||
|
||||
dist = 1;
|
||||
|
||||
int vsize = ((1 << maxDistBits) * (1 << maxDistBits)) << 2;
|
||||
visited.clear();
|
||||
visited.append(cast(ubyte)0, vsize);
|
||||
visited_ptr = visited.ptr();
|
||||
visitedOccupied = 2;
|
||||
visitedEmpty = 3;
|
||||
oldcells.clear();
|
||||
oldcells.append(Vector3d(0, 0, 0));
|
||||
|
||||
for (; dist < maxDistance; dist++) {
|
||||
// for each distance
|
||||
if (oldcells.length() == 0) // no cells to pass through
|
||||
break;
|
||||
newcells.clear();
|
||||
visitedOccupied += 2;
|
||||
visitedEmpty += 2;
|
||||
//CRLog::trace("dist: %d cells: %d", dist, oldcells.length());
|
||||
for (int i = 0; i < oldcells.length(); i++) {
|
||||
Vector3d pt = oldcells[i];
|
||||
int sx = mySign(pt.x);
|
||||
int sy = mySign(pt.y);
|
||||
int sz = mySign(pt.z);
|
||||
if (sx && sy && sz) {
|
||||
// 1, 1, 1
|
||||
visitCell(Vector3d(pt.x + sx, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y + sy, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + sz));
|
||||
} else {
|
||||
// has 0 in one of coords
|
||||
if (!sx) {
|
||||
if (!sy) {
|
||||
if (!sz) {
|
||||
// 0, 0, 0
|
||||
visitCell(Vector3d(pt.x + 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x - 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y + 1, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y - 1, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + 1));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z - 1));
|
||||
} else {
|
||||
// 0, 0, 1
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + sz));
|
||||
visitCell(Vector3d(pt.x + 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x - 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y + 1, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y - 1, pt.z));
|
||||
}
|
||||
} else {
|
||||
if (!sz) {
|
||||
// 0, 1, 0
|
||||
visitCell(Vector3d(pt.x, pt.y + sy, pt.z));
|
||||
visitCell(Vector3d(pt.x + 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x - 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + 1));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z - 1));
|
||||
} else {
|
||||
// 0, 1, 1
|
||||
visitCell(Vector3d(pt.x, pt.y + sy, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + sz));
|
||||
visitCell(Vector3d(pt.x + 1, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x - 1, pt.y, pt.z));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!sy) {
|
||||
if (!sz) {
|
||||
// 1, 0, 0
|
||||
visitCell(Vector3d(pt.x + sx, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y + 1, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y - 1, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + 1));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z - 1));
|
||||
} else {
|
||||
// 1, 0, 1
|
||||
visitCell(Vector3d(pt.x + sx, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + sz));
|
||||
visitCell(Vector3d(pt.x, pt.y + 1, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y - 1, pt.z));
|
||||
}
|
||||
} else {
|
||||
// 1, 1, 0
|
||||
visitCell(Vector3d(pt.x + sx, pt.y, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y + sy, pt.z));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z + 1));
|
||||
visitCell(Vector3d(pt.x, pt.y, pt.z - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newcells.swap(oldcells);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue