diff --git a/README.md b/README.md index 13c06fd9..f19f5bea 100644 --- a/README.md +++ b/README.md @@ -31,5 +31,5 @@ Checkout [utils/README.md](utils/README.md) for details on building. ros3djs is released with a BSD license. For full terms and conditions, see the [LICENSE](LICENSE) file. ### Authors -See the [AUTHORS.md](AUTHORS) file for a full list of contributors. +See the [AUTHORS.md](AUTHORS.md) file for a full list of contributors. diff --git a/build/ros3d.js b/build/ros3d.js index 6401affc..c582330a 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -168,6 +168,321 @@ ROS3D.closestAxisPoint = function(axisRay, camera, mousePos) { return ROS3D.findClosestPoint(axisRay, mpRay); }; +/** + * @author Julius Kammerl - jkammerl@willowgarage.com + */ + +/** + * The DepthCloud object. + * + * @constructor + * @param options - object with following keys: + * * f - The camera's focal length + * * pointSize - Point size (pixels) for rendered point cloud + * * width, height - Dimensions of the video stream + * * whiteness - Blends rgb values to white (0..100) + * * varianceThreshold - Threshold for variance filter, used for compression artifact removal + */ +ROS3D.DepthCloud = function(options) { + + THREE.Object3D.call(this); + + // /////////////////////////// + // depth cloud options + // /////////////////////////// + + this.url = options.url; + // f defaults to standard Kinect calibration + this.f = (options.f !== undefined) ? options.f : 526; + this.pointSize = (options.pointSize !== undefined) ? options.pointSize : 3; + this.width = (options.width !== undefined) ? options.width : 1024; + this.height = (options.height !== undefined) ? options.height : 1024; + this.whiteness = (options.whiteness !== undefined) ? options.whiteness : 0; + this.varianceThreshold = (options.varianceThreshold !== undefined) ? options.varianceThreshold : 0.000016667; + + var metaLoaded = false; + this.video = document.createElement('video'); + + this.video.addEventListener('loadedmetadata', this.metaLoaded.bind(this), false); + + this.video.loop = true; + this.video.src = this.url; + this.video.crossOrigin = 'Anonymous'; + this.video.setAttribute('crossorigin', 'Anonymous'); + + // /////////////////////////// + // load shaders + // /////////////////////////// + this.vertex_shader = [ + 'uniform sampler2D map;', + '', + 'uniform float width;', + 'uniform float height;', + 'uniform float nearClipping, farClipping;', + '', + 'uniform float pointSize;', + 'uniform float zOffset;', + '', + 'uniform float focallength;', + '', + 'varying vec2 vUvP;', + 'varying vec2 colorP;', + '', + 'varying float depthVariance;', + 'varying float maskVal;', + '', + 'float sampleDepth(vec2 pos)', + ' {', + ' float depth;', + ' ', + ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', + ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', + ' ', + ' vec4 depthColor = texture2D( map, vUv );', + ' ', + ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', + ' ', + ' if (depth>0.99)', + ' {', + ' vec4 depthColor2 = texture2D( map, vUv2 );', + ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', + ' depth = 0.99+depth2;', + ' }', + ' ', + ' return depth;', + ' }', + '', + 'float median(float a, float b, float c)', + ' {', + ' float r=a;', + ' ', + ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', + ' {', + ' vec2 smp = decodeDepth(vec2(position.x, position.y));', + ' float depth = smp.x;', + ' depthVariance = smp.y;', + ' ', + ' float z = -depth;', + ' ', + ' pos = vec4(', + ' ( position.x / width - 0.5 ) * z * (1000.0/focallength) * -1.0,', + ' ( position.y / height - 0.5 ) * z * (1000.0/focallength),', + ' (- z + zOffset / 1000.0) * 2.0,', + ' 1.0);', + ' ', + ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', + ' vec4 maskColor = texture2D( map, maskP );', + ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', + ' }', + ' ', + ' gl_PointSize = pointSize;', + ' gl_Position = projectionMatrix * modelViewMatrix * pos;', + ' ', + '}' + ].join('\n'); + + this.fragment_shader = [ + 'uniform sampler2D map;', + 'uniform float varianceThreshold;', + 'uniform float whiteness;', + '', + 'varying vec2 vUvP;', + 'varying vec2 colorP;', + '', + 'varying float depthVariance;', + 'varying float maskVal;', + '', + '', + 'void main() {', + ' ', + ' vec4 color;', + ' ', + ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', + ' { ', + ' discard;', + ' }', + ' else ', + ' {', + ' color = texture2D( map, colorP );', + ' ', + ' float fader = whiteness /100.0;', + ' ', + ' color.r = color.r * (1.0-fader)+ fader;', + ' ', + ' color.g = color.g * (1.0-fader)+ fader;', + ' ', + ' color.b = color.b * (1.0-fader)+ fader;', + ' ', + ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', + ' }', + ' ', + ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', + ' ', + '}' + ].join('\n'); +}; +ROS3D.DepthCloud.prototype.__proto__ = THREE.Object3D.prototype; + +/* + * Callback called when video metadata is ready + */ +ROS3D.DepthCloud.prototype.metaLoaded = function() { + this.metaLoaded = true; + this.initStreamer(); +}; + +/* + * Callback called when video metadata is ready + */ +ROS3D.DepthCloud.prototype.initStreamer = function() { + + if (this.metaLoaded) { + this.texture = new THREE.Texture(this.video); + this.geometry = new THREE.Geometry(); + + for (var i = 0, l = this.width * this.height; i < l; i++) { + + var vertex = new THREE.Vector3(); + vertex.x = (i % this.width); + vertex.y = Math.floor(i / this.width); + + this.geometry.vertices.push(vertex); + } + + this.material = new THREE.ShaderMaterial({ + + uniforms : { + + 'map' : { + type : 't', + value : this.texture + }, + 'width' : { + type : 'f', + value : this.width + }, + 'height' : { + type : 'f', + value : this.height + }, + 'focallength' : { + type : 'f', + value : this.f + }, + 'pointSize' : { + type : 'f', + value : this.pointSize + }, + 'zOffset' : { + type : 'f', + value : 0 + }, + 'whiteness' : { + type : 'f', + value : this.whiteness + }, + 'varianceThreshold' : { + type : 'f', + value : this.varianceThreshold + } + }, + vertexShader : this.vertex_shader, + fragmentShader : this.fragment_shader + // depthWrite: false + + }); + + this.mesh = new THREE.ParticleSystem(this.geometry, this.material); + this.mesh.position.x = 0; + this.mesh.position.y = 0; + this.add(this.mesh); + + var that = this; + + setInterval(function() { + if (that.video.readyState === that.video.HAVE_ENOUGH_DATA) { + that.texture.needsUpdate = true; + } + }, 1000 / 30); + } +}; + +/* + * Start video playback + */ +ROS3D.DepthCloud.prototype.startStream = function() { + this.video.play(); +}; + +/* + * Stop video playback + */ +ROS3D.DepthCloud.prototype.stopStream = function() { + this.video.stop(); +}; + /** * @author David Gossow - dgossow@willowgarage.com */ @@ -2123,7 +2438,7 @@ ROS3D.Viewer = function(options) { }); /** - * Renders the associated scene to the that. + * Renders the associated scene to the viewer. */ function draw() { // update the controls diff --git a/build/ros3d.min.js b/build/ros3d.min.js index 6c8c8ed8..d2bf77e5 100644 --- a/build/ros3d.min.js +++ b/build/ros3d.min.js @@ -1,2 +1,2 @@ -var ROS3D=ROS3D||{REVISION:"4"};ROS3D.MARKER_ARROW=0,ROS3D.MARKER_CUBE=1,ROS3D.MARKER_SPHERE=2,ROS3D.MARKER_CYLINDER=3,ROS3D.MARKER_LINE_STRIP=4,ROS3D.MARKER_LINE_LIST=5,ROS3D.MARKER_CUBE_LIST=6,ROS3D.MARKER_SPHERE_LIST=7,ROS3D.MARKER_POINTS=8,ROS3D.MARKER_TEXT_VIEW_FACING=9,ROS3D.MARKER_MESH_RESOURCE=10,ROS3D.MARKER_TRIANGLE_LIST=11,ROS3D.INTERACTIVE_MARKER_KEEP_ALIVE=0,ROS3D.INTERACTIVE_MARKER_POSE_UPDATE=1,ROS3D.INTERACTIVE_MARKER_MENU_SELECT=2,ROS3D.INTERACTIVE_MARKER_BUTTON_CLICK=3,ROS3D.INTERACTIVE_MARKER_MOUSE_DOWN=4,ROS3D.INTERACTIVE_MARKER_MOUSE_UP=5,ROS3D.INTERACTIVE_MARKER_NONE=0,ROS3D.INTERACTIVE_MARKER_MENU=1,ROS3D.INTERACTIVE_MARKER_BUTTON=2,ROS3D.INTERACTIVE_MARKER_MOVE_AXIS=3,ROS3D.INTERACTIVE_MARKER_MOVE_PLANE=4,ROS3D.INTERACTIVE_MARKER_ROTATE_AXIS=5,ROS3D.INTERACTIVE_MARKER_MOVE_ROTATE=6,ROS3D.INTERACTIVE_MARKER_INHERIT=0,ROS3D.INTERACTIVE_MARKER_FIXED=1,ROS3D.INTERACTIVE_MARKER_VIEW_FACING=2,ROS3D.makeColorMaterial=function(e,t,r,i){var o=new THREE.Color;return o.setRGB(e,t,r),.99>=i?new THREE.MeshBasicMaterial({color:o.getHex(),opacity:i+.1,transparent:!0,depthWrite:!0,blendSrc:THREE.SrcAlphaFactor,blendDst:THREE.OneMinusSrcAlphaFactor,blendEquation:THREE.ReverseSubtractEquation,blending:THREE.NormalBlending}):new THREE.MeshLambertMaterial({color:o.getHex(),opacity:i,blending:THREE.NormalBlending})},ROS3D.intersectPlane=function(e,t,r){var i=new THREE.Vector3,o=new THREE.Vector3;i.subVectors(t,e.origin);var n=e.direction.dot(r);if(Math.abs(n)=Math.abs(h))return void 0;var d=n*a-s*c,p=d/h;return p},ROS3D.closestAxisPoint=function(e,t,r){var i=new THREE.Projector,o=e.origin.clone();i.projectVector(o,t);var n=e.direction.clone().add(e.origin);i.projectVector(n,t);var a=n.clone().sub(o),s=new THREE.Vector2,c=s.subVectors(r,o).dot(a)/a.dot(a),l=new THREE.Vector2;l.addVectors(o,a.clone().multiplyScalar(c));var h=new THREE.Vector3(l.x,l.y,.5);i.unprojectVector(h,t);var d=new THREE.Ray(t.position,h.sub(t.position).normalize());return ROS3D.findClosestPoint(e,d)},ROS3D.InteractiveMarker=function(e){THREE.Object3D.call(this),THREE.EventDispatcher.call(this);var t=this;e=e||{};var r=e.handle;this.name=r.name;var i=e.camera,o=e.path||"/";this.dragging=!1,this.onServerSetPose({pose:r.pose}),this.dragStart={position:new THREE.Vector3,orientation:new THREE.Quaternion,positionWorld:new THREE.Vector3,orientationWorld:new THREE.Quaternion,event3d:{}},r.controls.forEach(function(e){t.add(new ROS3D.InteractiveMarkerControl({parent:t,message:e,camera:i,path:o}))}),r.menuEntries.length>0&&(this.menu=new ROS3D.InteractiveMarkerMenu({menuEntries:r.menuEntries}),this.menu.addEventListener("menu-select",function(e){t.dispatchEvent(e)}))},ROS3D.InteractiveMarker.prototype.__proto__=THREE.Object3D.prototype,ROS3D.InteractiveMarker.prototype.showMenu=function(e,t){this.menu&&this.menu.show(e,t)},ROS3D.InteractiveMarker.prototype.moveAxis=function(e,t,r){if(this.dragging){var i=e.currentControlOri,o=t.clone().applyQuaternion(i),n=this.dragStart.event3d.intersection.point,a=o.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),s=new THREE.Ray(n,a),c=ROS3D.closestAxisPoint(s,r.camera,r.mousePos),l=new THREE.Vector3;l.addVectors(this.dragStart.position,o.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(c)),this.setPosition(e,l),r.stopPropagation()}},ROS3D.InteractiveMarker.prototype.movePlane=function(e,t,r){if(this.dragging){var i=e.currentControlOri,o=t.clone().applyQuaternion(i),n=this.dragStart.event3d.intersection.point,a=o.clone().applyQuaternion(this.dragStart.orientationWorld),s=ROS3D.intersectPlane(r.mouseRay,n,a),c=new THREE.Vector3;c.subVectors(s,n),c.add(this.dragStart.positionWorld),this.setPosition(e,c),r.stopPropagation()}},ROS3D.InteractiveMarker.prototype.rotateAxis=function(e,t,r){if(this.dragging){e.updateMatrixWorld();var i=e.currentControlOri,o=i.clone().multiply(t.clone()),n=new THREE.Vector3(1,0,0).applyQuaternion(o),a=this.dragStart.event3d.intersection.point,s=n.applyQuaternion(this.dragStart.orientationWorld),c=ROS3D.intersectPlane(r.mouseRay,a,s),l=new THREE.Ray(this.dragStart.positionWorld,s),h=ROS3D.intersectPlane(l,a,s),d=this.dragStart.orientationWorld.clone().multiply(o),p=d.clone().inverse();c.sub(h),c.applyQuaternion(p);var u=this.dragStart.event3d.intersection.point.clone();u.sub(h),u.applyQuaternion(p);var E=Math.atan2(c.y,c.z),R=Math.atan2(u.y,u.z),m=R-E,v=new THREE.Quaternion;v.setFromAxisAngle(n,m),this.setOrientation(e,v.multiply(this.dragStart.orientationWorld)),r.stopPropagation()}},ROS3D.InteractiveMarker.prototype.feedbackEvent=function(e,t){this.dispatchEvent({type:e,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:t.name})},ROS3D.InteractiveMarker.prototype.startDrag=function(e,t){if(0===t.domEvent.button){t.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var r=new THREE.Vector3;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,r),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=t,this.feedbackEvent("user-mousedown",e)}},ROS3D.InteractiveMarker.prototype.stopDrag=function(e,t){0===t.domEvent.button&&(t.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",e))},ROS3D.InteractiveMarker.prototype.buttonClick=function(e,t){t.stopPropagation(),this.feedbackEvent("user-button-click",e)},ROS3D.InteractiveMarker.prototype.setPosition=function(e,t){this.position=t,this.feedbackEvent("user-pose-change",e)},ROS3D.InteractiveMarker.prototype.setOrientation=function(e,t){t.normalize(),this.quaternion=t,this.feedbackEvent("user-pose-change",e)},ROS3D.InteractiveMarker.prototype.onServerSetPose=function(e){if(void 0!==e)if(this.dragging)this.bufferedPoseEvent=e;else{var t=e.pose;this.position.x=t.position.x,this.position.y=t.position.y,this.position.z=t.position.z,this.useQuaternion=!0,this.quaternion=new THREE.Quaternion(t.orientation.x,t.orientation.y,t.orientation.z,t.orientation.w),this.updateMatrixWorld(!0)}},ROS3D.InteractiveMarkerClient=function(e){e=e||{},this.ros=e.ros,this.tfClient=e.tfClient,this.topic=e.topic,this.path=e.path||"/",this.camera=e.camera,this.rootObject=e.rootObject||new THREE.Object3D,this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.topic&&this.subscribe(this.topic)},ROS3D.InteractiveMarkerClient.prototype.subscribe=function(e){this.unsubscribe(),this.updateTopic=new ROSLIB.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdate.bind(this)),this.feedbackTopic=new ROSLIB.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new ROSLIB.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new ROSLIB.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))},ROS3D.InteractiveMarkerClient.prototype.unsubscribe=function(){this.updateTopic&&this.updateTopic.unsubscribe(),this.feedbackTopic&&this.feedbackTopic.unadvertise();for(var e in this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}},ROS3D.InteractiveMarkerClient.prototype.processInit=function(e){var t=e.msg;t.erases=[];for(var r in this.interactiveMarkers)t.erases.push(r);t.poses=[],this.processUpdate(t)},ROS3D.InteractiveMarkerClient.prototype.processUpdate=function(e){var t=this;e.erases.forEach(function(e){t.eraseIntMarker(e)}),e.poses.forEach(function(e){var r=t.interactiveMarkers[e.name];r&&r.setPoseFromServer(e.pose)}),e.markers.forEach(function(e){var r=t.interactiveMarkers[e.name];r&&t.eraseIntMarker(r.name);var i=new ROS3D.InteractiveMarkerHandle({message:e,feedbackTopic:t.feedbackTopic,tfClient:t.tfClient});t.interactiveMarkers[e.name]=i;var o=new ROS3D.InteractiveMarker({handle:i,camera:t.camera,path:t.path});o.name=e.name,t.rootObject.add(o),i.on("pose",function(e){o.onServerSetPose({pose:e})}),o.addEventListener("user-pose-change",i.setPoseFromClient.bind(i)),o.addEventListener("user-mousedown",i.onMouseDown.bind(i)),o.addEventListener("user-mouseup",i.onMouseUp.bind(i)),o.addEventListener("user-button-click",i.onButtonClick.bind(i)),o.addEventListener("menu-select",i.onMenuSelect.bind(i)),i.subscribeTf()})},ROS3D.InteractiveMarkerClient.prototype.eraseIntMarker=function(e){this.interactiveMarkers[e]&&(this.rootObject.remove(this.rootObject.getChildByName(e)),delete this.interactiveMarkers[e])},ROS3D.InteractiveMarkerControl=function(e){function t(e){e.stopPropagation()}var r=this;THREE.Object3D.call(this),THREE.EventDispatcher.call(this),e=e||{},this.parent=e.parent;var i=e.message;this.name=i.name,this.camera=e.camera,this.path=e.path||"/",this.dragging=!1;var o=new THREE.Quaternion(i.orientation.x,i.orientation.y,i.orientation.z,i.orientation.w);o.normalize();var n=new THREE.Vector3(1,0,0);switch(n.applyQuaternion(o),this.currentControlOri=new THREE.Quaternion,i.interaction_mode){case ROS3D.INTERACTIVE_MARKER_MOVE_AXIS:this.addEventListener("mousemove",this.parent.moveAxis.bind(this.parent,this,n)),this.addEventListener("touchmove",this.parent.moveAxis.bind(this.parent,this,n));break;case ROS3D.INTERACTIVE_MARKER_ROTATE_AXIS:this.addEventListener("mousemove",this.parent.rotateAxis.bind(this.parent,this,o));break;case ROS3D.INTERACTIVE_MARKER_MOVE_PLANE:this.addEventListener("mousemove",this.parent.movePlane.bind(this.parent,this,n));break;case ROS3D.INTERACTIVE_MARKER_BUTTON:this.addEventListener("click",this.parent.buttonClick.bind(this.parent,this));break;default:}i.interaction_mode!==ROS3D.INTERACTIVE_MARKER_NONE&&(this.addEventListener("mousedown",this.parent.startDrag.bind(this.parent,this)),this.addEventListener("mouseup",this.parent.stopDrag.bind(this.parent,this)),this.addEventListener("contextmenu",this.parent.showMenu.bind(this.parent,this)),this.addEventListener("mouseover",t),this.addEventListener("mouseout",t),this.addEventListener("click",t),this.addEventListener("touchstart",function(e){console.log(e.domEvent),1===e.domEvent.touches.length&&(e.type="mousedown",e.domEvent.button=0,r.dispatchEvent(e))}),this.addEventListener("touchmove",function(e){1===e.domEvent.touches.length&&(console.log(e.domEvent),e.type="mousemove",e.domEvent.button=0,r.dispatchEvent(e))}),this.addEventListener("touchend",function(e){0===e.domEvent.touches.length&&(e.domEvent.button=0,e.type="mouseup",r.dispatchEvent(e),e.type="click",r.dispatchEvent(e))}));var a=new THREE.Quaternion,s=this.parent.position.clone().multiplyScalar(-1);switch(i.orientation_mode){case ROS3D.INTERACTIVE_MARKER_INHERIT:a=this.parent.quaternion.clone().inverse(),this.updateMatrixWorld=function(e){ROS3D.InteractiveMarkerControl.prototype.updateMatrixWorld.call(r,e),r.currentControlOri.copy(r.quaternion),r.currentControlOri.normalize()};break;case ROS3D.INTERACTIVE_MARKER_FIXED:this.updateMatrixWorld=function(e){r.useQuaternion=!0,r.quaternion=r.parent.quaternion.clone().inverse(),r.updateMatrix(),r.matrixWorldNeedsUpdate=!0,ROS3D.InteractiveMarkerControl.prototype.updateMatrixWorld.call(r,e),r.currentControlOri.copy(r.quaternion)};break;case ROS3D.INTERACTIVE_MARKER_VIEW_FACING:var c=i.independentMarkerOrientation;this.updateMatrixWorld=function(e){r.camera.updateMatrixWorld();var t=(new THREE.Matrix4).extractRotation(r.camera.matrixWorld),i=new THREE.Matrix4,o=.5*Math.PI,n=new THREE.Vector3(-o,0,o);i.setRotationFromEuler(n);var a=new THREE.Matrix4;a.getInverse(r.parent.matrixWorld),t.multiplyMatrices(t,i),t.multiplyMatrices(a,t),r.currentControlOri.setFromRotationMatrix(t),c||(r.useQuaternion=!0,r.quaternion.copy(r.currentControlOri),r.updateMatrix(),r.matrixWorldNeedsUpdate=!0),ROS3D.InteractiveMarkerControl.prototype.updateMatrixWorld.call(r,e)};break;default:console.error("Unkown orientation mode: "+i.orientation_mode)}i.markers.forEach(function(e){var t=new ROS3D.Marker({message:e,path:r.path});""!==e.header.frame_id&&(t.position.add(s),t.position.applyQuaternion(a),t.quaternion.multiplyQuaternions(a,t.quaternion),t.updateMatrixWorld()),r.add(t)})},ROS3D.InteractiveMarkerControl.prototype.__proto__=THREE.Object3D.prototype,ROS3D.InteractiveMarkerHandle=function(e){e=e||{},this.message=e.message,this.feedbackTopic=e.feedbackTopic,this.tfClient=e.tfClient,this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new ROSLIB.Transform,this.pose=new ROSLIB.Pose,this.setPoseFromServer(this.message.pose)},ROS3D.InteractiveMarkerHandle.prototype.__proto__=EventEmitter2.prototype,ROS3D.InteractiveMarkerHandle.prototype.subscribeTf=function(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdate.bind(this))},ROS3D.InteractiveMarkerHandle.prototype.emitServerPoseUpdate=function(){var e=new ROSLIB.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)},ROS3D.InteractiveMarkerHandle.prototype.setPoseFromServer=function(e){this.pose=new ROSLIB.Pose(e),this.emitServerPoseUpdate()},ROS3D.InteractiveMarkerHandle.prototype.tfUpdate=function(e){this.tfTransform=new ROSLIB.Transform(e),this.emitServerPoseUpdate()},ROS3D.InteractiveMarkerHandle.prototype.setPoseFromClient=function(e){this.pose=new ROSLIB.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),this.pose.applyTransform(t),this.sendFeedback(ROS3D.INTERACTIVE_MARKER_POSE_UPDATE,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))},ROS3D.InteractiveMarkerHandle.prototype.onButtonClick=function(e){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_BUTTON_CLICK,e.clickPosition,0,e.controlName)},ROS3D.InteractiveMarkerHandle.prototype.onMouseDown=function(e){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_MOUSE_DOWN,e.clickPosition,0,e.controlName),this.dragging=!0},ROS3D.InteractiveMarkerHandle.prototype.onMouseUp=function(e){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_MOUSE_UP,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)},ROS3D.InteractiveMarkerHandle.prototype.onMenuSelect=function(e){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_MENU_SELECT,void 0,e.id,e.controlName)},ROS3D.InteractiveMarkerHandle.prototype.sendFeedback=function(e,t,r,i){var o=void 0!==t;t=t||{x:0,y:0,z:0};var n={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:i,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:o,menu_entry_id:r};this.feedbackTopic.publish(n)},ROS3D.InteractiveMarkerMenu=function(e){function t(e,t){this.dispatchEvent({type:"menu-select",domEvent:t,id:e.id,controlName:this.controlName}),this.hide(t)}function r(e,o){var n=document.createElement("ul");e.appendChild(n);for(var a=o.children,s=0;a.length>s;s++){var c=document.createElement("li"),l=document.createElement("div");l.appendChild(document.createTextNode(a[s].title)),n.appendChild(c),c.appendChild(l),a[s].children.length>0?(r(c,a[s]),l.addEventListener("click",i.hide.bind(i))):(l.addEventListener("click",t.bind(i,a[s])),l.className="default-interactive-marker-menu-entry")}}var i=this;e=e||{};var o=e.menuEntries,n=e.className||"default-interactive-marker-menu";e.entryClassName||"default-interactive-marker-menu-entry";var a=e.overlayClassName||"default-interactive-marker-overlay",s=[];if(s[0]={children:[]},THREE.EventDispatcher.call(this),null===document.getElementById("default-interactive-marker-menu-css")){var c=document.createElement("style");c.id="default-interactive-marker-menu-css",c.type="text/css",c.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: 0.8em;z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(c)}this.menuDomElem=document.createElement("div"),this.menuDomElem.style.position="absolute",this.menuDomElem.className=n,this.menuDomElem.addEventListener("contextmenu",function(e){e.preventDefault()}),this.overlayDomElem=document.createElement("div"),this.overlayDomElem.className=a,this.hideListener=this.hide.bind(this),this.overlayDomElem.addEventListener("contextmenu",this.hideListener),this.overlayDomElem.addEventListener("click",this.hideListener);var l,h,d;for(l=0;o.length>l;l++)h=o[l],d=h.id,s[d]={title:h.title,id:d,children:[]};for(l=0;o.length>l;l++){h=o[l],d=h.id;var p=s[d],u=s[h.parent_id];u.children.push(p)}r(this.menuDomElem,s[0])},ROS3D.InteractiveMarkerMenu.prototype.show=function(e,t){t&&t.preventDefault&&t.preventDefault(),this.controlName=e.name,this.menuDomElem.style.left=t.domEvent.clientX+"px",this.menuDomElem.style.top=t.domEvent.clientY+"px",document.body.appendChild(this.overlayDomElem),document.body.appendChild(this.menuDomElem)},ROS3D.InteractiveMarkerMenu.prototype.hide=function(e){e&&e.preventDefault&&e.preventDefault(),document.body.removeChild(this.overlayDomElem),document.body.removeChild(this.menuDomElem)},ROS3D.OccupancyGrid=function(e){e=e||{};var t=e.message,r=t.info.width,i=t.info.height,o=new THREE.PlaneGeometry(r,i),n=document.createElement("canvas");n.width=r,n.height=i;for(var a=n.getContext("2d"),s=a.createImageData(r,i),c=0;i>c;c++)for(var l=0;r>l;l++){var h,d=l+(i-c-1)*r,p=t.data[d];h=100===p?0:0===p?255:127;var u=4*(l+c*r);s.data[u]=h,s.data[++u]=h,s.data[++u]=h,s.data[++u]=255}a.putImageData(s,0,0);var E=new THREE.Texture(n);E.needsUpdate=!0;var R=new THREE.MeshBasicMaterial({map:E});R.side=THREE.DoubleSide,THREE.Mesh.call(this,o,R),this.position.x=r*t.info.resolution/2,this.position.y=i*t.info.resolution/2,this.scale.x=t.info.resolution,this.scale.y=t.info.resolution},ROS3D.OccupancyGrid.prototype.__proto__=THREE.Mesh.prototype,ROS3D.OccupancyGridClient=function(e){var t=this;e=e||{};var r=e.ros,i=e.topic||"/map";this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new THREE.Object3D,this.currentGrid=null;var o=new ROSLIB.Topic({ros:r,name:i,messageType:"nav_msgs/OccupancyGrid",compression:"png"});o.subscribe(function(e){t.currentGrid&&t.rootObject.remove(t.currentGrid);var r=new ROS3D.OccupancyGrid({message:e});t.currentGrid=t.tfClient?new ROS3D.SceneNode({frameID:e.header.frame_id,tfClient:t.tfClient,object:r,pose:e.info.origin}):r,t.rootObject.add(t.currentGrid),t.emit("change"),t.continuous||o.unsubscribe()})},ROS3D.OccupancyGridClient.prototype.__proto__=EventEmitter2.prototype,ROS3D.Marker=function(e){e=e||{};var t=e.path||"/",r=e.message;"/"!==t.substr(t.length-1)&&(t+="/"),THREE.Object3D.call(this),this.useQuaternion=!0,this.setPose(r.pose);var i=ROS3D.makeColorMaterial(r.color.r,r.color.g,r.color.b,r.color.a);switch(r.type){case ROS3D.MARKER_ARROW:var o,n=r.scale.x,a=.23*n,s=r.scale.y,c=.5*s,l=null;if(2===r.points.length){l=new THREE.Vector3(r.points[0].x,r.points[0].y,r.points[0].z);var h=new THREE.Vector3(r.points[1].x,r.points[1].y,r.points[1].z);o=l.clone().negate().add(h),n=o.length(),s=r.scale.y,c=r.scale.x,0!==r.scale.z&&(a=r.scale.z)}this.add(new ROS3D.Arrow({direction:o,origin:l,length:n,headLength:a,shaftDiameter:c,headDiameter:s,material:i}));break;case ROS3D.MARKER_CUBE:var d=new THREE.CubeGeometry(r.scale.x,r.scale.y,r.scale.z);this.add(new THREE.Mesh(d,i));break;case ROS3D.MARKER_SPHERE:var p=new THREE.SphereGeometry(.5),u=new THREE.Mesh(p,i);u.scale.x=r.scale.x,u.scale.y=r.scale.y,u.scale.z=r.scale.z,this.add(u);break;case ROS3D.MARKER_CYLINDER:var E=new THREE.CylinderGeometry(.5,.5,1,16,1,!1),R=new THREE.Mesh(E,i);R.useQuaternion=!0,R.quaternion.setFromAxisAngle(new THREE.Vector3(1,0,0),.5*Math.PI),R.scale=new THREE.Vector3(r.scale.x,r.scale.y,r.scale.z),this.add(R);break;case ROS3D.MARKER_CUBE_LIST:case ROS3D.MARKER_SPHERE_LIST:case ROS3D.MARKER_POINTS:var m,v=new THREE.Geometry,T=new THREE.ParticleBasicMaterial({size:r.scale.x});for(m=0;r.points.length>m;m++){var O=new THREE.Vector3;O.x=r.points[m].x,O.y=r.points[m].y,O.z=r.points[m].z,v.vertices.push(O)}if(r.colors.length===r.points.length)for(T.vertexColors=!0,m=0;r.points.length>m;m++){var f=new THREE.Color;f.setRGB(r.colors[m].r,r.colors[m].g,r.colors[m].b),v.colors.push(f)}else T.color.setRGB(r.color.r,r.color.g,r.color.b);this.add(new THREE.ParticleSystem(v,T));break;case ROS3D.MARKER_TEXT_VIEW_FACING:var S=new THREE.TextGeometry(r.text,{size:.5*r.scale.x,height:.1*r.scale.x,curveSegments:4,font:"helvetiker",bevelEnabled:!1,bevelThickness:2,bevelSize:2,material:0,extrudeMaterial:0});S.computeVertexNormals(),S.computeBoundingBox();var g=new THREE.Mesh(S,i),M=-.5*(S.boundingBox.max.x-S.boundingBox.min.x);g.position.y=-M,g.rotation.x=.5*Math.PI,g.rotation.y=1.5*Math.PI,this.add(g);break;case ROS3D.MARKER_MESH_RESOURCE:this.add(new ROS3D.MeshResource({path:t,resource:r.mesh_resource.substr(10)}));break;case ROS3D.MARKER_TRIANGLE_LIST:var b=new ROS3D.TriangleList({material:i,vertices:r.points,colors:r.colors});b.scale=new THREE.Vector3(r.scale.x,r.scale.y,r.scale.z),this.add(b);break;default:console.error("Currently unsupported marker type: "+r.type)}},ROS3D.Marker.prototype.__proto__=THREE.Object3D.prototype,ROS3D.Marker.prototype.setPose=function(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion=new THREE.Quaternion(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.quaternion.normalize(),this.updateMatrixWorld()},ROS3D.MarkerClient=function(e){var t=this;e=e||{};var r=e.ros,i=e.topic;this.tfClient=e.tfClient,this.rootObject=e.rootObject||new THREE.Object3D,this.currentMarker=null;var o=new ROSLIB.Topic({ros:r,name:i,messageType:"visualization_msgs/Marker",compression:"png"});o.subscribe(function(e){var r=new ROS3D.Marker({message:e});t.currentMarker&&t.rootObject.remove(t.currentMarker),t.currentMarker=new ROS3D.SceneNode({frameID:e.header.frame_id,tfClient:t.tfClient,object:r}),t.rootObject.add(t.currentMarker),t.emit("change")})},ROS3D.MarkerClient.prototype.__proto__=EventEmitter2.prototype,ROS3D.Arrow=function(e){e=e||{};var t=e.origin||new THREE.Vector3(0,0,0),r=e.direction||new THREE.Vector3(1,0,0),i=e.length||1,o=e.headLength||.2,n=e.shaftDiameter||.05,a=e.headDiameter||.1,s=e.material||new THREE.MeshBasicMaterial,c=i-o,l=new THREE.CylinderGeometry(.5*n,.5*n,c,12,1),h=new THREE.Matrix4;h.setPosition(new THREE.Vector3(0,.5*c,0)),l.applyMatrix(h);var d=new THREE.CylinderGeometry(0,.5*a,o,12,1);h.setPosition(new THREE.Vector3(0,c+.5*o,0)),d.applyMatrix(h),THREE.GeometryUtils.merge(l,d),THREE.Mesh.call(this,l,s),this.position=t,this.setDirection(r)},ROS3D.Arrow.prototype.__proto__=THREE.Mesh.prototype,ROS3D.Arrow.prototype.setDirection=function(e){var t=new THREE.Vector3(0,1,0).cross(e),r=Math.acos(new THREE.Vector3(0,1,0).dot(e.clone().normalize()));this.matrix=(new THREE.Matrix4).makeRotationAxis(t.normalize(),r),this.rotation.setEulerFromRotationMatrix(this.matrix,this.eulerOrder)},ROS3D.Arrow.prototype.setLength=function(e){this.scale.set(e,e,e)},ROS3D.Arrow.prototype.setColor=function(e){this.line.material.color.setHex(e),this.cone.material.color.setHex(e)},ROS3D.Axes=function(e){function t(e){var t=new THREE.Color;t.setRGB(e.x,e.y,e.z);var i=new THREE.MeshBasicMaterial({color:t.getHex()}),o=new THREE.Vector3;o.crossVectors(e,new THREE.Vector3(0,-1,0));var n=new THREE.Quaternion;n.setFromAxisAngle(o,.5*Math.PI);var a=new THREE.Mesh(r.headGeom,i);a.position=e.clone(),a.position.multiplyScalar(.95),a.useQuaternion=!0,a.quaternion=n,a.updateMatrix(),r.add(a);var s=new THREE.Mesh(r.lineGeom,i);s.position=e.clone(),s.position.multiplyScalar(.45),s.useQuaternion=!0,s.quaternion=n,s.updateMatrix(),r.add(s)}var r=this;e=e||{};var i=e.shaftRadius||.008,o=e.headRadius||.023,n=e.headLength||.1;THREE.Object3D.call(this),this.lineGeom=new THREE.CylinderGeometry(i,i,1-n),this.headGeom=new THREE.CylinderGeometry(0,o,n),t(new THREE.Vector3(1,0,0)),t(new THREE.Vector3(0,1,0)),t(new THREE.Vector3(0,0,1))},ROS3D.Axes.prototype.__proto__=THREE.Object3D.prototype,ROS3D.Grid=function(e){e=e||{};var t=e.size||50,r=e.color||"#cccccc",i=e.lineWidth||1;THREE.Mesh.call(this,new THREE.PlaneGeometry(t,t,t,t),new THREE.MeshBasicMaterial({color:r,wireframe:!0,wireframeLinewidth:i,transparent:!0}))},ROS3D.Grid.prototype.__proto__=THREE.Mesh.prototype,ROS3D.MeshResource=function(e){var t=this;e=e||{};var r=e.path||"/",i=e.resource;this.warnings=e.warnings,THREE.Object3D.call(this),"/"!==r.substr(r.length-1)&&(this.path+="/");var o=r+i;if(o.substr(-4).toLowerCase(),".dae"===o.substr(-4).toLowerCase()){var n=new ColladaLoader2;n.log=function(e){t.warnings&&console.warn(e)},n.load(o,function(e){if(e.dae.asset.unit){var r=e.dae.asset.unit;e.scene.scale=new THREE.Vector3(r,r,r)}t.add(e.scene)})}},ROS3D.MeshResource.prototype.__proto__=THREE.Object3D.prototype,ROS3D.TriangleList=function(e){e=e||{};var t=e.material||new THREE.MeshBasicMaterial,r=e.vertices,i=e.colors;THREE.Object3D.call(this),t.side=THREE.DoubleSide;var o=new THREE.Geometry;for(n=0;r.length>n;n++)o.vertices.push(new THREE.Vector3(r[n].x,r[n].y,r[n].z));var n,a;if(i.length===r.length){for(n=0;r.length>n;n+=3){var s=new THREE.Face3(n,n+1,n+2);for(a=3*n;3*n+3>a;n++){var c=new THREE.Color;c.setRGB(i[n].r,i[n].g,i[n].b),s.vertexColors.push(c)}o.faces.push(h)}t.vertexColors=THREE.VertexColors}else if(i.length===r.length/3){for(n=0;r.length>n;n+=3){var l=new THREE.Face3(n,n+1,n+2);l.color.setRGB(i[n/3].r,i[n/3].g,i[n/3].b),o.faces.push(l)}t.vertexColors=THREE.FaceColors}else for(n=0;r.length>n;n+=3){var h=new THREE.Face3(n,n+1,n+2);o.faces.push(h)}o.computeBoundingBox(),o.computeBoundingSphere(),o.computeCentroids(),o.computeFaceNormals(),this.add(new THREE.Mesh(o,t))},ROS3D.TriangleList.prototype.__proto__=THREE.Object3D.prototype,ROS3D.TriangleList.prototype.setColor=function(e){this.mesh.material.color.setHex(e)},ROS3D.Urdf=function(e){e=e||{};var t=e.urdfModel,r=e.path||"/",i=e.tfClient;THREE.Object3D.call(this),this.useQuaternion=!0;var o=t.links;for(var n in o){var a=o[n];if(a.visual&&a.visual.geometry&&a.visual.geometry.type===ROSLIB.URDF_MESH){var s="/"+a.name,c=a.visual.geometry.filename,l=c.substr(-4).toLowerCase();if(".dae"===l){var h=new ROS3D.SceneNode({frameID:s,pose:a.visual.origin,tfClient:i,object:new ROS3D.MeshResource({path:r,resource:c.substring(10)})});this.add(h)}}}},ROS3D.Urdf.prototype.__proto__=THREE.Object3D.prototype,ROS3D.UrdfClient=function(e){var t=this;e=e||{};var r=e.ros,i=e.param||"robot_description";this.path=e.path||"/",this.tfClient=e.tfClient,this.rootObject=e.rootObject||new THREE.Object3D;var o=new ROSLIB.Param({ros:r,name:i});o.get(function(e){var r=new ROSLIB.UrdfModel({string:e});t.rootObject.add(new ROS3D.Urdf({urdfModel:r,path:t.path,tfClient:t.tfClient}))})},ROS3D.SceneNode=function(e){e=e||{};var t=this,r=e.tfClient,i=e.frameID,o=e.object;this.pose=e.pose||new ROSLIB.Pose,THREE.Object3D.call(this),this.useQuaternion=!0,this.add(o),this.updatePose(this.pose),r.subscribe(i,function(e){var r=new ROSLIB.Transform(e),i=new ROSLIB.Pose(t.pose);i.applyTransform(r),t.updatePose(i)})},ROS3D.SceneNode.prototype.__proto__=THREE.Object3D.prototype,ROS3D.SceneNode.prototype.updatePose=function(e){this.position.x=e.position.x,this.position.y=e.position.y,this.position.z=e.position.z,this.quaternion=new THREE.Quaternion(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)},ROS3D.Viewer=function(e){function t(){r.cameraControls.update(),r.directionalLight.position=r.camera.localToWorld(new THREE.Vector3(-1,1,0)),r.directionalLight.position.normalize(),r.renderer.clear(!0,!0,!0),r.renderer.render(r.scene,r.camera),r.highlighter.renderHighlight(r.renderer,r.scene,r.camera),requestAnimationFrame(t)}var r=this;e=e||{};var i=e.divID,o=e.width,n=e.height,a=e.background||"#111111";e.antialias;var s=e.intensity||.66,c=e.cameraPose||{x:3,y:3,z:3};this.renderer=new THREE.WebGLRenderer({antialias:this.antialias}),this.renderer.setClearColorHex(a.replace("#","0x"),1),this.renderer.sortObjects=!1,this.renderer.setSize(o,n),this.renderer.shadowMapEnabled=!1,this.renderer.autoClear=!1,this.scene=new THREE.Scene,this.camera=new THREE.PerspectiveCamera(40,o/n,.01,1e3),this.camera.position.x=c.x,this.camera.position.y=c.y,this.camera.position.z=c.z,this.cameraControls=new ROS3D.OrbitControls({scene:this.scene,camera:this.camera}),this.cameraControls.userZoomSpeed=.5,this.scene.add(new THREE.AmbientLight(5592405)),this.directionalLight=new THREE.DirectionalLight(16777215,s),this.scene.add(this.directionalLight),this.selectableObjects=new THREE.Object3D,this.scene.add(this.selectableObjects);var l=new ROS3D.MouseHandler({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new ROS3D.Highlighter({mouseHandler:l}),document.getElementById(i).appendChild(this.renderer.domElement),t()},ROS3D.Viewer.prototype.addObject=function(e,t){t?this.selectableObjects.add(e):this.scene.add(e)},ROS3D.Highlighter=function(e){e=e||{};var t=e.mouseHandler;this.hoverObjs=[],t.addEventListener("mouseover",this.onMouseOver.bind(this)),t.addEventListener("mouseout",this.onMouseOut.bind(this))},ROS3D.Highlighter.prototype.onMouseOver=function(e){this.hoverObjs.push(e.currentTarget)},ROS3D.Highlighter.prototype.onMouseOut=function(e){this.hoverObjs.splice(this.hoverObjs.indexOf(e.currentTarget),1)},ROS3D.Highlighter.prototype.getWebglObjects=function(e,t,r){for(var i=e.__webglObjects,o=0;t.length>o;o++)if(t[o]){for(var n=i.length-1;n>=0;n--)if(i[n].object===t[o]){r.push(i[n]);break}this.getWebglObjects(e,t[o].children,r)}},ROS3D.Highlighter.prototype.renderHighlight=function(e,t,r){var i=[];this.getWebglObjects(t,this.hoverObjs,i),t.overrideMaterial=new THREE.MeshBasicMaterial({fog:!1,opacity:.5,depthTest:!0,depthWrite:!1,polygonOffset:!0,polygonOffsetUnits:-1,side:THREE.DoubleSide});var o=t.__webglObjects;t.__webglObjects=i,e.render(t,r),t.__webglObjects=o,t.overrideMaterial=null},ROS3D.MouseHandler=function(e){THREE.EventDispatcher.call(this),this.renderer=e.renderer,this.camera=e.camera,this.rootObject=e.rootObject,this.fallbackTarget=e.fallbackTarget,this.lastTarget=this.fallbackTarget,this.dragging=!1,this.projector=new THREE.Projector;var t=["contextmenu","click","dblclick","mouseout","mousedown","mouseup","mousemove","mousewheel","DOMMouseScroll","touchstart","touchend","touchcancel","touchleave","touchmove"];this.listeners={},t.forEach(function(e){this.listeners[e]=this.processDomEvent.bind(this),this.renderer.domElement.addEventListener(e,this.listeners[e],!1)},this)},ROS3D.MouseHandler.prototype.processDomEvent=function(e){e.preventDefault(); -var t=e.target,r=t.getBoundingClientRect(),i=e.clientX-r.left-t.clientLeft+t.scrollLeft,o=e.clientY-r.top-t.clientTop+t.scrollTop,n=2*(i/t.clientWidth)-1,a=2*(-o/t.clientHeight)+1,s=new THREE.Vector3(n,a,.5);this.projector.unprojectVector(s,this.camera);var c=new THREE.Raycaster(this.camera.position.clone(),s.sub(this.camera.position).normalize()),l=c.ray,h={mousePos:new THREE.Vector2(n,a),mouseRay:l,domEvent:e,camera:this.camera,intersection:this.lastIntersection};if("mouseout"===e.type)return this.dragging&&(this.notify(this.lastTarget,"mouseup",h),this.dragging=!1),this.notify(this.lastTarget,"mouseout",h),this.lastTarget=null,void 0;if(this.dragging)return this.notify(this.lastTarget,e.type,h),("mouseup"===e.type&&2===e.button||"click"===e.type)&&(this.dragging=!1),void 0;t=this.lastTarget;var d=[];if(d=c.intersectObject(this.rootObject,!0),d.length>0?(t=d[0].object,h.intersection=this.lastIntersection=d[0]):t=this.fallbackTarget,t!==this.lastTarget){var p=this.notify(t,"mouseover",h);p?this.notify(this.lastTarget,"mouseout",h):(t=this.fallbackTarget,t!==this.lastTarget&&(this.notify(t,"mouseover",h),this.notify(this.lastTarget,"mouseout",h)))}this.notify(t,e.type,h),"mousedown"===e.type&&(this.dragging=!0),this.lastTarget=t},ROS3D.MouseHandler.prototype.notify=function(e,t,r){for(r.type=t,r.cancelBubble=!1,r.stopPropagation=function(){r.cancelBubble=!0},r.currentTarget=e;r.currentTarget;){if(r.currentTarget.dispatchEvent&&r.currentTarget.dispatchEvent instanceof Function&&(r.currentTarget.dispatchEvent(r),r.cancelBubble))return this.dispatchEvent(r),!0;r.currentTarget=r.currentTarget.parent}return!1},ROS3D.OrbitControls=function(e){function t(e){var t=e.domEvent;switch(t.preventDefault(),t.button){case 0:g=S.ROTATE,d.set(t.clientX,t.clientY);break;case 1:g=S.MOVE,T=new THREE.Vector3(0,0,1);var r=(new THREE.Matrix4).extractRotation(this.camera.matrix);T.applyMatrix4(r),v=c.center.clone(),O=c.camera.position.clone(),f=i(e.mouseRay,v,T);break;case 2:g=S.ZOOM,E.set(t.clientX,t.clientY)}this.showAxes()}function r(e){var t=e.domEvent;if(g===S.ROTATE)p.set(t.clientX,t.clientY),u.subVectors(p,d),c.rotateLeft(2*Math.PI*u.x/h*c.userRotateSpeed),c.rotateUp(2*Math.PI*u.y/h*c.userRotateSpeed),d.copy(p),this.showAxes();else if(g===S.ZOOM)R.set(t.clientX,t.clientY),m.subVectors(R,E),m.y>0?c.zoomIn():c.zoomOut(),E.copy(R),this.showAxes();else if(g===S.MOVE){var r=i(e.mouseRay,c.center,T);if(!r)return;var o=(new THREE.Vector3).subVectors(f.clone(),r.clone());c.center.addVectors(v.clone(),o.clone()),c.camera.position.addVectors(O.clone(),o.clone()),c.update(),c.camera.updateMatrixWorld(),this.showAxes()}}function i(e,t,r){var i=new THREE.Vector3,o=new THREE.Vector3;i.subVectors(t,e.origin);var n=e.direction.dot(r);if(Math.abs(n)0?c.zoomOut():c.zoomIn(),this.showAxes()}}function a(e){t(e),e.preventDefault()}function s(e){r(e),e.preventDefault()}THREE.EventDispatcher.call(this);var c=this;e=e||{};var l=e.scene;this.camera=e.camera,this.center=new THREE.Vector3,this.userZoom=!0,this.userZoomSpeed=e.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=e.userRotateSpeed||1,this.autoRotate=e.autoRotate,this.autoRotateSpeed=e.autoRotateSpeed||2,this.camera.up=new THREE.Vector3(0,0,1);var h=1800,d=new THREE.Vector2,p=new THREE.Vector2,u=new THREE.Vector2,E=new THREE.Vector2,R=new THREE.Vector2,m=new THREE.Vector2,v=new THREE.Vector3,T=new THREE.Vector3,O=new THREE.Vector3,f=new THREE.Vector3;this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new THREE.Vector3;var S={NONE:-1,ROTATE:0,ZOOM:1,MOVE:2},g=S.NONE;this.axes=new ROS3D.Axes({shaftRadius:.025,headRadius:.07,headLength:.2}),l.add(this.axes),this.axes.traverse(function(e){e.visible=!1}),this.addEventListener("mousedown",t),this.addEventListener("mouseup",o),this.addEventListener("mousemove",r),this.addEventListener("touchstart",a),this.addEventListener("touchmove",s),this.addEventListener("mousewheel",n),this.addEventListener("DOMMouseScroll",n)},ROS3D.OrbitControls.prototype.showAxes=function(){var e=this;this.axes.traverse(function(e){e.visible=!0}),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(function(){e.axes.traverse(function(e){e.visible=!1}),e.hideTimeout=!1},1e3)},ROS3D.OrbitControls.prototype.rotateLeft=function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e},ROS3D.OrbitControls.prototype.rotateRight=function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e},ROS3D.OrbitControls.prototype.rotateUp=function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e},ROS3D.OrbitControls.prototype.rotateDown=function(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e},ROS3D.OrbitControls.prototype.zoomIn=function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e},ROS3D.OrbitControls.prototype.zoomOut=function(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e},ROS3D.OrbitControls.prototype.update=function(){var e=this.camera.position,t=e.clone().sub(this.center),r=Math.atan2(t.y,t.x),i=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),r+=this.thetaDelta,i+=this.phiDelta;var o=1e-6;i=Math.max(o,Math.min(Math.PI-o,i));var n=t.length();t.y=n*Math.sin(i)*Math.sin(r),t.z=n*Math.cos(i),t.x=n*Math.sin(i)*Math.cos(r),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),n=t.length(),this.axes.position=this.center.clone(),this.axes.scale.x=this.axes.scale.y=this.axes.scale.z=.05*n,this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}; \ No newline at end of file +var ROS3D=ROS3D||{REVISION:"4"};ROS3D.MARKER_ARROW=0,ROS3D.MARKER_CUBE=1,ROS3D.MARKER_SPHERE=2,ROS3D.MARKER_CYLINDER=3,ROS3D.MARKER_LINE_STRIP=4,ROS3D.MARKER_LINE_LIST=5,ROS3D.MARKER_CUBE_LIST=6,ROS3D.MARKER_SPHERE_LIST=7,ROS3D.MARKER_POINTS=8,ROS3D.MARKER_TEXT_VIEW_FACING=9,ROS3D.MARKER_MESH_RESOURCE=10,ROS3D.MARKER_TRIANGLE_LIST=11,ROS3D.INTERACTIVE_MARKER_KEEP_ALIVE=0,ROS3D.INTERACTIVE_MARKER_POSE_UPDATE=1,ROS3D.INTERACTIVE_MARKER_MENU_SELECT=2,ROS3D.INTERACTIVE_MARKER_BUTTON_CLICK=3,ROS3D.INTERACTIVE_MARKER_MOUSE_DOWN=4,ROS3D.INTERACTIVE_MARKER_MOUSE_UP=5,ROS3D.INTERACTIVE_MARKER_NONE=0,ROS3D.INTERACTIVE_MARKER_MENU=1,ROS3D.INTERACTIVE_MARKER_BUTTON=2,ROS3D.INTERACTIVE_MARKER_MOVE_AXIS=3,ROS3D.INTERACTIVE_MARKER_MOVE_PLANE=4,ROS3D.INTERACTIVE_MARKER_ROTATE_AXIS=5,ROS3D.INTERACTIVE_MARKER_MOVE_ROTATE=6,ROS3D.INTERACTIVE_MARKER_INHERIT=0,ROS3D.INTERACTIVE_MARKER_FIXED=1,ROS3D.INTERACTIVE_MARKER_VIEW_FACING=2,ROS3D.makeColorMaterial=function(a,b,c,d){var e=new THREE.Color;return e.setRGB(a,b,c),.99>=d?new THREE.MeshBasicMaterial({color:e.getHex(),opacity:d+.1,transparent:!0,depthWrite:!0,blendSrc:THREE.SrcAlphaFactor,blendDst:THREE.OneMinusSrcAlphaFactor,blendEquation:THREE.ReverseSubtractEquation,blending:THREE.NormalBlending}):new THREE.MeshLambertMaterial({color:e.getHex(),opacity:d,blending:THREE.NormalBlending})},ROS3D.intersectPlane=function(a,b,c){var d=new THREE.Vector3,e=new THREE.Vector3;d.subVectors(b,a.origin);var f=a.direction.dot(c);if(Math.abs(f)0.99)"," {"," vec4 depthColor2 = texture2D( map, vUv2 );"," float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;"," depth = 0.99+depth2;"," }"," "," return depth;"," }","","float median(float a, float b, float c)"," {"," float r=a;"," "," if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))"," {"," vec2 smp = decodeDepth(vec2(position.x, position.y));"," float depth = smp.x;"," depthVariance = smp.y;"," "," float z = -depth;"," "," pos = vec4("," ( position.x / width - 0.5 ) * z * (1000.0/focallength) * -1.0,"," ( position.y / height - 0.5 ) * z * (1000.0/focallength),"," (- z + zOffset / 1000.0) * 2.0,"," 1.0);"," "," vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );"," vec4 maskColor = texture2D( map, maskP );"," maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;"," }"," "," gl_PointSize = pointSize;"," gl_Position = projectionMatrix * modelViewMatrix * pos;"," ","}"].join("\n"),this.fragment_shader=["uniform sampler2D map;","uniform float varianceThreshold;","uniform float whiteness;","","varying vec2 vUvP;","varying vec2 colorP;","","varying float depthVariance;","varying float maskVal;","","","void main() {"," "," vec4 color;"," "," if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))"," { "," discard;"," }"," else "," {"," color = texture2D( map, colorP );"," "," float fader = whiteness /100.0;"," "," color.r = color.r * (1.0-fader)+ fader;"," "," color.g = color.g * (1.0-fader)+ fader;"," "," color.b = color.b * (1.0-fader)+ fader;"," "," color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );"," }"," "," gl_FragColor = vec4( color.r, color.g, color.b, color.a );"," ","}"].join("\n")},ROS3D.DepthCloud.prototype.__proto__=THREE.Object3D.prototype,ROS3D.DepthCloud.prototype.metaLoaded=function(){this.metaLoaded=!0,this.initStreamer()},ROS3D.DepthCloud.prototype.initStreamer=function(){if(this.metaLoaded){this.texture=new THREE.Texture(this.video),this.geometry=new THREE.Geometry;for(var a=0,b=this.width*this.height;b>a;a++){var c=new THREE.Vector3;c.x=a%this.width,c.y=Math.floor(a/this.width),this.geometry.vertices.push(c)}this.material=new THREE.ShaderMaterial({uniforms:{map:{type:"t",value:this.texture},width:{type:"f",value:this.width},height:{type:"f",value:this.height},focallength:{type:"f",value:this.f},pointSize:{type:"f",value:this.pointSize},zOffset:{type:"f",value:0},whiteness:{type:"f",value:this.whiteness},varianceThreshold:{type:"f",value:this.varianceThreshold}},vertexShader:this.vertex_shader,fragmentShader:this.fragment_shader}),this.mesh=new THREE.ParticleSystem(this.geometry,this.material),this.mesh.position.x=0,this.mesh.position.y=0,this.add(this.mesh);var d=this;setInterval(function(){d.video.readyState===d.video.HAVE_ENOUGH_DATA&&(d.texture.needsUpdate=!0)},1e3/30)}},ROS3D.DepthCloud.prototype.startStream=function(){this.video.play()},ROS3D.DepthCloud.prototype.stopStream=function(){this.video.stop()},ROS3D.InteractiveMarker=function(a){THREE.Object3D.call(this),THREE.EventDispatcher.call(this);var b=this;a=a||{};var c=a.handle;this.name=c.name;var d=a.camera,e=a.path||"/";this.dragging=!1,this.onServerSetPose({pose:c.pose}),this.dragStart={position:new THREE.Vector3,orientation:new THREE.Quaternion,positionWorld:new THREE.Vector3,orientationWorld:new THREE.Quaternion,event3d:{}},c.controls.forEach(function(a){b.add(new ROS3D.InteractiveMarkerControl({parent:b,message:a,camera:d,path:e}))}),c.menuEntries.length>0&&(this.menu=new ROS3D.InteractiveMarkerMenu({menuEntries:c.menuEntries}),this.menu.addEventListener("menu-select",function(a){b.dispatchEvent(a)}))},ROS3D.InteractiveMarker.prototype.__proto__=THREE.Object3D.prototype,ROS3D.InteractiveMarker.prototype.showMenu=function(a,b){this.menu&&this.menu.show(a,b)},ROS3D.InteractiveMarker.prototype.moveAxis=function(a,b,c){if(this.dragging){var d=a.currentControlOri,e=b.clone().applyQuaternion(d),f=this.dragStart.event3d.intersection.point,g=e.clone().applyQuaternion(this.dragStart.orientationWorld.clone()),h=new THREE.Ray(f,g),i=ROS3D.closestAxisPoint(h,c.camera,c.mousePos),j=new THREE.Vector3;j.addVectors(this.dragStart.position,e.clone().applyQuaternion(this.dragStart.orientation).multiplyScalar(i)),this.setPosition(a,j),c.stopPropagation()}},ROS3D.InteractiveMarker.prototype.movePlane=function(a,b,c){if(this.dragging){var d=a.currentControlOri,e=b.clone().applyQuaternion(d),f=this.dragStart.event3d.intersection.point,g=e.clone().applyQuaternion(this.dragStart.orientationWorld),h=ROS3D.intersectPlane(c.mouseRay,f,g),i=new THREE.Vector3;i.subVectors(h,f),i.add(this.dragStart.positionWorld),this.setPosition(a,i),c.stopPropagation()}},ROS3D.InteractiveMarker.prototype.rotateAxis=function(a,b,c){if(this.dragging){a.updateMatrixWorld();var d=a.currentControlOri,e=d.clone().multiply(b.clone()),f=new THREE.Vector3(1,0,0).applyQuaternion(e),g=this.dragStart.event3d.intersection.point,h=f.applyQuaternion(this.dragStart.orientationWorld),i=ROS3D.intersectPlane(c.mouseRay,g,h),j=new THREE.Ray(this.dragStart.positionWorld,h),k=ROS3D.intersectPlane(j,g,h),l=this.dragStart.orientationWorld.clone().multiply(e),m=l.clone().inverse();i.sub(k),i.applyQuaternion(m);var n=this.dragStart.event3d.intersection.point.clone();n.sub(k),n.applyQuaternion(m);var o=Math.atan2(i.y,i.z),p=Math.atan2(n.y,n.z),q=p-o,r=new THREE.Quaternion;r.setFromAxisAngle(f,q),this.setOrientation(a,r.multiply(this.dragStart.orientationWorld)),c.stopPropagation()}},ROS3D.InteractiveMarker.prototype.feedbackEvent=function(a,b){this.dispatchEvent({type:a,position:this.position.clone(),orientation:this.quaternion.clone(),controlName:b.name})},ROS3D.InteractiveMarker.prototype.startDrag=function(a,b){if(0===b.domEvent.button){b.stopPropagation(),this.dragging=!0,this.updateMatrixWorld(!0);var c=new THREE.Vector3;this.matrixWorld.decompose(this.dragStart.positionWorld,this.dragStart.orientationWorld,c),this.dragStart.position=this.position.clone(),this.dragStart.orientation=this.quaternion.clone(),this.dragStart.event3d=b,this.feedbackEvent("user-mousedown",a)}},ROS3D.InteractiveMarker.prototype.stopDrag=function(a,b){0===b.domEvent.button&&(b.stopPropagation(),this.dragging=!1,this.dragStart.event3d={},this.onServerSetPose(this.bufferedPoseEvent),this.bufferedPoseEvent=void 0,this.feedbackEvent("user-mouseup",a))},ROS3D.InteractiveMarker.prototype.buttonClick=function(a,b){b.stopPropagation(),this.feedbackEvent("user-button-click",a)},ROS3D.InteractiveMarker.prototype.setPosition=function(a,b){this.position=b,this.feedbackEvent("user-pose-change",a)},ROS3D.InteractiveMarker.prototype.setOrientation=function(a,b){b.normalize(),this.quaternion=b,this.feedbackEvent("user-pose-change",a)},ROS3D.InteractiveMarker.prototype.onServerSetPose=function(a){if(void 0!==a)if(this.dragging)this.bufferedPoseEvent=a;else{var b=a.pose;this.position.x=b.position.x,this.position.y=b.position.y,this.position.z=b.position.z,this.useQuaternion=!0,this.quaternion=new THREE.Quaternion(b.orientation.x,b.orientation.y,b.orientation.z,b.orientation.w),this.updateMatrixWorld(!0)}},ROS3D.InteractiveMarkerClient=function(a){a=a||{},this.ros=a.ros,this.tfClient=a.tfClient,this.topic=a.topic,this.path=a.path||"/",this.camera=a.camera,this.rootObject=a.rootObject||new THREE.Object3D,this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.topic&&this.subscribe(this.topic)},ROS3D.InteractiveMarkerClient.prototype.subscribe=function(a){this.unsubscribe(),this.updateTopic=new ROSLIB.Topic({ros:this.ros,name:a+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdate.bind(this)),this.feedbackTopic=new ROSLIB.Topic({ros:this.ros,name:a+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new ROSLIB.Service({ros:this.ros,name:a+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var b=new ROSLIB.ServiceRequest({});this.initService.callService(b,this.processInit.bind(this))},ROS3D.InteractiveMarkerClient.prototype.unsubscribe=function(){this.updateTopic&&this.updateTopic.unsubscribe(),this.feedbackTopic&&this.feedbackTopic.unadvertise();for(var a in this.interactiveMarkers)this.eraseIntMarker(a);this.interactiveMarkers={}},ROS3D.InteractiveMarkerClient.prototype.processInit=function(a){var b=a.msg;b.erases=[];for(var c in this.interactiveMarkers)b.erases.push(c);b.poses=[],this.processUpdate(b)},ROS3D.InteractiveMarkerClient.prototype.processUpdate=function(a){var b=this;a.erases.forEach(function(a){b.eraseIntMarker(a)}),a.poses.forEach(function(a){var c=b.interactiveMarkers[a.name];c&&c.setPoseFromServer(a.pose)}),a.markers.forEach(function(a){var c=b.interactiveMarkers[a.name];c&&b.eraseIntMarker(c.name);var d=new ROS3D.InteractiveMarkerHandle({message:a,feedbackTopic:b.feedbackTopic,tfClient:b.tfClient});b.interactiveMarkers[a.name]=d;var e=new ROS3D.InteractiveMarker({handle:d,camera:b.camera,path:b.path});e.name=a.name,b.rootObject.add(e),d.on("pose",function(a){e.onServerSetPose({pose:a})}),e.addEventListener("user-pose-change",d.setPoseFromClient.bind(d)),e.addEventListener("user-mousedown",d.onMouseDown.bind(d)),e.addEventListener("user-mouseup",d.onMouseUp.bind(d)),e.addEventListener("user-button-click",d.onButtonClick.bind(d)),e.addEventListener("menu-select",d.onMenuSelect.bind(d)),d.subscribeTf()})},ROS3D.InteractiveMarkerClient.prototype.eraseIntMarker=function(a){this.interactiveMarkers[a]&&(this.rootObject.remove(this.rootObject.getChildByName(a)),delete this.interactiveMarkers[a])},ROS3D.InteractiveMarkerControl=function(a){function b(a){a.stopPropagation()}var c=this;THREE.Object3D.call(this),THREE.EventDispatcher.call(this),a=a||{},this.parent=a.parent;var d=a.message;this.name=d.name,this.camera=a.camera,this.path=a.path||"/",this.dragging=!1;var e=new THREE.Quaternion(d.orientation.x,d.orientation.y,d.orientation.z,d.orientation.w);e.normalize();var f=new THREE.Vector3(1,0,0);switch(f.applyQuaternion(e),this.currentControlOri=new THREE.Quaternion,d.interaction_mode){case ROS3D.INTERACTIVE_MARKER_MOVE_AXIS:this.addEventListener("mousemove",this.parent.moveAxis.bind(this.parent,this,f)),this.addEventListener("touchmove",this.parent.moveAxis.bind(this.parent,this,f));break;case ROS3D.INTERACTIVE_MARKER_ROTATE_AXIS:this.addEventListener("mousemove",this.parent.rotateAxis.bind(this.parent,this,e));break;case ROS3D.INTERACTIVE_MARKER_MOVE_PLANE:this.addEventListener("mousemove",this.parent.movePlane.bind(this.parent,this,f));break;case ROS3D.INTERACTIVE_MARKER_BUTTON:this.addEventListener("click",this.parent.buttonClick.bind(this.parent,this))}d.interaction_mode!==ROS3D.INTERACTIVE_MARKER_NONE&&(this.addEventListener("mousedown",this.parent.startDrag.bind(this.parent,this)),this.addEventListener("mouseup",this.parent.stopDrag.bind(this.parent,this)),this.addEventListener("contextmenu",this.parent.showMenu.bind(this.parent,this)),this.addEventListener("mouseover",b),this.addEventListener("mouseout",b),this.addEventListener("click",b),this.addEventListener("touchstart",function(a){console.log(a.domEvent),1===a.domEvent.touches.length&&(a.type="mousedown",a.domEvent.button=0,c.dispatchEvent(a))}),this.addEventListener("touchmove",function(a){1===a.domEvent.touches.length&&(console.log(a.domEvent),a.type="mousemove",a.domEvent.button=0,c.dispatchEvent(a))}),this.addEventListener("touchend",function(a){0===a.domEvent.touches.length&&(a.domEvent.button=0,a.type="mouseup",c.dispatchEvent(a),a.type="click",c.dispatchEvent(a))}));var g=new THREE.Quaternion,h=this.parent.position.clone().multiplyScalar(-1);switch(d.orientation_mode){case ROS3D.INTERACTIVE_MARKER_INHERIT:g=this.parent.quaternion.clone().inverse(),this.updateMatrixWorld=function(a){ROS3D.InteractiveMarkerControl.prototype.updateMatrixWorld.call(c,a),c.currentControlOri.copy(c.quaternion),c.currentControlOri.normalize()};break;case ROS3D.INTERACTIVE_MARKER_FIXED:this.updateMatrixWorld=function(a){c.useQuaternion=!0,c.quaternion=c.parent.quaternion.clone().inverse(),c.updateMatrix(),c.matrixWorldNeedsUpdate=!0,ROS3D.InteractiveMarkerControl.prototype.updateMatrixWorld.call(c,a),c.currentControlOri.copy(c.quaternion)};break;case ROS3D.INTERACTIVE_MARKER_VIEW_FACING:var i=d.independentMarkerOrientation;this.updateMatrixWorld=function(a){c.camera.updateMatrixWorld();var b=(new THREE.Matrix4).extractRotation(c.camera.matrixWorld),d=new THREE.Matrix4,e=.5*Math.PI,f=new THREE.Vector3(-e,0,e);d.setRotationFromEuler(f);var g=new THREE.Matrix4;g.getInverse(c.parent.matrixWorld),b.multiplyMatrices(b,d),b.multiplyMatrices(g,b),c.currentControlOri.setFromRotationMatrix(b),i||(c.useQuaternion=!0,c.quaternion.copy(c.currentControlOri),c.updateMatrix(),c.matrixWorldNeedsUpdate=!0),ROS3D.InteractiveMarkerControl.prototype.updateMatrixWorld.call(c,a)};break;default:console.error("Unkown orientation mode: "+d.orientation_mode)}d.markers.forEach(function(a){var b=new ROS3D.Marker({message:a,path:c.path});""!==a.header.frame_id&&(b.position.add(h),b.position.applyQuaternion(g),b.quaternion.multiplyQuaternions(g,b.quaternion),b.updateMatrixWorld()),c.add(b)})},ROS3D.InteractiveMarkerControl.prototype.__proto__=THREE.Object3D.prototype,ROS3D.InteractiveMarkerHandle=function(a){a=a||{},this.message=a.message,this.feedbackTopic=a.feedbackTopic,this.tfClient=a.tfClient,this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new ROSLIB.Transform,this.pose=new ROSLIB.Pose,this.setPoseFromServer(this.message.pose)},ROS3D.InteractiveMarkerHandle.prototype.__proto__=EventEmitter2.prototype,ROS3D.InteractiveMarkerHandle.prototype.subscribeTf=function(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdate.bind(this))},ROS3D.InteractiveMarkerHandle.prototype.emitServerPoseUpdate=function(){var a=new ROSLIB.Pose(this.pose);a.applyTransform(this.tfTransform),this.emit("pose",a)},ROS3D.InteractiveMarkerHandle.prototype.setPoseFromServer=function(a){this.pose=new ROSLIB.Pose(a),this.emitServerPoseUpdate()},ROS3D.InteractiveMarkerHandle.prototype.tfUpdate=function(a){this.tfTransform=new ROSLIB.Transform(a),this.emitServerPoseUpdate()},ROS3D.InteractiveMarkerHandle.prototype.setPoseFromClient=function(a){this.pose=new ROSLIB.Pose(a);var b=this.tfTransform.clone();b.rotation.invert(),this.pose.applyTransform(b),this.sendFeedback(ROS3D.INTERACTIVE_MARKER_POSE_UPDATE,void 0,0,a.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,a),250))},ROS3D.InteractiveMarkerHandle.prototype.onButtonClick=function(a){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_BUTTON_CLICK,a.clickPosition,0,a.controlName)},ROS3D.InteractiveMarkerHandle.prototype.onMouseDown=function(a){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_MOUSE_DOWN,a.clickPosition,0,a.controlName),this.dragging=!0},ROS3D.InteractiveMarkerHandle.prototype.onMouseUp=function(a){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_MOUSE_UP,a.clickPosition,0,a.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)},ROS3D.InteractiveMarkerHandle.prototype.onMenuSelect=function(a){this.sendFeedback(ROS3D.INTERACTIVE_MARKER_MENU_SELECT,void 0,a.id,a.controlName)},ROS3D.InteractiveMarkerHandle.prototype.sendFeedback=function(a,b,c,d){var e=void 0!==b;b=b||{x:0,y:0,z:0};var f={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:d,event_type:a,pose:this.pose,mouse_point:b,mouse_point_valid:e,menu_entry_id:c};this.feedbackTopic.publish(f)},ROS3D.InteractiveMarkerMenu=function(a){function b(a,b){this.dispatchEvent({type:"menu-select",domEvent:b,id:a.id,controlName:this.controlName}),this.hide(b)}function c(a,e){var f=document.createElement("ul");a.appendChild(f);for(var g=e.children,h=0;h0?(c(i,g[h]),j.addEventListener("click",d.hide.bind(d))):(j.addEventListener("click",b.bind(d,g[h])),j.className="default-interactive-marker-menu-entry")}}var d=this;a=a||{};var e=a.menuEntries,f=a.className||"default-interactive-marker-menu";a.entryClassName||"default-interactive-marker-menu-entry";var g=a.overlayClassName||"default-interactive-marker-overlay",h=[];if(h[0]={children:[]},THREE.EventDispatcher.call(this),null===document.getElementById("default-interactive-marker-menu-css")){var i=document.createElement("style");i.id="default-interactive-marker-menu-css",i.type="text/css",i.innerHTML=".default-interactive-marker-menu {background-color: #444444;border: 1px solid #888888;border: 1px solid #888888;padding: 0px 0px 0px 0px;color: #FFFFFF;font-family: sans-serif;font-size: 0.8em;z-index: 1002;}.default-interactive-marker-menu ul {padding: 0px 0px 5px 0px;margin: 0px;list-style-type: none;}.default-interactive-marker-menu ul li div {-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;cursor: default;padding: 3px 10px 3px 10px;}.default-interactive-marker-menu-entry:hover { background-color: #666666; cursor: pointer;}.default-interactive-marker-menu ul ul { font-style: italic; padding-left: 10px;}.default-interactive-marker-overlay { position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index: 1001; -moz-opacity: 0.0; opacity: .0; filter: alpha(opacity = 0);}",document.getElementsByTagName("head")[0].appendChild(i)}this.menuDomElem=document.createElement("div"),this.menuDomElem.style.position="absolute",this.menuDomElem.className=f,this.menuDomElem.addEventListener("contextmenu",function(a){a.preventDefault()}),this.overlayDomElem=document.createElement("div"),this.overlayDomElem.className=g,this.hideListener=this.hide.bind(this),this.overlayDomElem.addEventListener("contextmenu",this.hideListener),this.overlayDomElem.addEventListener("click",this.hideListener);var j,k,l;for(j=0;ji;i++)for(var j=0;c>j;j++){var k,l=j+(d-i-1)*c,m=b.data[l];k=100===m?0:0===m?255:127;var n=4*(j+i*c);h.data[n]=k,h.data[++n]=k,h.data[++n]=k,h.data[++n]=255}g.putImageData(h,0,0);var o=new THREE.Texture(f);o.needsUpdate=!0;var p=new THREE.MeshBasicMaterial({map:o});p.side=THREE.DoubleSide,THREE.Mesh.call(this,e,p),this.position.x=c*b.info.resolution/2,this.position.y=d*b.info.resolution/2,this.scale.x=b.info.resolution,this.scale.y=b.info.resolution},ROS3D.OccupancyGrid.prototype.__proto__=THREE.Mesh.prototype,ROS3D.OccupancyGridClient=function(a){var b=this;a=a||{};var c=a.ros,d=a.topic||"/map";this.continuous=a.continuous,this.tfClient=a.tfClient,this.rootObject=a.rootObject||new THREE.Object3D,this.currentGrid=null;var e=new ROSLIB.Topic({ros:c,name:d,messageType:"nav_msgs/OccupancyGrid",compression:"png"});e.subscribe(function(a){b.currentGrid&&b.rootObject.remove(b.currentGrid);var c=new ROS3D.OccupancyGrid({message:a});b.currentGrid=b.tfClient?new ROS3D.SceneNode({frameID:a.header.frame_id,tfClient:b.tfClient,object:c,pose:a.info.origin}):c,b.rootObject.add(b.currentGrid),b.emit("change"),b.continuous||e.unsubscribe()})},ROS3D.OccupancyGridClient.prototype.__proto__=EventEmitter2.prototype,ROS3D.Marker=function(a){a=a||{};var b=a.path||"/",c=a.message;"/"!==b.substr(b.length-1)&&(b+="/"),THREE.Object3D.call(this),this.useQuaternion=!0,this.setPose(c.pose);var d=ROS3D.makeColorMaterial(c.color.r,c.color.g,c.color.b,c.color.a);switch(c.type){case ROS3D.MARKER_ARROW:var e,f=c.scale.x,g=.23*f,h=c.scale.y,i=.5*h,j=null;if(2===c.points.length){j=new THREE.Vector3(c.points[0].x,c.points[0].y,c.points[0].z);var k=new THREE.Vector3(c.points[1].x,c.points[1].y,c.points[1].z);e=j.clone().negate().add(k),f=e.length(),h=c.scale.y,i=c.scale.x,0!==c.scale.z&&(g=c.scale.z)}this.add(new ROS3D.Arrow({direction:e,origin:j,length:f,headLength:g,shaftDiameter:i,headDiameter:h,material:d}));break;case ROS3D.MARKER_CUBE:var l=new THREE.CubeGeometry(c.scale.x,c.scale.y,c.scale.z);this.add(new THREE.Mesh(l,d));break;case ROS3D.MARKER_SPHERE:var m=new THREE.SphereGeometry(.5),n=new THREE.Mesh(m,d);n.scale.x=c.scale.x,n.scale.y=c.scale.y,n.scale.z=c.scale.z,this.add(n);break;case ROS3D.MARKER_CYLINDER:var o=new THREE.CylinderGeometry(.5,.5,1,16,1,!1),p=new THREE.Mesh(o,d);p.useQuaternion=!0,p.quaternion.setFromAxisAngle(new THREE.Vector3(1,0,0),.5*Math.PI),p.scale=new THREE.Vector3(c.scale.x,c.scale.y,c.scale.z),this.add(p);break;case ROS3D.MARKER_CUBE_LIST:case ROS3D.MARKER_SPHERE_LIST:case ROS3D.MARKER_POINTS:var q,r=new THREE.Geometry,s=new THREE.ParticleBasicMaterial({size:c.scale.x});for(q=0;qg;f++){var i=new THREE.Color;i.setRGB(d[f].r,d[f].g,d[f].b),h.vertexColors.push(i)}e.faces.push(k)}b.vertexColors=THREE.VertexColors}else if(d.length===c.length/3){for(f=0;f=0;f--)if(d[f].object===b[e]){c.push(d[f]);break}this.getWebglObjects(a,b[e].children,c)}},ROS3D.Highlighter.prototype.renderHighlight=function(a,b,c){var d=[];this.getWebglObjects(b,this.hoverObjs,d),b.overrideMaterial=new THREE.MeshBasicMaterial({fog:!1,opacity:.5,depthTest:!0,depthWrite:!1,polygonOffset:!0,polygonOffsetUnits:-1,side:THREE.DoubleSide});var e=b.__webglObjects;b.__webglObjects=d,a.render(b,c),b.__webglObjects=e,b.overrideMaterial=null},ROS3D.MouseHandler=function(a){THREE.EventDispatcher.call(this),this.renderer=a.renderer,this.camera=a.camera,this.rootObject=a.rootObject,this.fallbackTarget=a.fallbackTarget,this.lastTarget=this.fallbackTarget,this.dragging=!1,this.projector=new THREE.Projector;var b=["contextmenu","click","dblclick","mouseout","mousedown","mouseup","mousemove","mousewheel","DOMMouseScroll","touchstart","touchend","touchcancel","touchleave","touchmove"];this.listeners={},b.forEach(function(a){this.listeners[a]=this.processDomEvent.bind(this),this.renderer.domElement.addEventListener(a,this.listeners[a],!1)},this)},ROS3D.MouseHandler.prototype.processDomEvent=function(a){a.preventDefault();var b=a.target,c=b.getBoundingClientRect(),d=a.clientX-c.left-b.clientLeft+b.scrollLeft,e=a.clientY-c.top-b.clientTop+b.scrollTop,f=2*(d/b.clientWidth)-1,g=2*(-e/b.clientHeight)+1,h=new THREE.Vector3(f,g,.5);this.projector.unprojectVector(h,this.camera);var i=new THREE.Raycaster(this.camera.position.clone(),h.sub(this.camera.position).normalize()),j=i.ray,k={mousePos:new THREE.Vector2(f,g),mouseRay:j,domEvent:a,camera:this.camera,intersection:this.lastIntersection};if("mouseout"===a.type)return this.dragging&&(this.notify(this.lastTarget,"mouseup",k),this.dragging=!1),this.notify(this.lastTarget,"mouseout",k),this.lastTarget=null,void 0;if(this.dragging)return this.notify(this.lastTarget,a.type,k),("mouseup"===a.type&&2===a.button||"click"===a.type)&&(this.dragging=!1),void 0;b=this.lastTarget;var l=[];if(l=i.intersectObject(this.rootObject,!0),l.length>0?(b=l[0].object,k.intersection=this.lastIntersection=l[0]):b=this.fallbackTarget,b!==this.lastTarget){var m=this.notify(b,"mouseover",k);m?this.notify(this.lastTarget,"mouseout",k):(b=this.fallbackTarget,b!==this.lastTarget&&(this.notify(b,"mouseover",k),this.notify(this.lastTarget,"mouseout",k)))}this.notify(b,a.type,k),"mousedown"===a.type&&(this.dragging=!0),this.lastTarget=b},ROS3D.MouseHandler.prototype.notify=function(a,b,c){for(c.type=b,c.cancelBubble=!1,c.stopPropagation=function(){c.cancelBubble=!0},c.currentTarget=a;c.currentTarget;){if(c.currentTarget.dispatchEvent&&c.currentTarget.dispatchEvent instanceof Function&&(c.currentTarget.dispatchEvent(c),c.cancelBubble))return this.dispatchEvent(c),!0;c.currentTarget=c.currentTarget.parent}return!1},ROS3D.OrbitControls=function(a){function b(a){var b=a.domEvent;switch(b.preventDefault(),b.button){case 0:w=v.ROTATE,l.set(b.clientX,b.clientY);break;case 1:w=v.MOVE,s=new THREE.Vector3(0,0,1);var c=(new THREE.Matrix4).extractRotation(this.camera.matrix);s.applyMatrix4(c),r=i.center.clone(),t=i.camera.position.clone(),u=d(a.mouseRay,r,s);break;case 2:w=v.ZOOM,o.set(b.clientX,b.clientY)}this.showAxes()}function c(a){var b=a.domEvent;if(w===v.ROTATE)m.set(b.clientX,b.clientY),n.subVectors(m,l),i.rotateLeft(2*Math.PI*n.x/k*i.userRotateSpeed),i.rotateUp(2*Math.PI*n.y/k*i.userRotateSpeed),l.copy(m),this.showAxes();else if(w===v.ZOOM)p.set(b.clientX,b.clientY),q.subVectors(p,o),q.y>0?i.zoomIn():i.zoomOut(),o.copy(p),this.showAxes();else if(w===v.MOVE){var c=d(a.mouseRay,i.center,s);if(!c)return;var e=(new THREE.Vector3).subVectors(u.clone(),c.clone());i.center.addVectors(r.clone(),e.clone()),i.camera.position.addVectors(t.clone(),e.clone()),i.update(),i.camera.updateMatrixWorld(),this.showAxes()}}function d(a,b,c){var d=new THREE.Vector3,e=new THREE.Vector3;d.subVectors(b,a.origin);var f=a.direction.dot(c);if(Math.abs(f)0?i.zoomOut():i.zoomIn(),this.showAxes()}}function g(a){b(a),a.preventDefault()}function h(a){c(a),a.preventDefault()}THREE.EventDispatcher.call(this);var i=this;a=a||{};var j=a.scene;this.camera=a.camera,this.center=new THREE.Vector3,this.userZoom=!0,this.userZoomSpeed=a.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=a.userRotateSpeed||1,this.autoRotate=a.autoRotate,this.autoRotateSpeed=a.autoRotateSpeed||2,this.camera.up=new THREE.Vector3(0,0,1);var k=1800,l=new THREE.Vector2,m=new THREE.Vector2,n=new THREE.Vector2,o=new THREE.Vector2,p=new THREE.Vector2,q=new THREE.Vector2,r=new THREE.Vector3,s=new THREE.Vector3,t=new THREE.Vector3,u=new THREE.Vector3;this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new THREE.Vector3;var v={NONE:-1,ROTATE:0,ZOOM:1,MOVE:2},w=v.NONE;this.axes=new ROS3D.Axes({shaftRadius:.025,headRadius:.07,headLength:.2}),j.add(this.axes),this.axes.traverse(function(a){a.visible=!1}),this.addEventListener("mousedown",b),this.addEventListener("mouseup",e),this.addEventListener("mousemove",c),this.addEventListener("touchstart",g),this.addEventListener("touchmove",h),this.addEventListener("mousewheel",f),this.addEventListener("DOMMouseScroll",f)},ROS3D.OrbitControls.prototype.showAxes=function(){var a=this;this.axes.traverse(function(a){a.visible=!0}),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout(function(){a.axes.traverse(function(a){a.visible=!1}),a.hideTimeout=!1},1e3)},ROS3D.OrbitControls.prototype.rotateLeft=function(a){void 0===a&&(a=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=a},ROS3D.OrbitControls.prototype.rotateRight=function(a){void 0===a&&(a=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=a},ROS3D.OrbitControls.prototype.rotateUp=function(a){void 0===a&&(a=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=a},ROS3D.OrbitControls.prototype.rotateDown=function(a){void 0===a&&(a=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=a},ROS3D.OrbitControls.prototype.zoomIn=function(a){void 0===a&&(a=Math.pow(.95,this.userZoomSpeed)),this.scale/=a},ROS3D.OrbitControls.prototype.zoomOut=function(a){void 0===a&&(a=Math.pow(.95,this.userZoomSpeed)),this.scale*=a},ROS3D.OrbitControls.prototype.update=function(){var a=this.camera.position,b=a.clone().sub(this.center),c=Math.atan2(b.y,b.x),d=Math.atan2(Math.sqrt(b.y*b.y+b.x*b.x),b.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),c+=this.thetaDelta,d+=this.phiDelta;var e=1e-6;d=Math.max(e,Math.min(Math.PI-e,d));var f=b.length();b.y=f*Math.sin(d)*Math.sin(c),b.z=f*Math.cos(d),b.x=f*Math.sin(d)*Math.cos(c),b.multiplyScalar(this.scale),a.copy(this.center).add(b),this.camera.lookAt(this.center),f=b.length(),this.axes.position=this.center.clone(),this.axes.scale.x=this.axes.scale.y=this.axes.scale.z=.05*f,this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}; \ No newline at end of file diff --git a/examples/depthcloud.html b/examples/depthcloud.html new file mode 100644 index 00000000..0feea4cf --- /dev/null +++ b/examples/depthcloud.html @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + +

Simple DepthCloud Example

+

Run the following commands in the terminal then go to http://localhost:9999/examples/depthcloud.html*.

+
    +
  1. roscore
  2. +
  3. roslaunch rosbridge_server rosbridge_websocket.launch
  4. +
  5. rosrun tf2_web_republisher tf2_web_republisher
  6. +
  7. roslaunch openni_launch openni.launch depth_registration:=true
  8. +
  9. rosrun ros_web_video ros_web_video _port:=9999 _framerate:=15 _bitrate:=250000 _profile:=best www_file_server:=true _wwwroot:=/path/to/ros3djs/
  10. +
  11. rosrun depthcloud_encoder depthcloud_encoder_node _depth:=/camera/depth_registered/image_rect _rgb:=/camera/rgb/image_rect_color
  12. +
+ *Due to a bug in the current WebGL implementations, it is not possible to serve + this file and the video stream from a different host or port number, so we need ros_web_video + to serve the html file as well. If you use Apache, you can set it up to proxy port 9999 to a subdirectory.
+
+ + \ No newline at end of file diff --git a/src/depthcloud/DepthCloud.js b/src/depthcloud/DepthCloud.js new file mode 100644 index 00000000..90963c28 --- /dev/null +++ b/src/depthcloud/DepthCloud.js @@ -0,0 +1,314 @@ +/** + * @author Julius Kammerl - jkammerl@willowgarage.com + */ + +/** + * The DepthCloud object. + * + * @constructor + * @param options - object with following keys: + * * f - The camera's focal length + * * pointSize - Point size (pixels) for rendered point cloud + * * width, height - Dimensions of the video stream + * * whiteness - Blends rgb values to white (0..100) + * * varianceThreshold - Threshold for variance filter, used for compression artifact removal + */ +ROS3D.DepthCloud = function(options) { + + THREE.Object3D.call(this); + + // /////////////////////////// + // depth cloud options + // /////////////////////////// + + this.url = options.url; + // f defaults to standard Kinect calibration + this.f = (options.f !== undefined) ? options.f : 526; + this.pointSize = (options.pointSize !== undefined) ? options.pointSize : 3; + this.width = (options.width !== undefined) ? options.width : 1024; + this.height = (options.height !== undefined) ? options.height : 1024; + this.whiteness = (options.whiteness !== undefined) ? options.whiteness : 0; + this.varianceThreshold = (options.varianceThreshold !== undefined) ? options.varianceThreshold : 0.000016667; + + var metaLoaded = false; + this.video = document.createElement('video'); + + this.video.addEventListener('loadedmetadata', this.metaLoaded.bind(this), false); + + this.video.loop = true; + this.video.src = this.url; + this.video.crossOrigin = 'Anonymous'; + this.video.setAttribute('crossorigin', 'Anonymous'); + + // /////////////////////////// + // load shaders + // /////////////////////////// + this.vertex_shader = [ + 'uniform sampler2D map;', + '', + 'uniform float width;', + 'uniform float height;', + 'uniform float nearClipping, farClipping;', + '', + 'uniform float pointSize;', + 'uniform float zOffset;', + '', + 'uniform float focallength;', + '', + 'varying vec2 vUvP;', + 'varying vec2 colorP;', + '', + 'varying float depthVariance;', + 'varying float maskVal;', + '', + 'float sampleDepth(vec2 pos)', + ' {', + ' float depth;', + ' ', + ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', + ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', + ' ', + ' vec4 depthColor = texture2D( map, vUv );', + ' ', + ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', + ' ', + ' if (depth>0.99)', + ' {', + ' vec4 depthColor2 = texture2D( map, vUv2 );', + ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', + ' depth = 0.99+depth2;', + ' }', + ' ', + ' return depth;', + ' }', + '', + 'float median(float a, float b, float c)', + ' {', + ' float r=a;', + ' ', + ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', + ' {', + ' vec2 smp = decodeDepth(vec2(position.x, position.y));', + ' float depth = smp.x;', + ' depthVariance = smp.y;', + ' ', + ' float z = -depth;', + ' ', + ' pos = vec4(', + ' ( position.x / width - 0.5 ) * z * (1000.0/focallength) * -1.0,', + ' ( position.y / height - 0.5 ) * z * (1000.0/focallength),', + ' (- z + zOffset / 1000.0) * 2.0,', + ' 1.0);', + ' ', + ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', + ' vec4 maskColor = texture2D( map, maskP );', + ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', + ' }', + ' ', + ' gl_PointSize = pointSize;', + ' gl_Position = projectionMatrix * modelViewMatrix * pos;', + ' ', + '}' + ].join('\n'); + + this.fragment_shader = [ + 'uniform sampler2D map;', + 'uniform float varianceThreshold;', + 'uniform float whiteness;', + '', + 'varying vec2 vUvP;', + 'varying vec2 colorP;', + '', + 'varying float depthVariance;', + 'varying float maskVal;', + '', + '', + 'void main() {', + ' ', + ' vec4 color;', + ' ', + ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', + ' { ', + ' discard;', + ' }', + ' else ', + ' {', + ' color = texture2D( map, colorP );', + ' ', + ' float fader = whiteness /100.0;', + ' ', + ' color.r = color.r * (1.0-fader)+ fader;', + ' ', + ' color.g = color.g * (1.0-fader)+ fader;', + ' ', + ' color.b = color.b * (1.0-fader)+ fader;', + ' ', + ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', + ' }', + ' ', + ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', + ' ', + '}' + ].join('\n'); +}; +ROS3D.DepthCloud.prototype.__proto__ = THREE.Object3D.prototype; + +/* + * Callback called when video metadata is ready + */ +ROS3D.DepthCloud.prototype.metaLoaded = function() { + this.metaLoaded = true; + this.initStreamer(); +}; + +/* + * Callback called when video metadata is ready + */ +ROS3D.DepthCloud.prototype.initStreamer = function() { + + if (this.metaLoaded) { + this.texture = new THREE.Texture(this.video); + this.geometry = new THREE.Geometry(); + + for (var i = 0, l = this.width * this.height; i < l; i++) { + + var vertex = new THREE.Vector3(); + vertex.x = (i % this.width); + vertex.y = Math.floor(i / this.width); + + this.geometry.vertices.push(vertex); + } + + this.material = new THREE.ShaderMaterial({ + + uniforms : { + + 'map' : { + type : 't', + value : this.texture + }, + 'width' : { + type : 'f', + value : this.width + }, + 'height' : { + type : 'f', + value : this.height + }, + 'focallength' : { + type : 'f', + value : this.f + }, + 'pointSize' : { + type : 'f', + value : this.pointSize + }, + 'zOffset' : { + type : 'f', + value : 0 + }, + 'whiteness' : { + type : 'f', + value : this.whiteness + }, + 'varianceThreshold' : { + type : 'f', + value : this.varianceThreshold + } + }, + vertexShader : this.vertex_shader, + fragmentShader : this.fragment_shader + // depthWrite: false + + }); + + this.mesh = new THREE.ParticleSystem(this.geometry, this.material); + this.mesh.position.x = 0; + this.mesh.position.y = 0; + this.add(this.mesh); + + var that = this; + + setInterval(function() { + if (that.video.readyState === that.video.HAVE_ENOUGH_DATA) { + that.texture.needsUpdate = true; + } + }, 1000 / 30); + } +}; + +/* + * Start video playback + */ +ROS3D.DepthCloud.prototype.startStream = function() { + this.video.play(); +}; + +/* + * Stop video playback + */ +ROS3D.DepthCloud.prototype.stopStream = function() { + this.video.stop(); +}; diff --git a/src/visualization/Viewer.js b/src/visualization/Viewer.js index 5f82bad1..025a0f12 100644 --- a/src/visualization/Viewer.js +++ b/src/visualization/Viewer.js @@ -78,7 +78,7 @@ ROS3D.Viewer = function(options) { }); /** - * Renders the associated scene to the that. + * Renders the associated scene to the viewer. */ function draw() { // update the controls