提交 14ad3788 编写于 作者: B Ben Houston

All unit tests pass now for Box2, Box3 and Triangle3. Fix bug in Plane.js...

All unit tests pass now for Box2, Box3 and Triangle3.  Fix bug in Plane.js caught in Triangle3 unit tests.  Replace Raycaster.pointInFace3 with Triangle3.containsPoint, no loss of FPS in examples.
上级 e47032d0
......@@ -37,26 +37,6 @@
// http://www.blackpawn.com/texts/pointinpoly/default.html
var pointInFace3 = function ( p, a, b, c ) {
v0.sub( c, a );
v1.sub( b, a );
v2.sub( p, a );
var dot00 = v0.dot( v0 );
var dot01 = v0.dot( v1 );
var dot02 = v0.dot( v2 );
var dot11 = v1.dot( v1 );
var dot12 = v1.dot( v2 );
var invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 );
var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 );
};
var intersectObject = function ( object, raycaster, intersects ) {
if ( object instanceof THREE.Particle ) {
......@@ -149,7 +129,7 @@
b = vertices[ face.b ];
c = vertices[ face.c ];
if ( ! pointInFace3( intersectPoint, a, b, c ) ) continue;
if ( ! THREE.Triangle3.containsPoint( intersectPoint, a, b, c ) ) continue;
} else if ( face instanceof THREE.Face4 ) {
......@@ -158,8 +138,8 @@
c = vertices[ face.c ];
d = vertices[ face.d ];
if ( ( ! pointInFace3( intersectPoint, a, b, d ) ) &&
( ! pointInFace3( intersectPoint, b, c, d ) ) ) continue;
if ( ( ! THREE.Triangle3.containsPoint( intersectPoint, a, b, d ) ) &&
( ! THREE.Triangle3.containsPoint( intersectPoint, b, c, d ) ) ) continue;
} else {
......
......@@ -140,7 +140,7 @@ THREE.Box3.prototype = {
},
size: function () {
size: function ( optionalTarget ) {
var result = optionalTarget || new THREE.Vector3();
return result.sub( this.max, this.min );
......
......@@ -51,8 +51,8 @@ THREE.Plane.prototype = {
setFromCoplanarPoints: function ( a, b, c ) {
var normal = THREE.Plane.__v1.sub( b, a ).cross(
THREE.Plane.__v2.sub( c, a ) );
var normal = THREE.Plane.__v1.sub( c, b ).crossSelf(
THREE.Plane.__v2.sub( a, b ) );
// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?
......
......@@ -18,6 +18,42 @@ THREE.Triangle3 = function ( a, b, c ) {
};
// static/instance method to calculate barycoordinates
THREE.Triangle3.barycoordinate = function ( point, a, b, c, optionalTarget ) {
THREE.Triangle3.__v0.sub( c, a );
THREE.Triangle3.__v1.sub( b, a );
THREE.Triangle3.__v2.sub( point, a );
var dot00 = THREE.Triangle3.__v0.dot( THREE.Triangle3.__v0 );
var dot01 = THREE.Triangle3.__v0.dot( THREE.Triangle3.__v1 );
var dot02 = THREE.Triangle3.__v0.dot( THREE.Triangle3.__v2 );
var dot11 = THREE.Triangle3.__v1.dot( THREE.Triangle3.__v1 );
var dot12 = THREE.Triangle3.__v1.dot( THREE.Triangle3.__v2 );
var denom = ( dot00 * dot11 - dot01 * dot01 );
// colinear or singular triangle
if( denom == 0 ) {
return false;
}
var invDenom = 1 / denom;
var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
var result = optionalTarget || new THREE.Vector3();
return result.set( u, v, 1 - u - v );
}
THREE.Triangle3.containsPoint = function ( point, a, b, c ) {
var result = THREE.Triangle3.barycoordinate( point, a, b, c, THREE.Triangle3.__v3 );
return ( result.x >= 0 ) && ( result.y >= 0 ) && ( ( result.x + result.y ) <= 1 );
}
THREE.Triangle3.prototype = {
constructor: THREE.Triangle3,
......@@ -54,17 +90,17 @@ THREE.Triangle3.prototype = {
area: function () {
__v0.sub( this.c, this.b );
__v1.sub( this.a, this.b );
THREE.Triangle3.__v0.sub( this.c, this.b );
THREE.Triangle3.__v1.sub( this.a, this.b );
return __v0.cross( __v1 ).length() * 0.5;
return THREE.Triangle3.__v0.crossSelf( THREE.Triangle3.__v1 ).length() * 0.5;
},
midpoint: function ( optionalTarget ) {
var result = optionalTarget || new THREE.Vector3();
return result.add( this.a, this.b ).addSelf( this.b ).multiplyScalar( 1 / 3 );
return result.add( this.a, this.b ).addSelf( this.c ).multiplyScalar( 1 / 3 );
},
......@@ -73,19 +109,17 @@ THREE.Triangle3.prototype = {
var result = optionalTarget || new THREE.Vector3();
result.sub( this.c, this.b );
__v0.sub( this.a, this.b );
result.cross( __v0 );
THREE.Triangle3.__v0.sub( this.a, this.b );
result.crossSelf( THREE.Triangle3.__v0 );
var resultLengthSq = result.lengthSq();
if( resultLengthSq > 0 ) {
return result.multiplyScalar( 1 / resultLengthSq );
return result.multiplyScalar( 1 / Math.sqrt( resultLengthSq ) );
}
// It is usually best to return a non-zero normal, even if it is made up, to avoid
// special case code to handle zero-length normals.
return result.set( 1, 0, 0 );
return result.set( 0, 0, 0 );
},
......@@ -97,23 +131,15 @@ THREE.Triangle3.prototype = {
},
containsPoint: function ( point ) {
barycoordinate: function ( point, optionalTarget ) {
__v0.sub( c, a );
__v1.sub( b, a );
__v2.sub( point, a );
return THREE.Triangle3.barycoordinate( point, this.a, this.b, this.c, optionalTarget );
var dot00 = __v0.dot( __v0 );
var dot01 = __v0.dot( __v1 );
var dot02 = __v0.dot( __v2 );
var dot11 = __v1.dot( __v1 );
var dot12 = __v1.dot( __v2 );
},
var invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 );
var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
containsPoint: function ( point ) {
return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 );
return THREE.Triangle3.containsPoint( point, this.a, this.b, this.c );
},
......@@ -134,3 +160,4 @@ THREE.Triangle3.prototype = {
THREE.Triangle3.__v0 = new THREE.Vector3();
THREE.Triangle3.__v1 = new THREE.Vector3();
THREE.Triangle3.__v2 = new THREE.Vector3();
THREE.Triangle3.__v3 = new THREE.Vector3();
......@@ -194,18 +194,18 @@ test( "isIntersectionBox", function() {
var b = new THREE.Box2( zero2, one2 );
var c = new THREE.Box2( one2.clone().negate(), one2 );
ok( a.isIntersection( a ), "Passed!" );
ok( a.isIntersection( b ), "Passed!" );
ok( a.isIntersection( c ), "Passed!" );
ok( a.isIntersectionBox( a ), "Passed!" );
ok( a.isIntersectionBox( b ), "Passed!" );
ok( a.isIntersectionBox( c ), "Passed!" );
ok( b.isIntersection( a ), "Passed!" );
ok( c.isIntersection( a ), "Passed!" );
ok( b.isIntersection( c ), "Passed!" );
ok( b.isIntersectionBox( a ), "Passed!" );
ok( c.isIntersectionBox( a ), "Passed!" );
ok( b.isIntersectionBox( c ), "Passed!" );
b.translate( new THREE.Vector2( 2, 2 ) );
ok( ! a.isIntersection( b ), "Passed!" );
ok( ! b.isIntersection( a ), "Passed!" );
ok( ! b.isIntersection( c ), "Passed!" );
ok( ! a.isIntersectionBox( b ), "Passed!" );
ok( ! b.isIntersectionBox( a ), "Passed!" );
ok( ! b.isIntersectionBox( c ), "Passed!" );
});
test( "intersect", function() {
......
......@@ -194,18 +194,18 @@ test( "isIntersectionBox", function() {
var b = new THREE.Box3( zero3, one3 );
var c = new THREE.Box3( one3.clone().negate(), one3 );
ok( a.isIntersection( a ), "Passed!" );
ok( a.isIntersection( b ), "Passed!" );
ok( a.isIntersection( c ), "Passed!" );
ok( a.isIntersectionBox( a ), "Passed!" );
ok( a.isIntersectionBox( b ), "Passed!" );
ok( a.isIntersectionBox( c ), "Passed!" );
ok( b.isIntersection( a ), "Passed!" );
ok( c.isIntersection( a ), "Passed!" );
ok( b.isIntersection( c ), "Passed!" );
ok( b.isIntersectionBox( a ), "Passed!" );
ok( c.isIntersectionBox( a ), "Passed!" );
ok( b.isIntersectionBox( c ), "Passed!" );
b.translate( new THREE.Vector3( 2, 2, 2 ) );
ok( ! a.isIntersection( b ), "Passed!" );
ok( ! b.isIntersection( a ), "Passed!" );
ok( ! b.isIntersection( c ), "Passed!" );
ok( ! a.isIntersectionBox( b ), "Passed!" );
ok( ! b.isIntersectionBox( a ), "Passed!" );
ok( ! b.isIntersectionBox( c ), "Passed!" );
});
test( "intersect", function() {
......
......@@ -47,15 +47,15 @@ test( "area", function() {
ok( a.area() == 0, "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 1, 0, 0, ), new THREE.Vector3( 0, 1, 0, ) );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
ok( a.area() == 0.5, "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0, ), new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 0, 0, 2, ) );
ok( a.empty() == 2, "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) );
ok( a.area() == 2, "Passed!" );
// colinear triangle.
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0, ), new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 3, 0, 0, ) );
ok( a.empty() == 0, "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 3, 0, 0 ) );
ok( a.area() == 0, "Passed!" );
});
test( "midpoint", function() {
......@@ -63,23 +63,22 @@ test( "midpoint", function() {
ok( a.midpoint().equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 1, 0, 0, ), new THREE.Vector3( 0, 1, 0, ) );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
ok( a.midpoint().equals( new THREE.Vector3( 1/3, 1/3, 0 ) ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0, ), new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 0, 0, 2, ) );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) );
ok( a.midpoint().equals( new THREE.Vector3( 2/3, 0, 2/3 ) ), "Passed!" );
});
test( "normal", function() {
var a = new THREE.Triangle3();
// artificial normal is created in this case.
ok( a.normal().equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" );
ok( a.normal().equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 1, 0, 0, ), new THREE.Vector3( 0, 1, 0, ) );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
ok( a.normal().equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0, ), new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 0, 0, 2, ) );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) );
ok( a.normal().equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" );
});
......@@ -90,37 +89,39 @@ test( "plane", function() {
ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" );
ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" );
ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" );
ok( a.plane().equal( a.normal() ), "Passed!" );
ok( a.plane().normal.equals( a.normal() ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 1, 0, 0, ), new THREE.Vector3( 0, 1, 0, ) );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" );
ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" );
ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" );
ok( a.plane().equal( a.normal() ), "Passed!" );
ok( a.plane().normal.equals( a.normal() ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0, ), new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 0, 0, 2, ) );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) );
ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" );
ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" );
ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" );
ok( a.plane().equal( a.normal() ), "Passed!" );
ok( a.plane().normal.clone().normalize().equals( a.normal() ), "Passed!" );
});
test( "containsPoint", function() {
var a = new THREE.Triangle3();
ok( ! a.containsPoint( a.a ), "Passed!" );
ok( ! a.containsPoint( a.b ), "Passed!" );
ok( ! a.containsPoint( a.c ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
ok( a.containsPoint( a.a ), "Passed!" );
ok( a.containsPoint( a.b ), "Passed!" );
ok( a.containsPoint( a.c ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 1, 0, 0, ), new THREE.Vector3( 0, 1, 0, ) );
ok( a.containsPoint( a.a ) == 0, "Passed!" );
ok( a.containsPoint( a.b ) == 0, "Passed!" );
ok( a.containsPoint( a.c ) == 0, "Passed!" );
ok( a.containsPoint( a.midpoint() ), "Passed!" );
ok( ! a.containsPoint( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0, ), new THREE.Vector3( 0, 0, 0, ), new THREE.Vector3( 0, 0, 2, ) );
ok( a.containsPoint( a.a ) == 0, "Passed!" );
ok( a.containsPoint( a.b ) == 0, "Passed!" );
ok( a.containsPoint( a.c ) == 0, "Passed!" );
a = new THREE.Triangle3( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) );
ok( a.containsPoint( a.a ), "Passed!" );
ok( a.containsPoint( a.b ), "Passed!" );
ok( a.containsPoint( a.c ), "Passed!" );
ok( a.containsPoint( a.midpoint() ), "Passed!" );
ok( ! a.containsPoint( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" );
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册