diff --git a/examples/d3d/d3d-msvc.visualdproj b/examples/d3d/d3d-msvc.visualdproj index a80d15b0..ed3b2e9b 100644 --- a/examples/d3d/d3d-msvc.visualdproj +++ b/examples/d3d/d3d-msvc.visualdproj @@ -411,6 +411,7 @@ + diff --git a/examples/d3d/src/d3d.d b/examples/d3d/src/d3d.d index cf216325..ca7934ef 100644 --- a/examples/d3d/src/d3d.d +++ b/examples/d3d/src/d3d.d @@ -116,6 +116,12 @@ class UiWidget : VerticalLayout { _mesh.addCubeMesh(vec3( i * 2 + 1.0f, -i * 2 + 1.0f, i * 2 + 1.0f), 0.2f, vec4(i / 12, 1 - i / 12, i / 12, 1)); _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); } /// returns true is widget is being animated - need to call animate() and redraw diff --git a/examples/d3d/src/dminer/core/blocks.d b/examples/d3d/src/dminer/core/blocks.d new file mode 100644 index 00000000..7a438ba3 --- /dev/null +++ b/examples/d3d/src/dminer/core/blocks.d @@ -0,0 +1,109 @@ +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 + +*/ +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) +}; + +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) { + 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; + } + + @property bool terrainSmoothing() { + return false; + } + + /// 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) { + //} +} + + +// block type definitions +__gshared BlockDef BLOCK_DEFS[256]; +// faster check for block->canPass() +__gshared bool BLOCK_TYPE_CAN_PASS[256]; +// faster check for block->isOpaque() +__gshared bool BLOCK_TYPE_OPAQUE[256]; +// faster check for block->isVisible() +__gshared bool BLOCK_TYPE_VISIBLE[256]; +// faster check for block->isVisible() +__gshared bool BLOCK_TERRAIN_SMOOTHING[256]; + +/// registers new block type +void registerBlockType(BlockDef def) { + if (BLOCK_DEFS[def.id]) { + if (BLOCK_DEFS[def.id] is def) + return; + destroy(BLOCK_DEFS[def.id]); + } + BLOCK_DEFS[def.id] = def; + // init property shortcuts + BLOCK_TYPE_CAN_PASS[def.id] = def.canPass; + BLOCK_TYPE_OPAQUE[def.id] = def.isOpaque; + BLOCK_TYPE_VISIBLE[def.id] = def.isVisible; + BLOCK_TERRAIN_SMOOTHING[def.id] = def.terrainSmoothing; +} + +/// init block types array +__gshared static this() { + import std.string; + for (int i = 0; i < 256; i++) { + if (!BLOCK_DEFS[i]) { + registerBlockType(new BlockDef(cast(cell_t)i, "undef%d".format(i), BlockVisibility.INVISIBLE, 0)); + } + } + BLOCK_TYPE_CAN_PASS[BOUND_SKY] = false; + BLOCK_TYPE_VISIBLE[BOUND_SKY] = false; + BLOCK_TYPE_CAN_PASS[BOUND_BOTTOM] = false; + BLOCK_TYPE_VISIBLE[BOUND_BOTTOM] = true; +} + diff --git a/examples/d3d/src/dminer/core/world.d b/examples/d3d/src/dminer/core/world.d index e62781cc..f6ad3cb9 100644 --- a/examples/d3d/src/dminer/core/world.d +++ b/examples/d3d/src/dminer/core/world.d @@ -1,6 +1,7 @@ module dminer.core.world; import dminer.core.minetypes; +import dminer.core.blocks; const int MAX_VIEW_DISTANCE_BITS = 7; const int MAX_VIEW_DISTANCE = (1 << MAX_VIEW_DISTANCE_BITS); @@ -104,3 +105,73 @@ public: 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; +public: + 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) { + if (y < 0) + return 3; + int chunkx = x >> CHUNK_DX_SHIFT; + int chunkz = z >> CHUNK_DX_SHIFT; + Chunk * p; + if (lastChunkX == chunkx && lastChunkZ == chunkz) { + p = lastChunk; + } else { + p = chunks.get(chunkx, chunkz); + lastChunkX = chunkx; + lastChunkZ = chunkz; + lastChunk = p; + } + if (!p) + return NO_CELL; + return p.get(x & CHUNK_DX_MASK, y, z & CHUNK_DX_MASK); + } + 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) { + int chunkx = x >> CHUNK_DX_SHIFT; + int chunkz = z >> CHUNK_DX_SHIFT; + Chunk * p; + if (lastChunkX == chunkx && lastChunkZ == chunkz) { + p = lastChunk; + } + else { + p = chunks.get(chunkx, chunkz); + lastChunkX = chunkx; + lastChunkZ = chunkz; + lastChunk = p; + } + if (!p) { + p = new Chunk(); + chunks.set(chunkx, chunkz, p); + lastChunkX = chunkx; + lastChunkZ = chunkz; + lastChunk = p; + } + p.set(x & CHUNK_DX_MASK, y, z & CHUNK_DX_MASK, value); + } + //bool canPass(Vector3d pos, Vector3d size) { + //} +} diff --git a/examples/example1/views/res/blocks.png b/examples/example1/views/res/blocks.png new file mode 100644 index 00000000..5a6c999b Binary files /dev/null and b/examples/example1/views/res/blocks.png differ diff --git a/examples/example1/views/resources.list b/examples/example1/views/resources.list index c767a4fe..d05c5428 100644 --- a/examples/example1/views/resources.list +++ b/examples/example1/views/resources.list @@ -16,3 +16,4 @@ res/mdpi/edit-undo.png res/mdpi/edit-unindent.png res/mdpi/tx_fabric.jpg res/theme_custom1.xml +res/blocks.png