Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DepthCloud #36

Merged
merged 14 commits into from
May 24, 2013
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

317 changes: 316 additions & 1 deletion build/ros3d.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ( (a<b) && (b<c) )',
' {',
' r = b;',
' }',
' if ( (a<c) && (c<b) )',
' {',
' r = c;',
' }',
' return r;',
' }',
'',
'float variance(float d1, float d2, float d3, float d4, float d5, float d6, float d7, float d8, float d9)',
' {',
' float mean = (d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 + d9) / 9.0;',
' float t1 = (d1-mean);',
' float t2 = (d2-mean);',
' float t3 = (d3-mean);',
' float t4 = (d4-mean);',
' float t5 = (d5-mean);',
' float t6 = (d6-mean);',
' float t7 = (d7-mean);',
' float t8 = (d8-mean);',
' float t9 = (d9-mean);',
' float v = (t1*t1+t2*t2+t3*t3+t4*t4+t5*t5+t6*t6+t7*t7+t8*t8+t9*t9)/9.0;',
' return v;',
' }',
'',
'vec2 decodeDepth(vec2 pos)',
' {',
' vec2 ret;',
' ',
' ',
' float depth1 = sampleDepth(vec2(position.x-1.0, position.y-1.0));',
' float depth2 = sampleDepth(vec2(position.x, position.y-1.0));',
' float depth3 = sampleDepth(vec2(position.x+1.0, position.y-1.0));',
' float depth4 = sampleDepth(vec2(position.x-1.0, position.y));',
' float depth5 = sampleDepth(vec2(position.x, position.y));',
' float depth6 = sampleDepth(vec2(position.x+1.0, position.y));',
' float depth7 = sampleDepth(vec2(position.x-1.0, position.y+1.0));',
' float depth8 = sampleDepth(vec2(position.x, position.y+1.0));',
' float depth9 = sampleDepth(vec2(position.x+1.0, position.y+1.0));',
' ',
' float median1 = median(depth1, depth2, depth3);',
' float median2 = median(depth4, depth5, depth6);',
' float median3 = median(depth7, depth8, depth9);',
' ',
' ret.x = median(median1, median2, median3);',
' ret.y = variance(depth1, depth2, depth3, depth4, depth5, depth6, depth7, depth8, depth9);',
' ',
' return ret;',
' ',
' }',
'',
'',
'void main() {',
' ',
' vUvP = vec2( position.x / (width*2.0), position.y / (height*2.0)+0.5 );',
' colorP = vec2( position.x / (width*2.0)+0.5 , position.y / (height*2.0) );',
' ',
' vec4 pos = vec4(0.0,0.0,0.0,0.0);',
' depthVariance = 0.0;',
' ',
' if ( (vUvP.x<0.0)|| (vUvP.x>0.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
*/
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions build/ros3d.min.js

Large diffs are not rendered by default.

Loading