Post by pab6750 on Aug 8, 2020 8:21:25 GMT
Hi, I have been trying to implement cones for the ray tracer, but I can't get one of the tests to pass. The test in question is the "Intersecting a cone's end caps" test, the second ray is supposed to intersect the cone twice, but my code only returns one intersection. That is because a is very close to 0 and b is not, so the code returns the case where the single intersection point is t = -c/2b. I've been debugging for ages, but can't see anything that could be wrong, any help would be appreciated.
for reference, here's my code:
for reference, here's my code:
@Override
public Intersection[] localIntersect(Ray r) {
double a = r.getDirection().getX() * r.getDirection().getX()
- r.getDirection().getY() * r.getDirection().getY()
+ r.getDirection().getZ() * r.getDirection().getZ();
double b = 2 * r.getOrigin().getX() * r.getDirection().getX()
- 2 * r.getOrigin().getY() * r.getDirection().getY()
+ 2 * r.getOrigin().getZ() * r.getDirection().getZ();
double c = r.getOrigin().getX() * r.getOrigin().getX()
- r.getOrigin().getY() * r.getOrigin().getY()
+ r.getOrigin().getZ() * r.getOrigin().getZ();
if(Math.abs(a) <= Tuple.EPSILON && Math.abs(b) > Tuple.EPSILON) {
Intersection[] xs = new Intersection[1];
xs[0] = new Intersection(-c / (2 * b), this);
return xs;
}
if(Math.abs(a) <= Tuple.EPSILON && Math.abs(b) <= Tuple.EPSILON) {
return null;
}
double discriminant = (b * b) - (4 * a * c);
if(discriminant < 0) {
return null;
}
double t0 = (-b - Math.sqrt(discriminant)) / (2 * a);
double t1 = (-b + Math.sqrt(discriminant)) / (2 * a);
if(t0 > t1) {
double temp = t0;
t0 = t1;
t1 = temp;
}
ArrayList<Intersection> xsTemp = new ArrayList<Intersection>();
double y0 = r.getOrigin().getY() + t0 * r.getDirection().getY();
if(this.minimum < y0 && y0 < this.maximum) {
xsTemp.add(new Intersection(t0, this));
}
double y1 = r.getOrigin().getY() + t1 * r.getDirection().getY();
if(this.minimum < y1 && y1 < this.maximum) {
xsTemp.add(new Intersection(t1, this));
}
this.intersectCaps(r, xsTemp);
Intersection[] xs = new Intersection[xsTemp.size()];
for(int i = 0; i < xsTemp.size(); i++) {
xs[i] = xsTemp.get(i);
}
return xs;
}
@Override
public Tuple localNormalAt(Tuple p) {
double dist = p.getX() * p.getX() + p.getZ() * p.getZ();
double y = Math.sqrt(dist);
if(y > 0) {
y *= -1;
}
if(dist < 1 && p.getY() >= this.maximum - Tuple.EPSILON) {
return new Tuple(0, 1, 0, Tuple.VECTOR);
} else if(dist < 1 && p.getY() <= this.minimum + Tuple.EPSILON) {
return new Tuple(0, -1, 0, Tuple.VECTOR);
} else {
return new Tuple(p.getX(), y, p.getZ(), Tuple.VECTOR);
}
}
private void intersectCaps(Ray r, ArrayList<Intersection> xs) {
if(!this.closed || Math.abs(r.getDirection().getY()) <= Tuple.EPSILON) {
return;
}
double t = (this.minimum - r.getOrigin().getY()) / r.getDirection().getY();
if(this.checkCap(r, t, this.minimum)) {
xs.add(new Intersection(t, this));
}
t = (this.maximum - r.getOrigin().getY()) / r.getDirection().getY();
if(this.checkCap(r, t, this.maximum)) {
xs.add(new Intersection(t, this));
}
}
private boolean checkCap(Ray r, double t, double y) {
double x = r.getOrigin().getX() + t * r.getDirection().getX();
double z = r.getOrigin().getZ() + t * r.getDirection().getZ();
return (x * x + z * z) <= y * y;
}