mirror of https://github.com/buggins/dlangui.git
optimize dminer example; fix win32 opengl support; enable wireframe mode for drawing of meshes
This commit is contained in:
parent
388bc94cf7
commit
4c1e97c952
|
@ -96,7 +96,7 @@ X<-----x-----
|
||||||
|
|
||||||
private immutable float CCC = 0.5; // cell cube coordinates
|
private immutable float CCC = 0.5; // cell cube coordinates
|
||||||
private immutable float TC0 = 0.0;
|
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 =
|
__gshared static const float[VERTEX_COMPONENTS * 4] face_vertices_north =
|
||||||
[
|
[
|
||||||
|
|
|
@ -6,7 +6,7 @@ import dminer.core.world;
|
||||||
import dlangui.graphics.scene.mesh;
|
import dlangui.graphics.scene.mesh;
|
||||||
|
|
||||||
|
|
||||||
version = FAST_VISIBILITY_PATH;
|
//version = FAST_VISIBILITY_PATH;
|
||||||
|
|
||||||
// Y range: 0..CHUNK_DY-1
|
// Y range: 0..CHUNK_DY-1
|
||||||
immutable int CHUNK_DY = 128;
|
immutable int CHUNK_DY = 128;
|
||||||
|
@ -29,7 +29,7 @@ interface CellVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ChunkVisitor {
|
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
|
// vertical stack of chunks with same X, Z, and different Y
|
||||||
|
@ -1550,13 +1550,18 @@ struct VisibilityCheckIterator {
|
||||||
if (!mask)
|
if (!mask)
|
||||||
return;
|
return;
|
||||||
// distance test
|
// distance test
|
||||||
Vector3d diff = p - camPos;
|
Vector3d diff = (p + Vector3d(4,4,4)) - camPos;
|
||||||
if (diff.squaredLength() > maxDistanceSquared)
|
if (diff.squaredLength() > maxDistanceSquared)
|
||||||
return;
|
return;
|
||||||
|
int distance = diff.squaredLength;
|
||||||
|
if (distance > 10*10) {
|
||||||
|
diff = (diff * 256 + cameraDirection * 16) / 256;
|
||||||
|
//diff += cameraDirection;
|
||||||
// direction test (TODO)
|
// direction test (TODO)
|
||||||
int dot = diff.dot(cameraDirection);
|
int dot = diff.dot(cameraDirection);
|
||||||
if (dot < 8000)
|
if (dot < 12000)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
//....
|
//....
|
||||||
// plan visiting
|
// plan visiting
|
||||||
VisibilityCheckChunk * plan = getOrAddPlannedChunk(p);
|
VisibilityCheckChunk * plan = getOrAddPlannedChunk(p);
|
||||||
|
@ -1571,7 +1576,8 @@ struct VisibilityCheckIterator {
|
||||||
swap(visitedChunks, plannedChunks);
|
swap(visitedChunks, plannedChunks);
|
||||||
plannedChunks.length = 0;
|
plannedChunks.length = 0;
|
||||||
foreach (ref p; visitedChunks) {
|
foreach (ref p; visitedChunks) {
|
||||||
visitor.visit(world, p.chunk);
|
if (!visitor.visit(world, p.chunk))
|
||||||
|
continue;
|
||||||
/// set mask of spread directions
|
/// set mask of spread directions
|
||||||
p.spreadToDirMask = calcSpreadMask(p.pos, startPos);
|
p.spreadToDirMask = calcSpreadMask(p.pos, startPos);
|
||||||
p.tracePaths();
|
p.tracePaths();
|
||||||
|
|
|
@ -120,6 +120,10 @@ struct Vector3d {
|
||||||
Vector3d opBinary(string op : "*")(int n) const {
|
Vector3d opBinary(string op : "*")(int n) const {
|
||||||
return Vector3d(x * n, y * n, z * n);
|
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) {
|
ref Vector3d opOpAssign(string op : "+")(const Vector3d v) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import dminer.core.chunk;
|
||||||
version (Android) {
|
version (Android) {
|
||||||
const int MAX_VIEW_DISTANCE = 60;
|
const int MAX_VIEW_DISTANCE = 60;
|
||||||
} else {
|
} else {
|
||||||
const int MAX_VIEW_DISTANCE = 120;
|
const int MAX_VIEW_DISTANCE = 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import dlangui.graphics.scene.effect;
|
||||||
import dlangui.graphics.glsupport;
|
import dlangui.graphics.glsupport;
|
||||||
import dlangui.graphics.gldrawbuf;
|
import dlangui.graphics.gldrawbuf;
|
||||||
|
|
||||||
|
//version = TEST_VISITOR_PERFORMANCE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
version (Android) {
|
version (Android) {
|
||||||
//enum SUPPORT_LEGACY_OPENGL = false;
|
//enum SUPPORT_LEGACY_OPENGL = false;
|
||||||
|
@ -62,8 +64,9 @@ extern (C) int UIAppMain(string[] args) {
|
||||||
|
|
||||||
class ChunkVisitCounter : ChunkVisitor {
|
class ChunkVisitCounter : ChunkVisitor {
|
||||||
int count;
|
int count;
|
||||||
void visit(World world, SmallChunk * chunk) {
|
bool visit(World world, SmallChunk * chunk) {
|
||||||
count++;
|
count++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +81,10 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
|
||||||
private Camera _cam;
|
private Camera _cam;
|
||||||
private vec3 _camPosition;
|
private vec3 _camPosition;
|
||||||
private vec3 _camForwardVector;
|
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) {
|
this(World world, Material material, Camera cam) {
|
||||||
super(material);
|
super(material);
|
||||||
|
@ -94,7 +101,7 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
|
||||||
_pos = _world.camPosition.pos;
|
_pos = _world.camPosition.pos;
|
||||||
_camPosition = _cam.translation;
|
_camPosition = _cam.translation;
|
||||||
_camForwardVector = _cam.forwardVectorWorld;
|
_camForwardVector = _cam.forwardVectorWorld;
|
||||||
_camPosition -= _camForwardVector * 8;
|
//_camPosition -= _camForwardVector * 8;
|
||||||
_skippedCount = _drawnCount = 0;
|
_skippedCount = _drawnCount = 0;
|
||||||
long ts = currentTimeMillis();
|
long ts = currentTimeMillis();
|
||||||
//_chunkVisitor.visitChunks(_pos);
|
//_chunkVisitor.visitChunks(_pos);
|
||||||
|
@ -102,6 +109,7 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
|
||||||
camVector.x = cast(int)(_camForwardVector.x * 256);
|
camVector.x = cast(int)(_camForwardVector.x * 256);
|
||||||
camVector.y = cast(int)(_camForwardVector.y * 256);
|
camVector.y = cast(int)(_camForwardVector.y * 256);
|
||||||
camVector.z = cast(int)(_camForwardVector.z * 256);
|
camVector.z = cast(int)(_camForwardVector.z * 256);
|
||||||
|
version (TEST_VISITOR_PERFORMANCE) {
|
||||||
ChunkVisitCounter countVisitor = new ChunkVisitCounter();
|
ChunkVisitCounter countVisitor = new ChunkVisitCounter();
|
||||||
_chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE);
|
_chunkIterator.start(_world, _world.camPosition.pos, MAX_VIEW_DISTANCE);
|
||||||
_chunkIterator.visitVisibleChunks(countVisitor, camVector);
|
_chunkIterator.visitVisibleChunks(countVisitor, camVector);
|
||||||
|
@ -110,26 +118,39 @@ class MinerDrawable : MaterialDrawableObject, ChunkVisitor {
|
||||||
_chunkIterator.visitVisibleChunks(this, camVector);
|
_chunkIterator.visitVisibleChunks(this, camVector);
|
||||||
long duration = currentTimeMillis() - ts;
|
long duration = currentTimeMillis() - ts;
|
||||||
Log.d("drawing of Miner scene finished in ", duration, " ms skipped:", _skippedCount, " drawn:", _drawnCount, " duration(noDraw)=", durationNoDraw);
|
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) {
|
if (chunk) {
|
||||||
Vector3d p = chunk.position;
|
Vector3d p = chunk.position;
|
||||||
vec3 chunkPos = vec3(p.x + 4, p.y + 4, p.z + 4);
|
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);
|
float dot = _camForwardVector.dot(chunkDirection);
|
||||||
//Log.d("visit() chunkPos ", chunkPos, " chunkDir ", chunkDirection, " camDir ");
|
float threshold = 0.87;
|
||||||
if (dot < 0.7) { // cos(45)
|
if (camDist < 12)
|
||||||
|
threshold = 0.5;
|
||||||
|
//Log.d("visit() chunkPos ", chunkPos, " chunkDir ", chunkDirection, " camDir ", " dot ", dot, " threshold ", threshold);
|
||||||
|
|
||||||
|
if (dot < threshold) { // cos(45)
|
||||||
_skippedCount++;
|
_skippedCount++;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
Mesh mesh = chunk.getMesh(world);
|
Mesh mesh = chunk.getMesh(world);
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
_material.bind(_node, mesh, lights(_node));
|
_material.bind(_node, mesh, lights(_node));
|
||||||
_material.drawMesh(mesh);
|
_material.drawMesh(mesh, _wireframe);
|
||||||
_material.unbind();
|
_material.unbind();
|
||||||
_drawnCount++;
|
_drawnCount++;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +253,8 @@ class UiWidget : VerticalLayout { //, CellVisitor
|
||||||
//updateMinerMesh();
|
//updateMinerMesh();
|
||||||
|
|
||||||
Material minerMaterial = new Material(EffectId("textured.vert", "textured.frag", null), "blocks");
|
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.textureLinear = false;
|
||||||
minerMaterial.fogParams = new FogParams(vec4(0.01, 0.01, 0.01, 1), 12, 80);
|
minerMaterial.fogParams = new FogParams(vec4(0.01, 0.01, 0.01, 1), 12, 80);
|
||||||
//minerMaterial.specular = 10;
|
//minerMaterial.specular = 10;
|
||||||
|
@ -240,6 +262,7 @@ class UiWidget : VerticalLayout { //, CellVisitor
|
||||||
//_minerDrawable.autobindLights = false;
|
//_minerDrawable.autobindLights = false;
|
||||||
//Model minerDrawable = new Model(minerMaterial, _minerMesh);
|
//Model minerDrawable = new Model(minerMaterial, _minerMesh);
|
||||||
Node3d minerNode = new Node3d("miner", _minerDrawable);
|
Node3d minerNode = new Node3d("miner", _minerDrawable);
|
||||||
|
//_minerDrawable.wireframe = true;
|
||||||
_scene.addChild(minerNode);
|
_scene.addChild(minerNode);
|
||||||
|
|
||||||
|
|
||||||
|
@ -342,6 +365,9 @@ class UiWidget : VerticalLayout { //, CellVisitor
|
||||||
override bool onKeyEvent(KeyEvent event) {
|
override bool onKeyEvent(KeyEvent event) {
|
||||||
if (event.action == KeyAction.KeyDown) {
|
if (event.action == KeyAction.KeyDown) {
|
||||||
switch(event.keyCode) with(KeyCode) {
|
switch(event.keyCode) with(KeyCode) {
|
||||||
|
case F1:
|
||||||
|
_minerDrawable.wireframe = !_minerDrawable.wireframe;
|
||||||
|
return true;
|
||||||
case KEY_W:
|
case KEY_W:
|
||||||
case UP:
|
case UP:
|
||||||
_world.camPosition.forward(1);
|
_world.camPosition.forward(1);
|
||||||
|
@ -455,11 +481,13 @@ class UiWidget : VerticalLayout { //, CellVisitor
|
||||||
import std.string : format;
|
import std.string : format;
|
||||||
Widget w = childById("lblPosition");
|
Widget w = childById("lblPosition");
|
||||||
string dir = _world.camPosition.direction.dir.to!string;
|
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,
|
_fps,
|
||||||
dir,
|
dir,
|
||||||
flying,
|
flying,
|
||||||
enableMeshUpdate).toUTF32;
|
enableMeshUpdate,
|
||||||
|
_minerDrawable ? _minerDrawable.wireframe : false
|
||||||
|
).toUTF32;
|
||||||
w.text = s;
|
w.text = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
/// 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;
|
VertexBuffer vb = mesh.vertexBuffer;
|
||||||
if (!vb) {
|
if (!vb) {
|
||||||
vb = new GLVertexBuffer();
|
vb = new GLVertexBuffer();
|
||||||
mesh.vertexBuffer = vb;
|
mesh.vertexBuffer = vb;
|
||||||
}
|
}
|
||||||
vb.draw(this);
|
vb.draw(this, wireframe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,10 +1310,32 @@ class GLVertexBuffer : VertexBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// draw mesh using specified effect
|
/// draw mesh using specified effect
|
||||||
override void draw(GraphicsEffect effect) {
|
override void draw(GraphicsEffect effect, bool wireframe) {
|
||||||
//bind();
|
//bind();
|
||||||
enableAttributes(effect);
|
enableAttributes(effect);
|
||||||
foreach (fragment; _indexFragments) {
|
foreach (fragment; _indexFragments) {
|
||||||
|
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),
|
checkgl!glDrawRangeElements(primitiveTypeToGL(fragment.type),
|
||||||
0, _vertexCount - 1, // The first to last vertex
|
0, _vertexCount - 1, // The first to last vertex
|
||||||
fragment.end - fragment.start, // count of indexes used to draw elements
|
fragment.end - fragment.start, // count of indexes used to draw elements
|
||||||
|
@ -1321,6 +1343,7 @@ class GLVertexBuffer : VertexBuffer {
|
||||||
cast(char*)(fragment.start * short.sizeof) // offset from index buffer beginning to fragment start
|
cast(char*)(fragment.start * short.sizeof) // offset from index buffer beginning to fragment start
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
disableAttributes(effect);
|
disableAttributes(effect);
|
||||||
//unbind();
|
//unbind();
|
||||||
}
|
}
|
||||||
|
@ -1381,10 +1404,11 @@ class DummyVertexBuffer : VertexBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// draw mesh using specified effect
|
/// draw mesh using specified effect
|
||||||
override void draw(GraphicsEffect effect) {
|
override void draw(GraphicsEffect effect, bool wireframe) {
|
||||||
//bind();
|
//bind();
|
||||||
enableAttributes(effect);
|
enableAttributes(effect);
|
||||||
foreach (fragment; _indexFragments) {
|
foreach (fragment; _indexFragments) {
|
||||||
|
// TODO: support wireframe
|
||||||
checkgl!glDrawRangeElements(primitiveTypeToGL(fragment.type),
|
checkgl!glDrawRangeElements(primitiveTypeToGL(fragment.type),
|
||||||
0, _vertexCount,
|
0, _vertexCount,
|
||||||
fragment.end - fragment.start,
|
fragment.end - fragment.start,
|
||||||
|
|
|
@ -230,8 +230,8 @@ class Material : RefCountedObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawMesh(Mesh mesh) {
|
void drawMesh(Mesh mesh, bool wireframe) {
|
||||||
effect.draw(mesh);
|
effect.draw(mesh, wireframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unbind() {
|
void unbind() {
|
||||||
|
|
|
@ -63,7 +63,7 @@ abstract class GraphicsEffect : RefCountedObject {
|
||||||
/// returns true if effect has uniform
|
/// returns true if effect has uniform
|
||||||
bool hasUniform(string uniformName);
|
bool hasUniform(string uniformName);
|
||||||
|
|
||||||
void draw(Mesh mesh);
|
void draw(Mesh mesh, bool wireframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DefaultUniform : int {
|
enum DefaultUniform : int {
|
||||||
|
@ -162,7 +162,7 @@ class VertexBuffer {
|
||||||
/// set or change data
|
/// set or change data
|
||||||
void setData(Mesh mesh) { }
|
void setData(Mesh mesh) { }
|
||||||
/// draw mesh using specified effect
|
/// draw mesh using specified effect
|
||||||
void draw(GraphicsEffect effect) { }
|
void draw(GraphicsEffect effect, bool wireframe) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// location for element is not found
|
/// location for element is not found
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Model : MaterialDrawableObject {
|
||||||
override void draw(Node3d node, bool wireframe) {
|
override void draw(Node3d node, bool wireframe) {
|
||||||
/// override it
|
/// override it
|
||||||
_material.bind(node, _mesh, lights(node));
|
_material.bind(node, _mesh, lights(node));
|
||||||
_material.drawMesh(_mesh);
|
_material.drawMesh(_mesh, wireframe);
|
||||||
_material.unbind();
|
_material.unbind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1574,7 +1574,7 @@ class Platform {
|
||||||
}
|
}
|
||||||
|
|
||||||
static if (ENABLE_OPENGL) {
|
static if (ENABLE_OPENGL) {
|
||||||
private __gshared bool _OPENGL_ENABLED = false;
|
private __gshared bool _OPENGL_ENABLED = true;
|
||||||
/// check if hardware acceleration is enabled
|
/// check if hardware acceleration is enabled
|
||||||
@property bool openglEnabled() { return _OPENGL_ENABLED; }
|
@property bool openglEnabled() { return _OPENGL_ENABLED; }
|
||||||
/// call on app initialization if OpenGL support is detected
|
/// call on app initialization if OpenGL support is detected
|
||||||
|
|
Loading…
Reference in New Issue