Ray class
@author mr.doob / http://mrdoob.com/
Ported to Dart from JS by: @author rob silverton / http://www.unwrong.com/
class Ray { Vector3 origin, direction; num near, far; final num precision; Ray( [this.origin, this.direction, this.near = 0, this.far = double.INFINITY] ) : precision = 0.0001 { if (this.origin == null) this.origin = new Vector3.zero(); if (this.direction == null) this.direction = new Vector3.zero(); } double _distanceFromIntersection( Vector3 origin, Vector3 direction, Vector3 position ) { Vector3 v0 = position - origin; double dot = v0.dot(direction); Vector3 intersect = origin + direction.scaled(dot); double distance = position.absoluteError(intersect); return distance; } //http://www.blackpawn.com/texts/pointinpoly/default.html bool _pointInFace3( Vector3 p, Vector3 a, Vector3 b, Vector3 c ) { num dot00, dot01, dot02, dot11, dot12, invDenom, u, v; Vector3 v0 = c - a; Vector3 v1 = b - a; Vector3 v2 = p - a; dot00 = v0.dot( v0 ); dot01 = v0.dot( v1 ); dot02 = v0.dot( v2 ); dot11 = v1.dot( v1 ); dot12 = v1.dot( v2 ); invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 ); u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 ); } List<Intersect> intersectObject( Object3D object, {bool recursive: false} ) { List<Vector3> abcd = new List.generate(4, (_) => new Vector3.zero()); Vector3 originCopy = new Vector3.zero(); Vector3 directionCopy = new Vector3.zero(); Vector3 vector = new Vector3.zero(); Vector3 normal = new Vector3.zero(); Vector3 intersectPoint = new Vector3.zero(); Intersect intersect; List intersects = []; int l = object.children.length; if ( recursive ) { object.children.forEach((child) { intersects.addAll(intersectObject( child )); }); } if ( object is Particle ) { num distance = _distanceFromIntersection( origin, direction, object.matrixWorld.getTranslation() ); if ( distance > object.scale.x ) { return []; } intersect = new Intersect( distance: distance, point: object.position, face: null, object: object); intersects.add( intersect ); } else if ( object is Mesh ) { Mesh mesh = object; // Checking boundingSphere num distance = _distanceFromIntersection( origin, direction, object.matrixWorld.getTranslation() ); Vector3 scale = Frustum.__v1.setValues( object.matrixWorld.getColumn(0).length, object.matrixWorld.getColumn(1).length, object.matrixWorld.getColumn(2).length ); if ( distance > mesh.geometry.boundingSphere.radius * Math.max( scale.x, Math.max( scale.y, scale.z ) ) ) { return intersects; } // Checking faces int f; Face face; num dot, scalar; Geometry geometry = mesh.geometry; List vertices = geometry.vertices; Matrix4 objMatrix; Material material; List<Material> geometryMaterials = object.geometry.materials; bool isFaceMaterial = object.material is MeshFaceMaterial; int side = object.material.side; extractRotation(object.matrixRotationWorld, object.matrixWorld); int fl = geometry.faces.length; for (var f = 0; f < fl; f++) { face = geometry.faces[f]; material = isFaceMaterial == true ? geometryMaterials[ face.materialIndex ] : object.material; if ( material == null ) continue; side = material.side; originCopy.setFrom( origin ); directionCopy.setFrom( 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.setFrom(face.centroid); vector.applyProjection(objMatrix).sub(originCopy); normal.setFrom(face.normal); normal.applyProjection(object.matrixRotationWorld); dot = directionCopy.dot(normal); // bail if ray and plane are parallel if ( dot.abs() < 0.0001 ) continue; // calc distance to plane scalar = normal.dot( vector ) / dot; // if negative distance, then plane is behind ray if ( scalar < 0 ) continue; if ( side == DoubleSide || ( side == FrontSide ? dot < 0 : dot > 0 ) ) { intersectPoint = originCopy + directionCopy.scale(scalar); abcd = face.indices.map((idx) => vertices[idx].clone().applyProjection(objMatrix)).toList(); var pointInFace; // TODO - Make this work a face of arbitrary size if ( face.size == 3) { pointInFace = _pointInFace3( intersectPoint, abcd[0], abcd[1], abcd[2] ); } else if ( face.size == 4 ) { pointInFace = _pointInFace3( intersectPoint, abcd[0], abcd[1], abcd[3]) || _pointInFace3( intersectPoint, abcd[1], abcd[2], abcd[3] ); } if ( pointInFace ) { intersect = new Intersect( distance: originCopy.absoluteError( intersectPoint ), point: intersectPoint.clone(), face: face, object: object ); intersects.add( intersect ); } } } } return intersects; } List<Intersect> intersectObjects( List<Object3D> objects ) { int l = objects.length; List<Intersect> intersects = []; objects.forEach((o) => intersects.addAll(intersectObject(o))); intersects.sort( ( a, b ) => a.distance.compareTo(b.distance) ); return intersects; } }
Constructors
new Ray([Vector3 origin, Vector3 direction, num near = 0, num far = double.INFINITY]) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
docs inherited from Object
Ray( [this.origin, this.direction, this.near = 0, this.far = double.INFINITY] ) : precision = 0.0001 { if (this.origin == null) this.origin = new Vector3.zero(); if (this.direction == null) this.direction = new Vector3.zero(); }
Properties
Methods
List<Intersect> intersectObject(Object3D object, {bool recursive: false}) #
List<Intersect> intersectObject( Object3D object, {bool recursive: false} ) { List<Vector3> abcd = new List.generate(4, (_) => new Vector3.zero()); Vector3 originCopy = new Vector3.zero(); Vector3 directionCopy = new Vector3.zero(); Vector3 vector = new Vector3.zero(); Vector3 normal = new Vector3.zero(); Vector3 intersectPoint = new Vector3.zero(); Intersect intersect; List intersects = []; int l = object.children.length; if ( recursive ) { object.children.forEach((child) { intersects.addAll(intersectObject( child )); }); } if ( object is Particle ) { num distance = _distanceFromIntersection( origin, direction, object.matrixWorld.getTranslation() ); if ( distance > object.scale.x ) { return []; } intersect = new Intersect( distance: distance, point: object.position, face: null, object: object); intersects.add( intersect ); } else if ( object is Mesh ) { Mesh mesh = object; // Checking boundingSphere num distance = _distanceFromIntersection( origin, direction, object.matrixWorld.getTranslation() ); Vector3 scale = Frustum.__v1.setValues( object.matrixWorld.getColumn(0).length, object.matrixWorld.getColumn(1).length, object.matrixWorld.getColumn(2).length ); if ( distance > mesh.geometry.boundingSphere.radius * Math.max( scale.x, Math.max( scale.y, scale.z ) ) ) { return intersects; } // Checking faces int f; Face face; num dot, scalar; Geometry geometry = mesh.geometry; List vertices = geometry.vertices; Matrix4 objMatrix; Material material; List<Material> geometryMaterials = object.geometry.materials; bool isFaceMaterial = object.material is MeshFaceMaterial; int side = object.material.side; extractRotation(object.matrixRotationWorld, object.matrixWorld); int fl = geometry.faces.length; for (var f = 0; f < fl; f++) { face = geometry.faces[f]; material = isFaceMaterial == true ? geometryMaterials[ face.materialIndex ] : object.material; if ( material == null ) continue; side = material.side; originCopy.setFrom( origin ); directionCopy.setFrom( 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.setFrom(face.centroid); vector.applyProjection(objMatrix).sub(originCopy); normal.setFrom(face.normal); normal.applyProjection(object.matrixRotationWorld); dot = directionCopy.dot(normal); // bail if ray and plane are parallel if ( dot.abs() < 0.0001 ) continue; // calc distance to plane scalar = normal.dot( vector ) / dot; // if negative distance, then plane is behind ray if ( scalar < 0 ) continue; if ( side == DoubleSide || ( side == FrontSide ? dot < 0 : dot > 0 ) ) { intersectPoint = originCopy + directionCopy.scale(scalar); abcd = face.indices.map((idx) => vertices[idx].clone().applyProjection(objMatrix)).toList(); var pointInFace; // TODO - Make this work a face of arbitrary size if ( face.size == 3) { pointInFace = _pointInFace3( intersectPoint, abcd[0], abcd[1], abcd[2] ); } else if ( face.size == 4 ) { pointInFace = _pointInFace3( intersectPoint, abcd[0], abcd[1], abcd[3]) || _pointInFace3( intersectPoint, abcd[1], abcd[2], abcd[3] ); } if ( pointInFace ) { intersect = new Intersect( distance: originCopy.absoluteError( intersectPoint ), point: intersectPoint.clone(), face: face, object: object ); intersects.add( intersect ); } } } } return intersects; }
List<Intersect> intersectObjects(List<Object3D> objects) #
List<Intersect> intersectObjects( List<Object3D> objects ) { int l = objects.length; List<Intersect> intersects = []; objects.forEach((o) => intersects.addAll(intersectObject(o))); intersects.sort( ( a, b ) => a.distance.compareTo(b.distance) ); return intersects; }