package utils.scene.u3d;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import wblut.geom.WB_Intersection;
import wblut.geom.WB_Point3d;
import utils.scene.Point3D;
public class Ray {
Point3D origin = null;
Vector3D dir = null;
public static final float SMALL_NUM = 0.000001f;
public Ray(Point3D origin, Vector3D dir) {
this.origin = origin;
this.dir = dir;
}
public Point3D getOrigin() {
return origin;
}
public Vector3D getDirection() {
return dir;
}
/**
* Algorithm from Moller, Trumbore, "Fast, Minimum Storage
* Ray / Triangle Intersection", Journal of Graphics Tools, Volume 2,
* Number 1, 1997, pp. 21-28.
*/
public Point3D intersectsTriangle(Mesh3DTriangle triangle) {
Vector3D vert0 = new Vector3D(triangle.getPointOne().x, triangle.getPointOne().y, triangle.getPointOne().z);
Vector3D edge1 = triangle.getEdge1();
Vector3D edge2 = triangle.getEdge2();
if(triangle.getNorm() == 0)
return null;
// Begin calculating determinant -- also used to calculate U parameter
Vector3D pvec = getDirection().crossProduct(edge2);
// If determinant is near zero, ray lies in plane of triangle
float det = (float) edge1.dotProduct(pvec);
if (det > -SMALL_NUM && det < SMALL_NUM)
return null;
float invDet = 1.0f / det;
// Calculate distance from vert0 to ray origin
Vector3D tvec = new Vector3D(origin.x, origin.y, origin.z).subtract(vert0);
float a = (float) -(triangle.getN().dotProduct(tvec));
float b = (float) triangle.getN().dotProduct(getDirection());
if(a / b < 0)
return null;
// Calculate U parameter and test bounds
float u = (float) (tvec.dotProduct(pvec) * invDet);
if (u < 0.0f || u > 1.0f)
return null;
// Prepare to test V parameter
Vector3D qvec = tvec.crossProduct(edge1);
// Calculate V parameter and test bounds
float v = (float) (getDirection().dotProduct(qvec) * invDet);
if (v < 0.0f || (u + v) > 1.0f)
return null;
// Calculate t, ray intersects triangle
float t = (float) (edge2.dotProduct(qvec) * invDet);
return new Point3D(t, u, v);
}
/**
* Algorithm from Moller, Trumbore, "Fast, Minimum Storage
* Ray / Triangle Intersection", Journal of Graphics Tools, Volume 2,
* Number 1, 1997, pp. 21-28.
*/
public Point3D intersectsTriangle(Mesh3DTriangle triangle, float distance) {
WB_Point3d closestPoint = WB_Intersection.closestPointToTriangle(new WB_Point3d(getOrigin().x, getOrigin().y, getOrigin().z), new WB_Point3d(triangle.getPointOne().x, triangle.getPointOne().y, triangle.getPointOne().z), new WB_Point3d(triangle.getPointTwo().x, triangle.getPointTwo().y, triangle.getPointTwo().z), new WB_Point3d(triangle.getPointThree().x, triangle.getPointThree().y, triangle.getPointThree().z));
if((origin.x - closestPoint.x) * (origin.x - closestPoint.x) + (origin.y - closestPoint.y) * (origin.y- closestPoint.y) + (origin.z - closestPoint.z) * (origin.z - closestPoint.z) > distance * distance)
return null;
//if(new Point3D(getOrigin().x, getOrigin().y, getOrigin().z).getDistance(new Point3D((float) closestPoint.x, (float) closestPoint.y, (float) closestPoint.z)) > distance)
// return null;
Vector3D vert0 = new Vector3D(triangle.getPointOne().x, triangle.getPointOne().y, triangle.getPointOne().z);
Vector3D edge1 = triangle.getEdge1();
Vector3D edge2 = triangle.getEdge2();
if(triangle.getNorm() == 0)
return null;
// Begin calculating determinant -- also used to calculate U parameter
Vector3D pvec = getDirection().crossProduct(edge2);
// If determinant is near zero, ray lies in plane of triangle
float det = (float) edge1.dotProduct(pvec);
if (det > -SMALL_NUM && det < SMALL_NUM)
return null;
float invDet = 1.0f / det;
// Calculate distance from vert0 to ray origin
Vector3D tvec = new Vector3D(origin.x, origin.y, origin.z).subtract(vert0);
float a = (float) -(triangle.getN().dotProduct(tvec));
float b = (float) triangle.getN().dotProduct(getDirection());
if(a / b < 0)
return null;
// Calculate U parameter and test bounds
float u = (float) (tvec.dotProduct(pvec) * invDet);
if (u < 0.0f || u > 1.0f)
return null;
// Prepare to test V parameter
Vector3D qvec = tvec.crossProduct(edge1);
// Calculate V parameter and test bounds
float v = (float) (getDirection().dotProduct(qvec) * invDet);
if (v < 0.0f || (u + v) > 1.0f)
return null;
// Calculate t, ray intersects triangle
float t = (float) (edge2.dotProduct(qvec) * invDet);
return new Point3D(t, u, v);
}
/*public Point3D intersectsTriangle(Mesh3DTriangle triangle) {
Point3D I = new Point3D();
Vector3D u, v, n;
Vector3D dir, w0, w, p1;
float r, a, b;
p1 = new Vector3D(triangle.getPointOne().x, triangle.getPointOne().y, triangle.getPointOne().z);
u = new Vector3D(triangle.getPointTwo().x, triangle.getPointTwo().y, triangle.getPointTwo().z);
u = u.subtract(p1);
v = new Vector3D(triangle.getPointThree().x, triangle.getPointThree().y, triangle.getPointThree().z);
v = v.subtract(p1);
n = Vector3D.crossProduct(u, v);
if (n.getNorm() == 0) {
return null;
}
dir = getDirection();
w0 = new Vector3D(getOrigin().x, getOrigin().y, getOrigin().z);
w0 = w0.subtract(p1);
a = (float) -(new Vector3D(n.getX(), n.getY(), n.getZ()).dotProduct(w0));
b = (float) new Vector3D(n.getX(), n.getY(), n.getZ()).dotProduct(dir);
if ((float)Math.abs(b) < SMALL_NUM) {
return null;
}
r = a / b;
if (r < 0.0) {
return null;
}
I = getOrigin().clone();
I.x += r * dir.getX();
I.y += r * dir.getY();
I.z += r * dir.getZ();
float uu, uv, vv, wu, wv, D;
uu = (float) Vector3D.dotProduct(u,u);
uv = (float) Vector3D.dotProduct(u,v);
vv = (float) Vector3D.dotProduct(v,v);
w = new Vector3D(I.x - triangle.getPointOne().x, I.y - triangle.getPointOne().y, I.z - triangle.getPointOne().z);
wu = (float) Vector3D.dotProduct(w,u);
wv = (float) Vector3D.dotProduct(w,v);
D = uv * uv - uu * vv;
// get and test parametric coords
float s, t;
s = (uv * wv - vv * wu) / D;
if (s < 0.0 || s > 1.0) // I is outside T
return null;
t = (uv * wu - uu * wv) / D;
if (t < 0.0 || (s + t) > 1.0) // I is outside T
return null;
return I; // I is in T
}
public Point3D intersectsTriangle(Mesh3DTriangle triangle, float distance) {
WB_Point3d closestPoint = WB_Intersection.closestPointToTriangle(new WB_Point3d(getOrigin().x, getOrigin().y, getOrigin().z), new WB_Point3d(triangle.getPointOne().x, triangle.getPointOne().y, triangle.getPointOne().z), new WB_Point3d(triangle.getPointTwo().x, triangle.getPointTwo().y, triangle.getPointTwo().z), new WB_Point3d(triangle.getPointThree().x, triangle.getPointThree().y, triangle.getPointThree().z));
if(new Point3D(getOrigin().x, getOrigin().y, getOrigin().z).getDistance(new Point3D((float) closestPoint.x, (float) closestPoint.y, (float) closestPoint.z)) > distance)
return null;
Point3D I = new Point3D();
Vector3D u, v, n;
Vector3D dir, w0, w, p1;
float r, a, b;
p1 = new Vector3D(triangle.getPointOne().x, triangle.getPointOne().y, triangle.getPointOne().z);
u = new Vector3D(triangle.getPointTwo().x, triangle.getPointTwo().y, triangle.getPointTwo().z);
u = u.subtract(p1);
v = new Vector3D(triangle.getPointThree().x, triangle.getPointThree().y, triangle.getPointThree().z);
v = v.subtract(p1);
n = Vector3D.crossProduct(u, v);
if (n.getNorm() == 0) {
return null;
}
dir = getDirection();
w0 = new Vector3D(getOrigin().x, getOrigin().y, getOrigin().z);
w0 = w0.subtract(p1);
a = (float) -(new Vector3D(n.getX(), n.getY(), n.getZ()).dotProduct(w0));
b = (float) new Vector3D(n.getX(), n.getY(), n.getZ()).dotProduct(dir);
if ((float)Math.abs(b) < SMALL_NUM) {
return null;
}
r = a / b;
if (r < 0.0) {
return null;
}
I = getOrigin().clone();
I.x += r * dir.getX();
I.y += r * dir.getY();
I.z += r * dir.getZ();
float uu, uv, vv, wu, wv, D;
uu = (float) Vector3D.dotProduct(u,u);
uv = (float) Vector3D.dotProduct(u,v);
vv = (float) Vector3D.dotProduct(v,v);
w = new Vector3D(I.x - triangle.getPointOne().x, I.y - triangle.getPointOne().y, I.z - triangle.getPointOne().z);
wu = (float) Vector3D.dotProduct(w,u);
wv = (float) Vector3D.dotProduct(w,v);
D = uv * uv - uu * vv;
// get and test parametric coords
float s, t;
s = (uv * wv - vv * wu) / D;
if (s < 0.0 || s > 1.0) // I is outside T
return null;
t = (uv * wu - uu * wv) / D;
if (t < 0.0 || (s + t) > 1.0) // I is outside T
return null;
return I; // I is in T
}*/
}