1 module dlangui.graphics.scene.node; 2 3 public import dlangui.core.config; 4 static if (ENABLE_OPENGL): 5 static if (BACKEND_GUI): 6 7 import dlangui.core.math3d; 8 9 import dlangui.graphics.scene.transform; 10 11 /// 3D scene node 12 class Node3d : Transform { 13 import dlangui.core.collections; 14 import dlangui.graphics.scene.scene3d; 15 import dlangui.graphics.scene.drawableobject; 16 import dlangui.graphics.scene.light; 17 import dlangui.graphics.scene.camera; 18 19 protected Node3d _parent; 20 protected Scene3d _scene; 21 protected string _id; 22 protected bool _visible = true; 23 protected DrawableObjectRef _drawable; 24 protected LightRef _light; 25 26 protected mat4 _worldMatrix; 27 28 protected ObjectList!Node3d _children; 29 30 this(string id = null) { 31 super(); 32 _id = id; 33 } 34 35 this(string id, DrawableObject drawable) { 36 super(); 37 _id = id; 38 _drawable = drawable; 39 } 40 41 @property bool visible() { return _visible; } 42 @property Node3d visible(bool v) { _visible = v; return this; } 43 44 /// drawable attached to node 45 @property ref DrawableObjectRef drawable() { return _drawable; } 46 47 /// light attached to node 48 @property ref LightRef light() { return _light; } 49 50 /// attach light to node 51 @property Node3d light(Light v) { 52 if (_light.get is v) 53 return this; 54 Node3d oldNode = v.node; 55 v.node = this; 56 _light = v; 57 if (oldNode) 58 oldNode._light = null; 59 return this; 60 } 61 62 /// returns scene for node 63 @property Scene3d scene() { 64 if (_scene) 65 return _scene; 66 if (_parent) 67 return _parent.scene; 68 return cast(Scene3d) this; 69 } 70 71 @property void scene(Scene3d v) { _scene = v; } 72 73 /// returns child node count 74 @property int childCount() { 75 return _children.count; 76 } 77 78 /// returns child node by index 79 Node3d child(int index) { 80 return _children[index]; 81 } 82 83 /// add child node, return current node 84 Node3d addChild(Node3d node) { 85 _children.add(node); 86 node.parent = this; 87 node.scene = scene; 88 return this; 89 } 90 91 /// removes and destroys child node by index 92 void removeChild(int index) { 93 destroy(_children.remove(index)); 94 } 95 96 /// remove and destroy child node (returns true if child is found and removed) 97 bool removeChild(Node3d child) { 98 int index = findChild(child); 99 if (index >= 0) { 100 removeChild(index); 101 return true; 102 } 103 return false; 104 } 105 106 /// find node index, returns -1 if not found 107 int findChild(Node3d node) { 108 if (node is null) 109 return -1; 110 for (int i = 0; i < childCount; i++) { 111 if (child(i) is node) 112 return i; 113 } 114 return -1; 115 } 116 117 @property ref ObjectList!Node3d children() { return _children; } 118 119 /// parent node 120 @property Node3d parent() { 121 return _parent; 122 } 123 124 @property Node3d parent(Node3d v) { 125 _parent = v; 126 _scene = v.scene; 127 return this; 128 } 129 /// id of node 130 @property string id() { 131 return _id; 132 } 133 /// set id for node 134 @property Node3d id(string v) { 135 _id = v; 136 return this; 137 } 138 139 /// active camera or null of no camera 140 @property Camera activeCamera() { 141 if (!scene) 142 return null; 143 return scene.activeCamera; 144 } 145 146 @property vec3 cameraPosition() { 147 auto cam = activeCamera; 148 if (cam) 149 return cam.translationWorld; 150 return vec3(0, 0, 0); 151 } 152 153 /// get view matrix based on active camera 154 @property ref const(mat4) viewMatrix() { 155 auto cam = activeCamera; 156 if (cam) 157 return cam.viewMatrix; 158 return mat4.IDENTITY; 159 } 160 161 /// get projection*view matrix based on active camera 162 @property ref const(mat4) projectionViewMatrix() { 163 auto cam = activeCamera; 164 if (cam) 165 return cam.projectionViewMatrix; 166 return mat4.IDENTITY; 167 } 168 169 protected mat4 _projectionViewModelMatrix; 170 171 /// returns projectionMatrix * viewMatrix * modelMatrix 172 @property ref const(mat4) projectionViewModelMatrix() { 173 // TODO: optimize 174 if (_parent) 175 _projectionViewModelMatrix = _scene.projectionViewMatrix * _parent.matrix * matrix; 176 else 177 _projectionViewModelMatrix = _scene.projectionViewMatrix * matrix; 178 return _projectionViewModelMatrix; 179 } 180 181 /// returns world matrix 182 @property ref const(mat4) worldMatrix() { 183 if (!parent) 184 return matrix; 185 _worldMatrix = parent.worldMatrix * matrix; 186 return _worldMatrix; 187 } 188 189 /** 190 * Gets the world view matrix corresponding to this node. 191 * 192 * @return The world view matrix of this node. 193 */ 194 @property ref const(mat4) worldViewMatrix() { 195 static mat4 worldView; 196 worldView = viewMatrix * worldMatrix; 197 return worldView; 198 } 199 200 /// returns translation vector (position) of this node in world space 201 @property vec3 translationWorld() { 202 vec3 translation; 203 worldMatrix.getTranslation(translation); 204 return translation; 205 } 206 207 /// returns translation vector (position) of this node in view space 208 @property vec3 translationView() { 209 vec3 translation; 210 worldMatrix.getTranslation(translation); 211 viewMatrix.transformPoint(translation); 212 return translation; 213 } 214 215 /** 216 * Gets the inverse transpose world matrix corresponding to this node. 217 * 218 * This matrix is typically used to transform normal vectors into world space. 219 * 220 * @return The inverse world matrix of this node. 221 */ 222 @property ref const(mat4) inverseTransposeWorldMatrix() { 223 static __gshared mat4 invTransWorld; 224 invTransWorld = worldMatrix; 225 invTransWorld.invert(); 226 invTransWorld.transpose(); 227 return invTransWorld; 228 } 229 230 /** 231 * Gets the inverse transpose world view matrix corresponding to this node. 232 * 233 * This matrix is typically used to transform normal vectors into view space. 234 * 235 * @return The inverse world view matrix of this node. 236 */ 237 @property ref const(mat4) inverseTransposeWorldViewMatrix() { 238 static __gshared mat4 invTransWorldView; 239 invTransWorldView = viewMatrix * worldMatrix; 240 invTransWorldView.invert(); 241 invTransWorldView.transpose(); 242 return invTransWorldView; 243 } 244 245 246 /** 247 * Returns the forward vector of the Node in world space. 248 * 249 * @return The forward vector in world space. 250 */ 251 @property vec3 forwardVectorWorld() { 252 return worldMatrix.forwardVector; 253 } 254 /** 255 * Returns the forward vector of the Node in view space. 256 * 257 * @return The forward vector in view space. 258 */ 259 @property vec3 forwardVectorView() { 260 vec3 vector = worldMatrix.forwardVector; 261 viewMatrix.transformVector(vector); 262 return vector; 263 } 264 }