Skip to content

Instantly share code, notes, and snippets.

@robotconscience
Created September 4, 2012 15:47
Show Gist options
  • Save robotconscience/3622629 to your computer and use it in GitHub Desktop.
Save robotconscience/3622629 to your computer and use it in GitHub Desktop.
THREE Ray intersectObject with Sprite support
// override THREE Ray
THREE.Ray.prototype.intersectObject = function ( object, recursive ) {
var intersect, intersects = [];
if ( recursive === true ) {
for ( var i = 0, l = object.children.length; i < l; i ++ ) {
Array.prototype.push.apply( intersects, this.intersectObject( object.children[ i ], recursive ) );
}
}
if ( object instanceof THREE.Particle ) {
distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
if ( distance > object.scale.x ) {
return [];
}
intersect = {
distance: distance,
point: object.position,
face: null,
object: object
};
intersects.push( intersect );
// BR ADDITION
} else if (object instanceof THREE.Sprite){
var distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
if ( object.parent instanceof THREE.Sprite || distance == null || distance > object.map.image.width*object.scale.x || distance > object.map.image.height*object.scale.y ) {
return [];
}
return [ {
distance: distance,
point: object.position,
face: null,
object: object
} ];
} else if ( object instanceof THREE.Mesh ) {
// Checking boundingSphere
var scale = THREE.Frustum.__v1.set( object.matrixWorld.getColumnX().length(), object.matrixWorld.getColumnY().length(), object.matrixWorld.getColumnZ().length() );
var scaledRadius = object.geometry.boundingSphere.radius * Math.max( scale.x, Math.max( scale.y, scale.z ) );
// Checking distance to ray
distance = distanceFromIntersection( this.origin, this.direction, object.matrixWorld.getPosition() );
if ( distance > scaledRadius) {
return intersects;
}
// Checking faces
var f, fl, face, dot, scalar,
rangeSq = this.range * this.range,
geometry = object.geometry,
vertices = geometry.vertices,
objMatrix, geometryMaterials,
isFaceMaterial, material, side;
geometryMaterials = object.geometry.materials;
isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
side = object.material.side;
object.matrixRotationWorld.extractRotation( object.matrixWorld );
for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
face = geometry.faces[ f ];
material = isFaceMaterial === true ? geometryMaterials[ face.materialIndex ] : object.material;
if ( material === undefined ) continue;
side = material.side;
originCopy.copy( this.origin );
directionCopy.copy( this.direction );
objMatrix = object.matrixWorld;
// determine if ray intersects the plane of the face
// note: this works regardless of the direction of the face normal
vector = objMatrix.multiplyVector3( vector.copy( face.centroid ) ).subSelf( originCopy );
normal = object.matrixRotationWorld.multiplyVector3( normal.copy( face.normal ) );
dot = directionCopy.dot( normal );
// bail if ray and plane are parallel
if ( Math.abs( dot ) < precision ) continue;
// calc distance to plane
scalar = normal.dot( vector ) / dot;
// if negative distance, then plane is behind ray
if ( scalar < 0 ) continue;
if ( side === THREE.DoubleSide || ( side === THREE.FrontSide ? dot < 0 : dot > 0 ) ) {
intersectPoint.add( originCopy, directionCopy.multiplyScalar( scalar ) );
distance = originCopy.distanceTo( intersectPoint );
if ( distance < this.near ) continue;
if ( distance > this.far ) continue;
if ( face instanceof THREE.Face3 ) {
a = objMatrix.multiplyVector3( a.copy( vertices[ face.a ] ) );
b = objMatrix.multiplyVector3( b.copy( vertices[ face.b ] ) );
c = objMatrix.multiplyVector3( c.copy( vertices[ face.c ] ) );
if ( pointInFace3( intersectPoint, a, b, c ) ) {
intersect = {
distance: distance,
point: intersectPoint.clone(),
face: face,
faceIndex: f,
object: object
};
intersects.push( intersect );
}
} else if ( face instanceof THREE.Face4 ) {
a = objMatrix.multiplyVector3( a.copy( vertices[ face.a ] ) );
b = objMatrix.multiplyVector3( b.copy( vertices[ face.b ] ) );
c = objMatrix.multiplyVector3( c.copy( vertices[ face.c ] ) );
d = objMatrix.multiplyVector3( d.copy( vertices[ face.d ] ) );
if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) {
intersect = {
distance: distance,
point: intersectPoint.clone(),
face: face,
faceIndex: f,
object: object
};
intersects.push( intersect );
}
}
}
}
}
intersects.sort( descSort );
return intersects;
// copies of private funs / vars
var a = new THREE.Vector3();
var b = new THREE.Vector3();
var c = new THREE.Vector3();
var d = new THREE.Vector3();
var originCopy = new THREE.Vector3();
var directionCopy = new THREE.Vector3();
var vector = new THREE.Vector3();
var normal = new THREE.Vector3();
var intersectPoint = new THREE.Vector3();
var descSort = function ( a, b ) {
return a.distance - b.distance;
};
//
var v0 = new THREE.Vector3(), v1 = new THREE.Vector3(), v2 = new THREE.Vector3();
var dot, intersect, distance;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment