///////////////////////////////////////////////////////////////////// // Explorer viewer extension // by Philippe Leefsma, March 2015 // ///////////////////////////////////////////////////////////////////// AutodeskNamespace("Autodesk.ADN.Viewing.Extension"); Autodesk.ADN.Viewing.Extension.Explorer = function (viewer, options) { Autodesk.Viewing.Extension.call(this, viewer, options); var _self = this; var _viewer = viewer; ///////////////////////////////////////////////////////////////// // The Explorer tool // ///////////////////////////////////////////////////////////////// function ExplorerTool(viewer) { this.getNames = function() { return ["Autodesk.ADN.Viewing.Tool.ExplorerTool"]; }; this.getName = function() { return "Autodesk.ADN.Viewing.Tool.ExplorerTool"; }; ///////////////////////////////////////////////////////////// // called when tool is activated // ///////////////////////////////////////////////////////////// this.activate = function(name) { _viewer.navigation.setRequestHomeView(true); var position = _viewer.navigation.getPosition(); var target = _viewer.navigation.getTarget(); var worldUp = _viewer.navigation.getWorldUpVector(); var pt = { x: position.x - target.x, y: position.y - target.y, z: position.z - target.z } this.height = dotProduct(pt, worldUp); var rVect = getPerpendicularVector(worldUp); this.radius = dotProduct(pt, rVect); }; ///////////////////////////////////////////////////////////// // called when tool is deactivated // ///////////////////////////////////////////////////////////// this.deactivate = function(name) { this.activated = false; }; this.speed = 0.3; this.phase = "1"; this.switchPhase = true; ///////////////////////////////////////////////////////////// // update is called by the framework // t: time elapsed since tool activated in ms ///////////////////////////////////////////////////////////// this.update = function(t) { var target = _viewer.navigation.getTarget(); var worldUp = _viewer.navigation.getWorldUpVector(); var offset = Math.abs(Math.cos(this.speed * t * 0.001)); // create some effect to keep camera near object // while it orbits for a while if(offset < 0.01) { if(this.switchPhase) { this.switchPhase = false; if (this.phase === "1") { this.phase = "2"; } else if (this.phase === "2") { this.phase = "1"; } } } if(offset > 0.99) { this.switchPhase = true; } if(this.phase === "1") this.offset = offset; var height = this.height * (0.5 + 1.5 * this.offset); var radius = this.radius * (0.5 + 1.5 * this.offset); var center = { x: target.x + height * worldUp.x, y: target.y + height * worldUp.y, z: target.z + height * worldUp.z } var pos = computeCirclularTrajectory( this.speed * t * 0.001, radius, worldUp, center); _viewer.navigation.setPosition(pos); return false; }; ///////////////////////////////////////////////////////////// // utilities // ///////////////////////////////////////////////////////////// function crossProduct(u, v) { return { x: u.y * v.z - u.z * v.y, y: u.z * v.x - u.x * v.z, z: u.x * v.y - u.y * v.x } } function dotProduct(u, v) { return Math.abs( u.x * v.x + u.y * v.y + u.z * v.z); } function norm(v) { return Math.sqrt( v.x * v.x + v.y * v.y + v.z * v.z); } function getPerpendicularVector(v) { var u = { x: 0, y: 0, z: 0 }; if(v.x !== 0) u = { x: 0, y: 1, z: 0 }; else if(v.y !== 0) u = { x: 1, y: 0, z: 0 }; else u = { x: 1, y: 0, z: 0 }; return crossProduct(v, u); } function computeCirclularTrajectory(t, radius, normal, center) { // C: center, n: normal, u: perpendicular to n // p(t) = r.cos(t).u + r.sin(t).(n x u) + C var u = getPerpendicularVector(normal); var v = crossProduct(u, normal); var pos = { x: radius * Math.cos(t) * u.x + radius * Math.sin(t) * v.x + center.x, y: radius * Math.cos(t) * u.y + radius * Math.sin(t) * v.y + center.y, z: radius * Math.cos(t) * u.z + radius * Math.sin(t) * v.z + center.z }; return pos; } } ///////////////////////////////////////////////////////////////// // load callback // ///////////////////////////////////////////////////////////////// _self.load = function () { _self.tool = new ExplorerTool(_viewer); _viewer.toolController.registerTool(_self.tool); _viewer.toolController.activateTool(_self.tool.getName()); console.log('Autodesk.ADN.Viewing.Extension.Explorer loaded'); return true; }; ///////////////////////////////////////////////////////////////// // unload callback // ///////////////////////////////////////////////////////////////// _self.unload = function () { _viewer.toolController.deactivateTool(_self.tool.getName()); console.log('Autodesk.ADN.Viewing.Extension.Explorer unloaded'); return true; }; }; Autodesk.ADN.Viewing.Extension.Explorer.prototype = Object.create(Autodesk.Viewing.Extension.prototype); Autodesk.ADN.Viewing.Extension.Explorer.prototype.constructor = Autodesk.ADN.Viewing.Extension.Explorer; Autodesk.Viewing.theExtensionManager.registerExtension( 'Autodesk.ADN.Viewing.Extension.Explorer', Autodesk.ADN.Viewing.Extension.Explorer);