提交 cf944781 编写于 作者: B Bart McLeod

deleted files that are now in the VrmlParser project

上级 44b40287
/**
* @author Bart McLeod, mcleod@spaceweb.nl
* @since 2016-05-10
*
* The VrmlParser/Renderer/Console renders the node tree as text output to the console,
* so that one can see what it is parsing.
*/
module.exports = {
depth: 0,
decoration: '',
/**
* Render method, that takes the output from the VrmlParser as input and
* writes a textual representation of the node tree to the console.
*
* @param nodeTree
*/
render: function (tree) {
this.decoration = '';
// determine decoration base on depth
for (var j = 0; j < this.depth; j++) {
this.decoration += '-';
}
for (var a in tree) {
if ('string' === typeof a) {
var value = tree[a];
if ('object' === typeof value) {
this.depth++;
console.log(this.decoration + a);
this.render(value);
this.depth--;
} else {
console.log(this.decoration + a + ': ' + tree[a]);
}
}
}
}
};
此差异已折叠。
/**
* @author Bart McLeod, mcleod@spaceweb.nl
* @since May 25, 2016
*
* @todo: Understand http://threejs.org/docs/#Reference/Extras.Animation/AnimationHandler, this code might duplicate for example removing an animation from the update loop
*
* Adds animation and interaction support to the VrmlParser.Renderer.ThreeJs
*/
/**
* Offers support for interaction and animation.
*
* Currently support clicking an object and seeing a log message for that.
*
* Also, in debug mode, a blue line will be drawn from the perspective camera to the clicked point.
* You can see this line when zooming out after clicking and object.
*
* @param debug
* @constructor
*/
VrmlParser.Renderer.ThreeJs['Animation'] = function (debug) {
// use global camera, scene and renderer ( a weakness, I think )
this.debug = debug ? true : false;
this.animations = {};
};
VrmlParser.Renderer.ThreeJs.Animation.prototype = {
/**
* Updates or registered animations with a delta from the global clock.
*
* @param delta
*/
update: function (delta) {
for ( var a in this.animations ) {
if ( !this.animations.hasOwnProperty(a) ) {
continue;
}
var callback = this.animations[a];
callback(delta);
}
},
/**
* Register a callback for the animations, it will be called at each tick with a delta
* from the global clock.
*
* @param name
* @param callback
*/
addAnimation: function (name, callback) {
this.animations[name] = callback;
},
/**
* Unregister a callback for the animations.
* @param name
*/
removeAnimation: function (name) {
delete this.animations[name];
},
/**
* Gets all routes that were registered for a sensor in the original VRML world.
*
* Returned routes have a source and target object. Each have a name and event property.
*
* @param string name Name of the source node of the event.
* @returns {*}
*/
getRoutesForEvent: function (name) {
var routesRegistry = scene.userData.routes;
var routes = routesRegistry[name];
//this.log('The routes are:');
for ( var r = 0; r < routes.length; r++ ) {
//this.log(routes[r]);
}
return routes;
},
/**
* Recursively finds all targetroutes for a given route.
*
* @param triggerRoute
* @returns {boolean}
*/
findTargetRoutes: function (triggerRoute) {
var targetRoutes = [];
if ( 'undefined' === typeof triggerRoute ) {
return targetRoutes;
}
var routesRegistry = scene.userData.routes;
if ( 'undefined' === typeof routesRegistry[triggerRoute.target.name] ) {
// this is the leaf route
return triggerRoute;
}
// 1. Find first level of targetRoutes (they can be chained)
var routes = routesRegistry[triggerRoute.target.name];
// find all the target routes of intermediate routes
for ( var i = 0; i < routes.length; i++ ) {
var route = routes[i];
// verify if the route has yet another target (it is an intermediate route)
// 2. Find targetroutes of intermediate route, create a nested array
var nestedTargetRoutes = this.findTargetRoutes(route);
targetRoutes.push(nestedTargetRoutes);
}
// 3. Return targetroute
return targetRoutes;
},
/**
* Utility to easily switch logging on and off with the debug flag.
* @param obj
*/
log: function (obj) {
if ( this.debug ) {
console.log(obj);
}
},
/**
* Goes up the object tree recursively to find an object with an originalVrmlNode that is of a sensorType,
* for example a TouchSensor.
*
* @param Object3D the clicked shape.
* @param string sensorType
* @returns {boolean}|{string} name of the sensor or false.
*/
findSensor: function (object, sensorType) {
var scope = this;
/**
* Will find a sensor in the children of obj, if any.
*
* It will do so recursively going down the object tree.
* It will not search up the tree to avoid infinite recursion.
*
* @param obj
* @param sensorType
*/
function findSensorinChildrenOf(obj, sensorType) {
if ( undefined === obj.children ) {
return false;
}
for ( var b = 0; b < obj.children.length; b++ ) {
var checkNode = obj.children[b];
if ( undefined === checkNode ) {
continue;
}
var eventName;
// check this node
if ( 'undefined' !== typeof checkNode.userData.originalVrmlNode
&& sensorType === checkNode.userData.originalVrmlNode.node ) {
// find the first route, we only use TimeSensor to get from one to the next
eventName = checkNode.name;
scope.log(sensorType + ': ' + eventName);
return eventName;
}
// var foundItInChildren
//
// // recurse
// if ( foundItInChildren = findSensorinChildrenOf(checkNode, sensorType) ) {
// return foundItInChildren;
// }
}
return false;
}
if ( null === object ) {
this.log('Cannot find a sensor of type ' + sensorType + ' in null');
return false;
}
var foundItInChildren;
if ( foundItInChildren = findSensorinChildrenOf(object, sensorType) ) {
return foundItInChildren;
}
this.log('No ' + sensorType + ' found amongst the children of the following node:');
this.log(object);
if ( 'undefined' === typeof object.parent || null === object.parent ) {
this.log('We cannot go up the tree any further');
// we're out of parents, there's not a single sensorType to be found here.
return false;
}
this.log('Searching up the tree');
// not found in the parent object, look in its parent in turn (go up the object tree recursively)
return this.findSensor(object.parent, sensorType);
},
// @todo: support more interactions than just clicking
/**
* Support clicking the scene.
*
* If an object is clicked, it will show up in here. If a handler was registered for it,
* we can execute the handler.
*
* Handlers will be registered by parsing VRML ROUTES for TouchSensors.
*
* Example:
* ROUTE klikopdeur.touchTime TO TimeSource.startTime
* ROUTE TimeSource.fraction_changed TO Deuropen.set_fraction
* ROUTE Deuropen.value_changed TO deur.rotation
*
* @todo: translate event names to English, so that they make sense to people who are not able to read Dutch
* The example is a three-step animation script:
* 1. The touchTime of the touch sensor is routed to the time source. We can translate this step, since we have
* a clock and a click event
*/
addClickSupport: function (camera, renderer) {
var localCamera = camera;
var localRenderer = renderer;
// clicking: enable clicking on the screen to interact with objects in the 3D world
projector = new THREE.Projector();
var line;
var scope = this;
renderer.domElement.addEventListener('mousedown', function (event) {
// use global camera, scene and renderer
var x = event.offsetX == undefined ? event.layerX : event.offsetX;
var y = event.offsetY == undefined ? event.layerY : event.offsetY;
var vector = new THREE.Vector3();
vector.set(( x / localRenderer.domElement.width ) * 2 - 1, -( y / localRenderer.domElement.height ) * 2 + 1, 0.5);
vector.unproject(localCamera);
var raycaster = new THREE.Raycaster(localCamera.position, vector.sub(localCamera.position).normalize());
var objects = scene.children;
var intersects = raycaster.intersectObjects(objects, true);
if ( intersects.length ) {
var firstIntersect = intersects[0].object;
var touch = scope.findSensor(firstIntersect, 'TouchSensor');
if ( false === touch ) {
// no touch sensor found
return;
}
// work on a clone [slice(0)] of the routes, otherwise, using pop() will make the array useless for next time
var routes = scope.getRoutesForEvent(touch).slice(0);
// naive, only use first
var targetRoutes = scope.findTargetRoutes(routes.pop());
// again, naive (good usecase for map reduce?
var targetRoute = targetRoutes;
while ( 'function' === typeof targetRoute.pop ) {
targetRoute = targetRoute.pop();
if ( 'undefined' === typeof targetRoute ) {
scope.log('no target route found for ' + touch);
return;
}
}
// we found the leaf targetRoute
scope.log(targetRoute);
var originalNode = scene.getObjectByName(targetRoute.source.name).userData.originalVrmlNode;
// any supported interpolator will work, for now, only OrientationInterpolator
if ( undefined === VrmlParser.Renderer.ThreeJs.Animation[originalNode.node] ) {
scope.log(originalNode.node + ' is not yet supported');
return;
}
var interpolator = new VrmlParser.Renderer.ThreeJs.Animation[originalNode.node](originalNode, scope.debug);
var name = 'surrounding_' + targetRoute.target.name;
var target = scene.getObjectByName(name);
// cleanup method for when the callback wants to be removed because it's done.
var finish = function () {
scope.removeAnimation(touch);
};
var callback = interpolator.getCallback(target, finish);
scope.addAnimation(touch, callback);
}
// drawing a line for diagnostic purposes.
// keep this disabled, unless you really, really need it.
// The problem is: the line can prevent finding your sensor if the line is clicked instead of your object.
// if ( true === scope.debug ) {
// // draw a line where the object was clicked
// if ( null !== line ) {
// scene.remove(line);
// }
//
// var lineMaterial = new THREE.LineBasicMaterial({
// color: 0x0000ff
// });
// var geometry = new THREE.Geometry();
//
// geometry.vertices.push(new THREE.Vector3(raycaster.ray.origin.x, raycaster.ray.origin.y, raycaster.ray.origin.z));
// geometry.vertices.push(new THREE.Vector3(raycaster.ray.origin.x + (raycaster.ray.direction.x * 100000), raycaster.ray.origin.y + (raycaster.ray.direction.y * 100000), raycaster.ray.origin.z + (raycaster.ray.direction.z * 100000)));
// line = new THREE.Line(geometry, lineMaterial);
// scene.add(line);
// // / draw a line
// }
}
,
false
);
// / clicking
}
};
/**
* @author Bart McLeod, mcleod@spaceweb.nl
* @since May 25, 2016
*
* Adds animation and interaction support to the VrmlParser.Renderer.ThreeJs
* @todo: take time into account
*/
/**
* The OrientationInterpolator wraps the essential properties of its original VRML node counterpart
* and adds functionality to support animation in Three.js.
*
* @param originalNode
* @constructor
*/
VrmlParser.Renderer.ThreeJs.Animation['OrientationInterpolator'] = function (originalNode, debug) {
this.key = originalNode.key;
this.keyValue = originalNode.keyValue;
this.debug = debug ? true : false;
// assumption that the object is already at keyValue[0], so start rotating toward keyValue[1]
this.index = 1;
this.finish = null;
this.target = null;
this.tweenObj = null;
}
VrmlParser.Renderer.ThreeJs.Animation.OrientationInterpolator.prototype = {
/**
* Utility to easily switch logging on and off with the debug flag.
* @param obj
*/
log: function (obj) {
if ( this.debug ) {
console.log(obj);
}
},
/**
* Runs when one tween completes and starts the next
*/
complete: function () {
// take next key or finish
this.index++;
if ( this.index >= this.keyValue.length ) {
this.log('finish at index ' + this.index);
this.finish();
return;
}
this.tween();
},
tween: function () {
var scope = this;
//this.log('tweening for ' + this.index);
var r = this.keyValue[this.index];
var endRadians = r.radians;
this.log('Animating from ' + this.target.rotation.y + ' to ' + endRadians);
var endQuaternion = new THREE.Quaternion();
var vector3 = new THREE.Vector3(r.x, r.y, r.z);
endQuaternion.setFromAxisAngle(vector3, endRadians);
this.tweenObj = new TWEEN
.Tween(this.target.quaternion)
.to(endQuaternion)
.start(+new Date())
.onComplete(function () {
scope.complete();
});
;
},
/**
* Gets the animation callback method, which can play the animation associated with this OrientationInterpolator.
* @param Object3D target
* @param callable finish A method that will be called when the callback is ready to be removed
*/
getCallback: function (target, finish) {
var scope = this;
// what to animate:
this.target = target;
// what to do after completion
this.finish = finish;
// trigger the animation
this.tween();
/**
* The animation callback
*
* @param float delta time difference
* @param callable finish will be called by the callback when it is ready to be removed
*/
var callback = function (delta) {
scope.tweenObj.update(+new Date());
};
return callback;
}
};
/**
* @author Bart McLeod, mcleod@spaceweb.nl
* @since May 25, 2016
*
* Adds animation and interaction support to the VrmlParser.Renderer.ThreeJs
* @todo: take time into account
*/
// we use below notation to create exports for the Google closure compiler
/**
* The OrientationInterpolator wraps the essential properties of its original VRML node counterpart
* and adds functionality to support animation in Three.js.
*
* @param originalNode
* @constructor
*/
VrmlParser.Renderer.ThreeJs.Animation['PositionInterpolator'] = function (originalNode, debug) {
this.key = originalNode.key;
this.keyValue = originalNode.keyValue;
this.debug = debug ? true : false;
}
VrmlParser.Renderer.ThreeJs.Animation.PositionInterpolator.prototype = {
/**
* Utility to easily switch logging on and off with the debug flag.
* @param obj
*/
log: function (obj) {
if ( this.debug ) {
console.log(obj);
}
},
tween: function (target, endPosition) {
return new TWEEN
.Tween(target.position)
.to(endPosition)
.start(+new Date())
;
},
/**
* Gets the animation callback method, which can play the animation associated with this OrientationInterpolator.
* @param Object3D target
* @param callable finish A method that will be called when the callback is ready to be removed
*/
getCallback: function (target, finish) {
var scope = this;
// assumption that the first position is the position the target is already at, so we start with the next
var index = 1;
var p = this.getPosition(index);
this.log(p);
this.log(target);
var tween = this.tween(target, p);
tween.onComplete(function () {
// take next key or finish
index++;
if ( index >= scope.keyValue.length ) {
console.log('finish');
// now make the end position of the target exactly the same as p, to correct any rounding errors from tweening
target.position = p;
finish();
return;
}
p = scope.getPosition(index);
scope.log(p);
tween = scope.tween(target, p);
tween.onComplete = this;
});
/**
* The animation callback
*
* @param float delta time difference
* @param callable finish will be called by the callback when it is ready to be removed
*/
var callback = function (delta) {
tween.update(+new Date());
};
return callback;
},
getPosition: function (index) {
var v = this.keyValue[index];
return new THREE.Vector3(v.x, v.y, v.z);
}
};
VrmlParser.Renderer.ThreeJs['VrmlNode'] = VrmlParser.Renderer.ThreeJs.VrmlNode || {};
/**
* @author Bart McLeod, mcleod@spaceweb.nl
* @since September 20, 2016
*
* Conversion of a VRML 97 NavigationInfo node to a ThreeJs camera
*/
VrmlParser.Renderer.ThreeJs.VrmlNode[ 'NavigationInfo' ] = function (originalNode, debug) {
this.debug = debug;
this.node = originalNode;
this.node.has = function (property) {
return ('undefined' !== typeof this[ property ] && null !== this[ property ]);
};
this.controls = null;
};
VrmlParser.Renderer.ThreeJs.VrmlNode.NavigationInfo.prototype = {
/**
* Utility to easily switch logging on and off with the debug flag.
* @param obj
*/
log: function (obj) {
if ( this.debug ) {
console.log(obj);
}
},
/**
* Uses the NavigationInfo from the original VRML to determine the best
* match for controls in ThreeJs.
*
* @todo: Figure out of support for avatarSize is possible
* @todo: Support for headlight
* @todo: Figure out if visibilityLimit can be implemented, could this be the 'far' property of the camera?
* @todo: Create controls that mimic the original design of VRML better.
* @param scene
*/
parse: function (scene) {
this.log('From NavigationInfo');
var speed = undefined !== this.node.speed ? this.node.speed : 1;
if ( undefined !== this.node.type ) {
switch ( this.node.type.toLowerCase() ) {
case 'fly': // fly
this.log('fly!');
// use global controls and camera, no better solution at hand
controls = new THREE.FlyControls(camera);
controls.movementSpeed = speed;
break;
}
} else {
this.log('fly!');
// use global controls and camera, no better solution at hand
controls = new THREE.FlyControls(camera);
controls.movementSpeed = speed;
}
/** Example of originalNode
* avatarSize [ 0.1, 1.6, 0.2,]
* headlight FALSE
* speed 4
* type "FLY"
* visibilityLimit 0.0
*/
}
}
/**
* @author Bart McLeod, mcleod@spaceweb.nl
* @since September 1, 2016
*
* Conversion of a VRML 97 Viewpoint node to a ThreeJs camera
*/
VrmlParser.Renderer.ThreeJs.VrmlNode['Viewpoint'] = function (originalNode, debug) {
this.debug = debug;
this.node = originalNode;
this.node.has = function (property) {
return ('undefined' !== typeof this[property] && null !== this[property]);
};
};
VrmlParser.Renderer.ThreeJs.VrmlNode.Viewpoint.prototype = {
/**
* Utility to easily switch logging on and off with the debug flag.
* @param obj
*/
log: function (obj) {
if ( this.debug ) {
console.log(obj);
}
},
parse: function (scene) {
var fov, aspect, near, far;
fov = Math.round(180 / Math.PI * this.node.fieldOfView);
aspect = window.innerWidth / window.innerHeight;
near = 0.01;
far = 1e5;
// @todo: support for jump (bool)
var camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
var surroundingGroup = new THREE.Group();
surroundingGroup.add(camera);
if ( this.node.has('name') ) {
camera.name = this.node.name;
} else {
camera.name = this.node.description;
}
surroundingGroup.getCamera = function () {
return this.children[0];
}
var p = this.node.position;
surroundingGroup.position.set(p.x, p.y, p.z);
var o = this.node.orientation;
var vector3 = new THREE.Vector3(o.x, o.y, o.z);
surroundingGroup.quaternion.setFromAxisAngle(vector3, o.radians);
return surroundingGroup;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册