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 /** 14 * holds the WebGL context 15 */ 16 var gl = null; 17 18 /** 19 * 20 * @class 21 */ 22 function Potree(){ 23 this.camHandler = null; 24 } 25 26 /** 27 * a list of all js files that must be included by Potree 28 */ 29 Potree.includes = [ 30 "config.js", 31 "libs/mjs/mjs.js", 32 "libs/WebglDebug/webgl-debug.js", 33 "libs/other/other.js", 34 "src/extensions/Array.js", 35 "src/extensions/mjs.js", 36 "src/extensions/String.js", 37 "src/extensions/ArrayBuffer.js", 38 "src/extensions/Float32Array.js", 39 "src/utils/utils.js", 40 "src/KeyListener.js", 41 "src/MouseListener.js", 42 "src/ResourceManager/TextureManager.js", 43 "src/ResourceManager/MaterialManager.js", 44 "src/shader/Shader.js", 45 "src/utils/Plane.js", 46 "src/utils/Frustum.js", 47 "src/rendering/Renderer.js", 48 "src/scenegraph/AABB.js", 49 "src/scenegraph/SceneNode.js", 50 "src/scenegraph/Camera.js", 51 "src/scenegraph/Scene.js", 52 "src/scenegraph/MeshNode.js", 53 "src/scenegraph/Light.js", 54 "src/scenegraph/Sphere.js", 55 // "src/scenegraph/Plane.js", 56 "src/objects/Mesh.js", 57 "src/Viewport.js", 58 "src/navigation/CamHandler.js", 59 "src/navigation/FreeFlightCamHandler.js", 60 "src/Framebuffer.js", 61 "src/FramebufferFloat32.js", 62 "src/ResourceManager/ShaderManager.js", 63 "src/utils/MeshUtils.js", 64 "src/scenegraph/PointcloudOctreeSceneNode.js", 65 "src/scenegraph/PointCloudSceneNode.js", 66 "src/objects/PointCloud.js", 67 "src/objects/PointcloudOctreeNode.js", 68 "src/objects/PointcloudOctree.js", 69 "src/materials/Material.js", 70 "src/materials/WeightedPointSizeMaterial.js", 71 "src/materials/FixedPointSizeMaterial.js", 72 "src/materials/PointCloudMaterial.js", 73 "src/materials/FlatMaterial.js", 74 "src/materials/FilteredSplatsMaterial.js", 75 "src/loader/POCLoader.js", 76 "src/loader/PointAttributes.js", 77 "src/loader/ProceduralPointcloudGenerator.js", 78 "src/loader/PlyLoader.js", 79 "src/utils/LRU.js", 80 ]; 81 82 Potree.Settings = new Object(); 83 84 //settings 85 Potree.Settings.showBoundingBoxes = false; 86 Potree.Settings.LOD = true; 87 Potree.Settings.LODMultiplicator = 10.0; 88 Potree.Settings.pointSize = 1; 89 Potree.Settings.backgroundColor = [0,0,0,1];//[ 0.3, 0.3, 0.4, 1 ]; 90 Potree.Settings.showGrid = false; 91 Potree.Settings.frustumCulling = true; 92 93 //other 94 Potree.testFBO = null; 95 Potree.gridSceneNode = null; 96 Potree.canvas = null; 97 Potree.initialized = false; 98 99 100 /** 101 * includes the javascript file at {path} by adding a script tag to the document. 102 * 103 * @param path Potree library path 104 * @returns 105 */ 106 Potree.importScripts = function(path){ 107 var importText = ""; 108 for(var i = 0; i < Potree.includes.length; i++){ 109 var include = Potree.includes[i]; 110 //document.write("<scri" + "pt type=\"text/javascript\" src=\"" + path + "/" +include+"\"></scri" + "pt>"); 111 importText += "<scri" + "pt type=\"text/javascript\" src=\"" + path + "/" +include+"\"></scri" + "pt>\n"; 112 } 113 document.write(importText); 114 }; 115 116 117 Potree.isWebGLEnabled = function(canvas){ 118 var names = [ "webgl", "experimental-webgl", "moz-webgl", "webkit-3d" ]; 119 for ( var i = 0; names.length > i; i++) { 120 try { 121 gl = canvas.getContext(names[i], { 122 antialias : false 123 }); 124 if (gl) { 125 break; 126 } 127 } catch (e) { 128 } 129 } 130 if (!gl) { 131 console.log("No known OpenGL context detected! Is it enabled?"); 132 return false; 133 } 134 135 return true; 136 }; 137 138 /** 139 * 140 * @param canvas the canvas element for rendering. 141 * Potree can only be intialized once. 142 * @returns 143 */ 144 Potree.init = function(canvas) { 145 if(Potree.initialized){ 146 console.log("Potree has already been initialized"); 147 return true; 148 } 149 150 Potree.canvas = canvas; 151 Potree.currentScene = new Scene("default"); 152 153 if(!Potree.initGL()){ 154 // init failed -> display error message 155 var soSorry = document.createElement("div"); 156 var msg = "<br>Could not create a WebGL context. "; 157 msg += "<br><br>Try using <a href='http://www.mozilla.org' style='color: red'>Firefox</a> "; 158 msg += "or <a href='www.google.com/chrome/' style='color: red'>Chrome</a>."; 159 msg += "<br>Other WebGL enabled browsers are not supported but they might work as well."; 160 soSorry.innerHTML = msg; 161 soSorry.style.fontSize = "large"; 162 soSorry.style.fontWeight = "bold"; 163 soSorry.style.color = "#FFF"; 164 soSorry.style.textShadow = "black 0 0 4px, black 0 0 4px, black 0 0 4px, black 0 0 4px, black 0 0 4px, black 0 0 4px"; 165 soSorry.style.textAlign = "center"; 166 soSorry.style.verticalAlign = "bottom"; 167 soSorry.style.height = "100%"; 168 canvas.parentNode.replaceChild(soSorry, canvas); 169 170 return false; 171 } 172 173 {// register mouse and key listener 174 var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel"; //FF doesn't recognize mousewheel as of FF3.x 175 if (document.attachEvent){ //if IE (and Opera depending on user setting) 176 document.attachEvent("on"+mousewheelevt,MouseListener.mouseWheel); 177 }else if (document.addEventListener){ //WC3 browsers 178 document.addEventListener(mousewheelevt, MouseListener.mouseWheel, false); 179 } 180 document.onkeydown = KeyListener.keyDown; 181 document.onkeyup = KeyListener.keyUp; 182 document.onkeypress = KeyListener.keyPress; 183 document.onmousedown = MouseListener.mouseDown; 184 document.onmouseup = MouseListener.mouseUp; 185 document.onmousemove = MouseListener.mouseMove; 186 } 187 188 189 {// install cam handler 190 Potree.camHandler = new FreeFlightCamHandler(Potree.currentScene.activeCamera); 191 canvas.onfocus = function(){ 192 KeyListener.addListener(Potree.camHandler); 193 MouseListener.addListener(Potree.camHandler); 194 }; 195 196 canvas.onblur= function(){ 197 KeyListener.removeListener(Potree.camHandler); 198 MouseListener.removeListener(Potree.camHandler); 199 }; 200 } 201 202 Potree.initialized = true; 203 204 // shaders 205 var drawTextureShader = new Shader("drawTexture", "drawTexture.vs", "drawTexture.fs"); 206 207 // materials 208 var pointCloudMaterial = new PointCloudMaterial("pointCloud"); 209 210 Potree.mainLoop(); 211 212 return Potree.initialized; 213 }; 214 215 /** 216 * creates the WebGL context 217 * 218 */ 219 Potree.initGL = function() { 220 221 viewportWidth = Potree.canvas.width; 222 viewportHeight = Potree.canvas.height; 223 224 var names = [ "webgl", "experimental-webgl", "moz-webgl", "webkit-3d" ]; 225 for ( var i = 0; names.length > i; i++) { 226 try { 227 gl = Potree.canvas.getContext(names[i], { 228 antialias : false 229 }); 230 if (gl) { 231 break; 232 } 233 } catch (e) { 234 } 235 } 236 if (!gl) { 237 console.log("No known OpenGL context detected! Is it enabled?"); 238 return false; 239 } 240 241 // if(Potree.useDebugContext){ 242 // Logger.warn("using WebGLDebugUtils - debugcontext. Performance may suffer."); 243 // gl = WebGLDebugUtils.makeDebugContext(gl); 244 // } 245 246 // extensions 247 if (!gl.getExtension("OES_texture_float")) { 248 console.log("some functions require OES_texture_float extension"); 249 return false; 250 } 251 252 // basic settings 253 var cColor = Potree.Settings.backgroundColor; 254 gl.clearColor(cColor.r, cColor.g, cColor.b, cColor.a); 255 gl.enable(gl.DEPTH_TEST); 256 gl.enable(gl.BLEND); 257 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 258 259 this.gridSceneNode = Potree.createGridNode(); 260 261 return true; 262 }; 263 264 /** 265 * a grid at the origin. 266 * 267 * @returns {SceneNode} 268 */ 269 Potree.createGridNode = function createGridNode() { 270 // materials 271 var matXAxis = new FlatMaterial("xAxis", [1.0, 0.0, 0.0, 1.0]); 272 var matYAxis = new FlatMaterial("yAxis", [0.0, 1.0, 0.0, 1.0]); 273 var matZAxis = new FlatMaterial("zAxis", [0.0, 0.0, 1.0, 1.0]); 274 // var gridMaterial = new FlatMaterial("grid"); 275 // gridMaterial.setColor(new Colour(0.7, 0.7, 0.7, 1.0)); 276 277 var gridNode = new SceneNode("gridNode", null); 278 var mGrid = MeshUtils.createGrid(1, 20, 20); 279 var nGrid = new MeshNode("grid", mGrid, gridNode); 280 281 // unfortunately, lineWidth is not supported/does not work so create 3 lines 282 // instead of one thick line 283 { 284 var mXAxis = MeshUtils.createLine( [ 0, 0, 0 ], [ 1, 0, 0 ]); 285 mXAxis.setMaterial(matXAxis); 286 var nXAxis = new MeshNode("xAxis", mXAxis, gridNode); 287 var nXAxis1 = new MeshNode("xAxis1", mXAxis, gridNode); 288 nXAxis1.translate(0, 0, 0.0001); 289 var nXAxis2 = new MeshNode("xAxis2", mXAxis, gridNode); 290 nXAxis2.translate(0, 0, -0.0001); 291 } 292 293 { 294 var mYAxis = MeshUtils.createLine( [ 0, 0, 0 ], [ 0, 1, 0 ]); 295 mYAxis.setMaterial(matYAxis); 296 var nYAxis = new MeshNode("yAxis", mYAxis, gridNode); 297 var nYAxis1 = new MeshNode("yAxis1", mYAxis, gridNode); 298 nYAxis1.translate(0, 0, 0.0001); 299 var nYAxis2 = new MeshNode("yAxis2", mYAxis, gridNode); 300 nYAxis2.translate(0, 0, -0.0001); 301 } 302 303 { 304 var mZAxis = MeshUtils.createLine( [ 0, 0, 0 ], [ 0, 0, 1 ]); 305 mZAxis.setMaterial(matZAxis); 306 var nZAxis = new MeshNode("zAxis", mZAxis, gridNode); 307 var nZAxis1 = new MeshNode("zAxis1", mZAxis, gridNode); 308 nZAxis1.translate(0.0001, 0, 0); 309 var nZAxis2 = new MeshNode("zAxis2", mZAxis, gridNode); 310 nZAxis2.translate(-0.0001, 0, 0); 311 } 312 313 return gridNode; 314 }; 315 316 /** 317 * draws a frame to the canvas 318 */ 319 Potree.draw = function() { 320 Potree.canvas.width = Potree.canvas.clientWidth; 321 Potree.canvas.height = Potree.canvas.clientHeight; 322 323 var scene = Potree.currentScene; 324 var cam = scene.activeCamera; 325 cam.aspectRatio = Potree.canvas.clientWidth / Potree.canvas.clientHeight; 326 gl.viewport(0, 0, Potree.canvas.clientWidth, Potree.canvas.clientHeight); 327 var cColor = Potree.Settings.backgroundColor; 328 gl.clearColor(cColor.r, cColor.g, cColor.b, cColor.a); 329 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 330 331 Renderer.render(scene); 332 333 if(Potree.Settings.showGrid){ 334 Potree.gridSceneNode.render(cam); 335 } 336 337 // window.mozRequestAnimationFrame(Potree.draw); 338 // window.webkitRequestAnimationFrame (Potree.draw); 339 //setTimeout(Potree.draw, 0); 340 }; 341 342 343 Potree.mainLoop = function mainLoop(){ 344 Potree.calculateTimeSinceLastFrame(); 345 346 // var pcl = Potree.currentScene.rootNode.children["test"]; 347 // if(pcl != null){ 348 // pcl.rotateY(timeSinceLastFrame*0.7); 349 // } 350 351 Potree.update(timeSinceLastFrame); 352 Potree.draw(); 353 354 // with 0ms, interaction becomes a lot slower in firefox. 355 setTimeout(mainLoop, 10); 356 }; 357 358 var lastLoopTime = null; 359 var timeSinceLastFrame = null; 360 Potree.calculateTimeSinceLastFrame = function calculateTimeSinceLastFrame(){ 361 var newDrawTime = new Date().getTime(); 362 if (lastLoopTime != null) { 363 timeSinceLastFrame = (newDrawTime - lastLoopTime) / 1000.0; 364 }else{ 365 timeSinceLastFrame = 0; 366 } 367 lastLoopTime = new Date().getTime(); 368 369 }; 370 371 var fpsHistory = new Array(); 372 Potree.update = function update(time){ 373 374 var fps = 1 / time; 375 376 fpsHistory.push(fps); 377 if(fpsHistory.length > 10){ 378 fpsHistory.splice(0, 1); 379 } 380 var mean = 0; 381 for(var i = 0; i < fpsHistory.length; i++){ 382 mean += fpsHistory[i]; 383 } 384 mean = mean / fpsHistory.length; 385 386 Potree.currentScene.rootNode.addTime(time); 387 PointcloudOctreeNode.nodesLoadedThisFrame = 0; 388 389 Potree.camHandler.update(time); 390 391 var pcl = Potree.currentScene.rootNode["test"]; 392 if(pcl != null){ 393 pcl.rotateY(time); 394 } 395 }; 396 397 398 399 400 401 402 403 404 405 406