diff --git a/examples/dminer/src/dminer/core/blocks.d b/examples/dminer/src/dminer/core/blocks.d index 9f1e8c94..6883f152 100644 --- a/examples/dminer/src/dminer/core/blocks.d +++ b/examples/dminer/src/dminer/core/blocks.d @@ -96,7 +96,7 @@ X<-----x----- private immutable float CCC = 0.5; // cell cube coordinates private immutable float TC0 = 0.0; -private immutable float TC1 = 1.0; +private immutable float TC1 = 0.99; __gshared static const float[VERTEX_COMPONENTS * 4] face_vertices_north = [ @@ -184,7 +184,7 @@ __gshared static const float[VERTEX_COMPONENTS * 4] face_vertices_down = __gshared static const ushort[6] face_indexes = [ - 2, 1, 0, 0, 3, 2 // CCW + 2, 1, 0, 0, 3, 2 // CCW ]; __gshared static const ushort[6] face_indexes_back = diff --git a/examples/dminer/src/dminer/core/chunk.d b/examples/dminer/src/dminer/core/chunk.d index 14868fe6..70837494 100644 --- a/examples/dminer/src/dminer/core/chunk.d +++ b/examples/dminer/src/dminer/core/chunk.d @@ -6,7 +6,7 @@ import dminer.core.world; import dlangui.graphics.scene.mesh; -version = FAST_VISIBILITY_PATH; +//version = FAST_VISIBILITY_PATH; // Y range: 0..CHUNK_DY-1 immutable int CHUNK_DY = 128; @@ -29,7 +29,7 @@ interface CellVisitor { } interface ChunkVisitor { - void visit(World world, SmallChunk * chunk); + bool visit(World world, SmallChunk * chunk); } // vertical stack of chunks with same X, Z, and different Y @@ -1550,13 +1550,18 @@ struct VisibilityCheckIterator { if (!mask) return; // distance test - Vector3d diff = p - camPos; + Vector3d diff = (p + Vector3d(4,4,4)) - camPos; if (diff.squaredLength() > maxDistanceSquared) return; - // direction test (TODO) - int dot = diff.dot(cameraDirection); - if (dot < 8000) - return; + int distance = diff.squaredLength; + if (distance > 10*10) { + diff = (diff * 256 + cameraDirection * 16) / 256; + //diff += cameraDirection; + // direction test (TODO) + int dot = diff.dot(cameraDirection); + if (dot < 12000) + return; + } //.... // plan visiting VisibilityCheckChunk * plan = getOrAddPlannedChunk(p); @@ -1571,7 +1576,8 @@ struct VisibilityCheckIterator { swap(visitedChunks, plannedChunks); plannedChunks.length = 0; foreach (ref p; visitedChunks) { - visitor.visit(world, p.chunk); + if (!visitor.visit(world, p.chunk)) + continue; /// set mask of spread directions p.spreadToDirMask = calcSpreadMask(p.pos, startPos); p.tracePaths(); diff --git a/examples/dminer/src/dminer/core/minetypes.d b/examples/dminer/src/dminer/core/minetypes.d index f460ffd9..d4f0f446 100644 --- a/examples/dminer/src/dminer/core/minetypes.d +++ b/examples/dminer/src/dminer/core/minetypes.d @@ -120,6 +120,10 @@ struct Vector3d { Vector3d opBinary(string op : "*")(int n) const { return Vector3d(x * n, y * n, z * n); } + /// divide vector elements by constant + Vector3d opBinary(string op : "/")(int n) const { + return Vector3d(x / n, y / n, z / n); + } /// ref Vector3d opOpAssign(string op : "+")(const Vector3d v) { diff --git a/examples/dminer/src/dminer/core/world.d b/examples/dminer/src/dminer/core/world.d index e1862622..a2fcde70 100644 --- a/examples/dminer/src/dminer/core/world.d +++ b/examples/dminer/src/dminer/core/world.d @@ -7,7 +7,7 @@ import dminer.core.chunk; version (Android) { const int MAX_VIEW_DISTANCE = 60; } else { - const int MAX_VIEW_DISTANCE = 120; + const int MAX_VIEW_DISTANCE = 180; } diff --git a/examples/dminer/src/minermain.d b/examples/dminer/src/minermain.d index 820a3359..88b56348 100644 --- a/examples/dminer/src/minermain.d +++ b/examples/dminer/src/minermain.d @@ -15,6 +15,8 @@ import dlangui.graphics.scene.effect; import dlangui.graphics.glsupport; import dlangui.graphics.gldrawbuf; +//version = TEST_VISITOR_PERFORMANCE; + /* version (Android) { //enum SUPPORT_LEGACY_OPENGL = false; @@ -62,8 +64,9 @@ extern (C) int UIAppMain(string[] args) { class ChunkVisitCounter : ChunkVisitor { int count; - void visit(World world, SmallChunk * chunk) { + bool visit(World world, SmallChunk * chunk) { count++; + return true; } } @@ -78,6 +81,10 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor { private Camera _cam; private vec3 _camPosition; private vec3 _camForwardVector; + private bool _wireframe; + + @property bool wireframe() { return _wireframe; } + @property void wireframe(bool flgWireframe) { _wireframe = flgWireframe; } this(World world, Material material, Camera cam) { super(material); @@ -94,7 +101,7 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor { _pos = _world.camPosition.pos; _camPosition = _cam.translation; _camForwardVector = _cam.forwardVectorWorld; - _camPosition -= _camForwardVector * 8; + //_camPosition -= _camForwardVector * 8; _skippedCount = _drawnCount = 0; long ts = currentTimeMillis(); //_chunkVisitor.visitChunks(_pos); @@ -102,34 +109,48 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor { camVector.x = cast(int)(_camForwardVector.x * 256); camVector.y = cast(int)(_camForwardVector.y * 256); camVector.z = cast(int)(_camForwardVector.z * 256); - ChunkVisitCounter countVisitor = new ChunkVisitCounter(); - _chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE); - _chunkIterator.visitVisibleChunks(countVisitor, camVector); - long durationNoDraw = currentTimeMillis() - ts; - _chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE); - _chunkIterator.visitVisibleChunks(this, camVector); - long duration = currentTimeMillis() - ts; - Log.d("drawing of Miner scene finished in ", duration, " ms skipped:", _skippedCount, " drawn:", _drawnCount, " duration(noDraw)=", durationNoDraw); + version (TEST_VISITOR_PERFORMANCE) { + ChunkVisitCounter countVisitor = new ChunkVisitCounter(); + _chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE); + _chunkIterator.visitVisibleChunks(countVisitor, camVector); + long durationNoDraw = currentTimeMillis() - ts; + _chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE); + _chunkIterator.visitVisibleChunks(this, camVector); + long duration = currentTimeMillis() - ts; + Log.d("drawing of Miner scene finished in ", duration, " ms skipped:", _skippedCount, " drawn:", _drawnCount, " duration(noDraw)=", durationNoDraw); + } else { + _chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE); + _chunkIterator.visitVisibleChunks(this, camVector); + long duration = currentTimeMillis() - ts; + Log.d("drawing of Miner scene finished in ", duration, " ms skipped:", _skippedCount, " drawn:", _drawnCount); + } } - void visit(World world, SmallChunk * chunk) { + bool visit(World world, SmallChunk * chunk) { if (chunk) { Vector3d p = chunk.position; vec3 chunkPos = vec3(p.x + 4, p.y + 4, p.z + 4); - vec3 chunkDirection = (chunkPos - _camPosition).normalized; + float camDist = (_camPosition - chunkPos).length; + vec3 chunkDirection = (chunkPos - (_camPosition - (_camForwardVector * 12))).normalized; float dot = _camForwardVector.dot(chunkDirection); - //Log.d("visit() chunkPos ", chunkPos, " chunkDir ", chunkDirection, " camDir "); - if (dot < 0.7) { // cos(45) + float threshold = 0.87; + if (camDist < 12) + threshold = 0.5; + //Log.d("visit() chunkPos ", chunkPos, " chunkDir ", chunkDirection, " camDir ", " dot ", dot, " threshold ", threshold); + + if (dot < threshold) { // cos(45) _skippedCount++; - return; + return false; } Mesh mesh = chunk.getMesh(world); if (mesh) { _material.bind(_node, mesh, lights(_node)); - _material.drawMesh(mesh); + _material.drawMesh(mesh, _wireframe); _material.unbind(); _drawnCount++; } + return true; } + return true; } } @@ -232,7 +253,8 @@ class UiWidget : VerticalLayout { //, CellVisitor //updateMinerMesh(); Material minerMaterial = new Material(EffectId("textured.vert", "textured.frag", null), "blocks"); - minerMaterial.ambientColor = vec3(0.05,0.05,0.05); + //Material minerMaterial = new Material(EffectId("colored.vert", "colored.frag", null), "blocks"); + minerMaterial.ambientColor = vec3(0.25,0.25,0.25); minerMaterial.textureLinear = false; minerMaterial.fogParams = new FogParams(vec4(0.01, 0.01, 0.01, 1), 12, 80); //minerMaterial.specular = 10; @@ -240,6 +262,7 @@ class UiWidget : VerticalLayout { //, CellVisitor //_minerDrawable.autobindLights = false; //Model minerDrawable = new Model(minerMaterial, _minerMesh); Node3d minerNode = new Node3d("miner", _minerDrawable); + //_minerDrawable.wireframe = true; _scene.addChild(minerNode); @@ -342,6 +365,9 @@ class UiWidget : VerticalLayout { //, CellVisitor override bool onKeyEvent(KeyEvent event) { if (event.action == KeyAction.KeyDown) { switch(event.keyCode) with(KeyCode) { + case F1: + _minerDrawable.wireframe = !_minerDrawable.wireframe; + return true; case KEY_W: case UP: _world.camPosition.forward(1); @@ -455,11 +481,13 @@ class UiWidget : VerticalLayout { //, CellVisitor 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, + dstring s = format("pos(%d,%d) h=%d fps:%d %s [F]lying: %s [U]pdateMesh: %s [F1] wireframe: %s", _world.camPosition.pos.x, _world.camPosition.pos.z, _world.camPosition.pos.y, _fps, dir, flying, - enableMeshUpdate).toUTF32; + enableMeshUpdate, + _minerDrawable ? _minerDrawable.wireframe : false + ).toUTF32; w.text = s; } diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index 67be417c..f281d7d4 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -435,13 +435,13 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect { } /// draw mesh using this program (program should be bound by this time and all uniforms should be set) - override void draw(Mesh mesh) { + override void draw(Mesh mesh, bool wireframe) { VertexBuffer vb = mesh.vertexBuffer; if (!vb) { vb = new GLVertexBuffer(); mesh.vertexBuffer = vb; } - vb.draw(this); + vb.draw(this, wireframe); } } @@ -1310,16 +1310,39 @@ class GLVertexBuffer : VertexBuffer { } /// draw mesh using specified effect - override void draw(GraphicsEffect effect) { + override void draw(GraphicsEffect effect, bool wireframe) { //bind(); enableAttributes(effect); foreach (fragment; _indexFragments) { - checkgl!glDrawRangeElements(primitiveTypeToGL(fragment.type), - 0, _vertexCount - 1, // The first to last vertex - fragment.end - fragment.start, // count of indexes used to draw elements - GL_UNSIGNED_SHORT, - cast(char*)(fragment.start * short.sizeof) // offset from index buffer beginning to fragment start - ); + if (wireframe && fragment.type == PrimitiveType.triangles) { + // TODO: support wireframe not only for triangles + int triangleCount = fragment.end - fragment.start; + //triangleCount /= 3; + //checkgl!glDisable(GL_CULL_FACE); + for (int i = 0; i < triangleCount; i += 3) { + // GL line loop works strange; use GL_LINES instead + checkgl!glDrawRangeElements(GL_LINE_LOOP, //GL_TRIANGLES, + 0, _vertexCount - 1, // The first to last vertex start, end + 3, // count of indexes used to draw elements + GL_UNSIGNED_SHORT, + cast(char*)((fragment.start + i) * short.sizeof) // offset from index buffer beginning to fragment start + ); + //checkgl!glDrawRangeElements(GL_LINES, //GL_TRIANGLES, + // 0, _vertexCount - 1, // The first to last vertex start, end + // 2, // count of indexes used to draw elements + // GL_UNSIGNED_SHORT, + // cast(char*)((fragment.start + i + 1) * short.sizeof) // offset from index buffer beginning to fragment start + // ); + } + //checkgl!glEnable(GL_CULL_FACE); + } else { + checkgl!glDrawRangeElements(primitiveTypeToGL(fragment.type), + 0, _vertexCount - 1, // The first to last vertex + fragment.end - fragment.start, // count of indexes used to draw elements + GL_UNSIGNED_SHORT, + cast(char*)(fragment.start * short.sizeof) // offset from index buffer beginning to fragment start + ); + } } disableAttributes(effect); //unbind(); @@ -1381,10 +1404,11 @@ class DummyVertexBuffer : VertexBuffer { } /// draw mesh using specified effect - override void draw(GraphicsEffect effect) { + override void draw(GraphicsEffect effect, bool wireframe) { //bind(); enableAttributes(effect); foreach (fragment; _indexFragments) { + // TODO: support wireframe checkgl!glDrawRangeElements(primitiveTypeToGL(fragment.type), 0, _vertexCount, fragment.end - fragment.start, diff --git a/src/dlangui/graphics/scene/material.d b/src/dlangui/graphics/scene/material.d index 623e2cf8..e19aa378 100644 --- a/src/dlangui/graphics/scene/material.d +++ b/src/dlangui/graphics/scene/material.d @@ -230,8 +230,8 @@ class Material : RefCountedObject { } } - void drawMesh(Mesh mesh) { - effect.draw(mesh); + void drawMesh(Mesh mesh, bool wireframe) { + effect.draw(mesh, wireframe); } void unbind() { diff --git a/src/dlangui/graphics/scene/mesh.d b/src/dlangui/graphics/scene/mesh.d index 2c16f067..a0d2a259 100644 --- a/src/dlangui/graphics/scene/mesh.d +++ b/src/dlangui/graphics/scene/mesh.d @@ -63,7 +63,7 @@ abstract class GraphicsEffect : RefCountedObject { /// returns true if effect has uniform bool hasUniform(string uniformName); - void draw(Mesh mesh); + void draw(Mesh mesh, bool wireframe); } enum DefaultUniform : int { @@ -162,7 +162,7 @@ class VertexBuffer { /// set or change data void setData(Mesh mesh) { } /// draw mesh using specified effect - void draw(GraphicsEffect effect) { } + void draw(GraphicsEffect effect, bool wireframe) { } } /// location for element is not found diff --git a/src/dlangui/graphics/scene/model.d b/src/dlangui/graphics/scene/model.d index 7c99b3e3..d90991be 100644 --- a/src/dlangui/graphics/scene/model.d +++ b/src/dlangui/graphics/scene/model.d @@ -29,7 +29,7 @@ class Model : MaterialDrawableObject { override void draw(Node3d node, bool wireframe) { /// override it _material.bind(node, _mesh, lights(node)); - _material.drawMesh(_mesh); + _material.drawMesh(_mesh, wireframe); _material.unbind(); } } diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index b400bf35..20cc9546 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -1574,7 +1574,7 @@ class Platform { } static if (ENABLE_OPENGL) { - private __gshared bool _OPENGL_ENABLED = false; + private __gshared bool _OPENGL_ENABLED = true; /// check if hardware acceleration is enabled @property bool openglEnabled() { return _OPENGL_ENABLED; } /// call on app initialization if OpenGL support is detected