1 module dlangui.graphics.scene.scene3d; 2 3 public import dlangui.core.config; 4 static if (ENABLE_OPENGL): 5 static if (BACKEND_GUI): 6 7 import dlangui.core.types; 8 9 import dlangui.core.math3d; 10 import dlangui.graphics.scene.node; 11 import dlangui.graphics.scene.skybox; 12 13 /// Reference counted Scene3d object 14 alias Scene3dRef = Ref!Scene3d; 15 16 17 /// 3D scene 18 class Scene3d : Node3d { 19 import dlangui.graphics.scene.camera; 20 import dlangui.graphics.scene.light; 21 22 protected vec3 _ambientColor; 23 protected Camera _activeCamera; 24 protected SkyBox _skyBox; 25 26 /// ambient light color 27 @property vec3 ambientColor() { return _ambientColor; } 28 /// set ambient light color 29 @property void ambientColor(const ref vec3 v) { _ambientColor = v; } 30 31 this(string id = null) { 32 super(id); 33 _skyBox = new SkyBox(this); 34 } 35 36 ~this() { 37 destroy(_skyBox); 38 } 39 40 @property SkyBox skyBox() { return _skyBox; } 41 42 /// active camera 43 override @property Camera activeCamera() { 44 if (_activeCamera) 45 return _activeCamera; 46 // TODO: find camera in child nodes 47 return null; 48 } 49 /// set or clear current active camera 50 @property void activeCamera(Camera cam) { 51 _activeCamera = cam; 52 if (cam && cam.parent != this) 53 addChild(cam); 54 } 55 56 /// returns scene for node 57 override @property Scene3d scene() { 58 return this; 59 } 60 61 override @property void scene(Scene3d v) { 62 //ignore 63 } 64 65 protected bool _wireframe; 66 void drawScene(bool wireframe) { 67 _wireframe = wireframe; 68 updateAutoboundLights(); 69 if (_skyBox.visible) { 70 import dlangui.graphics.glsupport; 71 checkgl!glDisable(GL_DEPTH_TEST); 72 checkgl!glDisable(GL_CULL_FACE); 73 if (_activeCamera) { 74 _skyBox.translation = _activeCamera.translation; 75 _skyBox.scaling = _activeCamera.farRange * 0.3; 76 } 77 visit(_skyBox, &sceneDrawVisitor); 78 checkgl!glEnable(GL_DEPTH_TEST); 79 checkgl!glEnable(GL_CULL_FACE); 80 checkgl!glClear(GL_DEPTH_BUFFER_BIT); 81 } 82 visit(this, &sceneDrawVisitor); 83 } 84 85 protected bool sceneDrawVisitor(Node3d node) { 86 if (!node.visible) 87 return false; 88 if (!node.drawable.isNull) 89 node.drawable.draw(node, _wireframe); 90 return false; 91 } 92 93 void updateAutoboundLights() { 94 _lights.reset(); 95 visit(this, &lightBindingVisitor); 96 } 97 98 protected bool lightBindingVisitor(Node3d node) { 99 if (!node.light.isNull && node.light.enabled && node.light.autobind) 100 _lights.add(node.light); 101 return false; 102 } 103 104 protected LightParams _lights; 105 106 @property ref LightParams boundLights() { 107 return _lights; 108 } 109 110 @property LightParams * boundLightsPtr() { 111 return _lights.empty ? null : &_lights; 112 } 113 } 114 115 /// depth-first recursive node traversion, stops if visitor returns true 116 bool visit(Node3d node, bool delegate(Node3d node) visitor) { 117 if (!node.visible) 118 return false; 119 bool res = false; 120 if (visitor(node)) 121 return true; 122 foreach(child; node.children) { 123 res = visit(child, visitor); 124 if (res) 125 return true; 126 } 127 return false; 128 }