Dart DocumentationthreeRay

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

Vector3 direction #

Vector3 origin,
       direction

num far #

num near,
   far

num near #

num near

Vector3 origin #

Vector3 origin

final num precision #

final num precision

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;
}