1 /** 2 * potree.js 3 * http://potree.org 4 * 5 * Copyright 2012, Markus Sch�tz 6 * Licensed under the GPL Version 2 or later. 7 * - http://potree.org/wp/?page_id=7 8 * - http://www.gnu.org/licenses/gpl-3.0.html 9 * 10 */ 11 12 /** 13 * @class 14 */ 15 function SceneNode(name, parent) { 16 if (arguments[0] === inheriting) return; 17 this._scene = null; 18 this.name = name; 19 this.parent = parent; 20 this.children = new Object(); 21 this.aabb = null; 22 this._visible = true; 23 24 // age in s 25 this.age = 0; 26 27 this._transform = M4x4.I; 28 if (parent != null) { 29 parent.addChild(this); 30 this.scene = parent.scene; 31 } 32 } 33 34 Object.defineProperty(SceneNode.prototype, 'visible', { 35 set: function(visible){ 36 this._visible = visible; 37 }, 38 39 get: function(){ 40 return this._visible; 41 } 42 }); 43 44 Object.defineProperty(SceneNode.prototype, 'scene', { 45 set: function(scene){ 46 this._scene = scene; 47 }, 48 49 get: function(){ 50 return this._scene; 51 } 52 }); 53 54 Object.defineProperty(SceneNode.prototype, "transform", { 55 get: function(){ 56 return this._transform; 57 }, 58 set: function(transform){ 59 this._transform = transform; 60 } 61 }); 62 63 Object.defineProperty(SceneNode.prototype, 'localTransformation', { 64 get: function(){ 65 return this._transform; 66 } 67 }); 68 69 Object.defineProperty(SceneNode.prototype, 'globalTransformation', { 70 get: function(){ 71 var cur = this; 72 var globalTransform = cur._transform; 73 while (cur.parent != null) { 74 cur = cur.parent; 75 globalTransform = M4x4.mul(cur._transform, globalTransform); 76 } 77 return globalTransform; 78 } 79 }); 80 81 Object.defineProperty(SceneNode.prototype, 'localPosition', { 82 get: function(){ 83 return V3.transform(V3.$(0, 0, 0), this._transform); 84 } 85 }); 86 87 Object.defineProperty(SceneNode.prototype, 'globalPosition', { 88 get: function(){ 89 return V3.transform(V3.$(0, 0, 0), this.globalTransformation); 90 } 91 }); 92 93 Object.defineProperty(SceneNode.prototype, 'descendants', { 94 get: function(){ 95 var descendants = new Array(); 96 var stack = new Array(); 97 stack.push(this); 98 while(stack.length != 0){ 99 var node = stack.pop(); 100 descendants.push(node); 101 for(var key in node.children) { 102 stack.push(node.children[key]); 103 } 104 } 105 106 return descendants; 107 } 108 }); 109 110 SceneNode.prototype.getLocalDirection = function(){ 111 var pos1 = V3.transform(V3.$(0, 0, 0), this._transform); 112 var pos2 = V3.transform(V3.$(0, 0, -1), this._transform); 113 114 var dir = V3.normalize(V3.sub(pos2, pos1)); 115 return dir; 116 }; 117 118 SceneNode.prototype.getGlobalDirection = function(){ 119 var transform = this.globalTransformation; 120 var pos1 = V3.transform(V3.$(0, 0, 0), transform); 121 var pos2 = V3.transform(V3.$(0, 0, -1), transform); 122 123 var dir = V3.normalize(V3.sub(pos2, pos1)); 124 return dir; 125 }; 126 127 SceneNode.prototype.getUpVector = function() { 128 var pos = V3.transform(V3.$(0, 0, 0), this._transform); 129 var absUp = V3.transform(V3.$(0, 1, 0), this._transform); 130 var up = V3.sub(absUp, pos); 131 132 return up; 133 }; 134 135 SceneNode.prototype.getSideVector = function() { 136 var pos = V3.transform(V3.$(0, 0, 0), this._transform); 137 var absSide = V3.transform(V3.$(1, 0, 0), this._transform); 138 var side = V3.sub(absSide, pos); 139 140 return side; 141 }; 142 143 SceneNode.prototype.getViewVector = function() { 144 var pos = V3.transform(V3.$(0, 0, 0), this._transform); 145 var absView = V3.transform(V3.$(1, 0, 0), this._transform); 146 var view = V3.sub(absView, pos); 147 148 return view; 149 }; 150 151 152 SceneNode.prototype.addTime = function(time) { 153 this.age += time; 154 155 for ( var childname in this.children) { 156 this.children[childname].addTime(time); 157 } 158 }; 159 160 SceneNode.prototype.setParent = function(parent) { 161 delete parent[this.name]; 162 this.parent = parent; 163 parent.children[this.name] = this; 164 this.scene = parent.scene; 165 }; 166 167 SceneNode.prototype.addChild = function(child) { 168 if (child.parent != null) { 169 delete child.parent.children[child.name]; 170 } 171 172 child.parent = this; 173 child.scene = this.scene; 174 this.children[child.name] = child; 175 }; 176 177 178 /** 179 * Liefert das Inverse der lokalen Transformationsmatrix unter der Annahme, dass 180 * es sich um eine Matrix handelt, die nach R�ckverschiebung zum Ursprung 181 * orthogonal ist. 182 * 183 * @returns 184 */ 185 SceneNode.prototype.getInverseLocalTransformation = function() { 186 var pos = this.localPosition; 187 var toOrigin = M4x4.translate3(-pos[0], -pos[1], -pos[2], M4x4.I); 188 var atOrigin = M4x4.mul(toOrigin, this._transform); 189 var inverseOrthonormal = M4x4.inverseOrthonormal(atOrigin); 190 191 return M4x4.mul(inverseOrthonormal, toOrigin); 192 }; 193 194 /** 195 * Liefert das Inverse der globalen Transformationsmatrix unter der Annahme, 196 * dass es sich um eine Matrix handelt, die nach R�ckverschiebung zum Ursprung 197 * orthogonal ist. 198 * 199 * @returns 200 */ 201 SceneNode.prototype.getInverseGlobalTransformation = function() { 202 var pos = this.globalPosition; 203 var toOrigin = M4x4.translate3(-pos[0], -pos[1], -pos[2], M4x4.I); 204 var atOrigin = M4x4.mul(toOrigin, this.globalTransformation); 205 var inverseOrthonormal = M4x4.inverseOrthonormal(atOrigin); 206 207 return M4x4.mul(inverseOrthonormal, toOrigin); 208 }; 209 210 SceneNode.prototype.translate = function(x, y, z) { 211 //TODO probably bugged. in one case the first, in another the second(commented) seems to behave right. 212 this._transform = M4x4.translate3(x, y, z, this._transform); 213 // this._transform = M4x4.mul(M4x4.makeTranslate3(x,y,z), this._transform); 214 }; 215 216 SceneNode.prototype.rotate = function(angle, axis) { 217 this._transform = M4x4.mul(M4x4.rotate(angle, axis, M4x4.I), this._transform); 218 }; 219 220 SceneNode.prototype.rotateX = function(angle) { 221 this._transform = M4x4.mul(M4x4.rotate(angle, V3.$(1, 0, 0), M4x4.I), this._transform); 222 }; 223 224 SceneNode.prototype.rotateY = function(angle) { 225 this._transform = M4x4.mul(M4x4.rotate(angle, V3.$(0, 1, 0), M4x4.I), this._transform); 226 }; 227 228 SceneNode.prototype.rotateZ = function(angle) { 229 this._transform = M4x4.mul(M4x4.rotate(angle, V3.$(0, 0, 1), M4x4.I), this._transform); 230 }; 231 232 SceneNode.prototype.scale = function(x, y, z) { 233 this._transform = M4x4.scale3(x, y, z, this._transform); 234 }; 235 236 SceneNode.prototype.lookAt = function(target){ 237 //TODO check for correctness 238 //TODO probably will not work if this sceneNodes parent transformation is != Identity 239 //TODO up-vector is always 0/1/0. check for linear independance 240 241 var nPos = this.globalPosition; 242 243 var dz = V3.direction(nPos, target); 244 var dy = V3.$(0,1,0); 245 var dx = V3.cross(dy, dz); 246 dy = V3.cross(dz, dx); 247 248 dx = V3.neg(dx); 249 dy = V3.neg(dy); 250 dz = V3.neg(dz); 251 252 var lookAt = M4x4.$( 253 dx.x, dx.y, dx.z, 0, 254 dy.x, dy.y, dy.z, 0, 255 dz.x, dz.y, dz.z, 0, 256 0, 0, 0, 1); 257 var translate = M4x4.makeTranslate3(nPos.x, nPos.y, nPos.z); 258 259 this.transform = M4x4.mul(translate, lookAt); 260 }; 261 262 SceneNode.prototype.render = function(camera) { 263 // in unterklassen �berschreiben 264 265 // if(this.visible){ 266 // for ( var childname in this.children) { 267 // this.children[childname].render(camera); 268 // } 269 // } 270 271 }; 272 273 SceneNode.prototype.toString = function() { 274 return this.asTreeString(0); 275 }; 276 277 SceneNode.prototype.asTreeString = function(level) { 278 var msg = " ".repeat(level * 3) + this.name + "\t" 279 + this.globalPosition + "\n"; 280 for ( var child in this.children) { 281 msg += this.children[child].asTreeString(level + 1); 282 } 283 284 return msg; 285 }; 286