### 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

for reference, here's my code:

*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:

`@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;

}