Post by likeaglove on Apr 15, 2020 1:52:36 GMT
I have implemented the Cone Shape from Chapter 13 All tests and examples pass except one. In the test scenario: Intersecting a cone with a ray. With inputs point(0, 0, -5) | vector(1, 1, 1) the expected output is t0 = 8.66025 & t1 = 8.66025;
However, the LocalIntersect function is returning an empty Array, when debugging I see that the "disc" value is a rather large negative value.
Here is the set up code:
I was wondering if anybody could point out an error in my Cone implementation. All other tests in the chapter pass, including the ones beyond this example.
However, the LocalIntersect function is returning an empty Array, when debugging I see that the "disc" value is a rather large negative value.
Here is the set up code:
Cone con = new Cone();
Tuple Origin = new Tuple(0f,0f,-5f,1);
Tuple Direction = new Tuple(1f,1f,1f,0).Normalise();
Ray r = new Ray(Origin,Direction);
Intersection[] xs = con.LocalIntersect(r);
Console.WriteLine(xs.Length);
Console.WriteLine(xs[0].T_Value);
Console.WriteLine(xs[1].T_Value);
This results in a out of bounds exception, due to the Intersection Array being empty, where it should be filled with duplicated 8.66025 values.I was wondering if anybody could point out an error in my Cone implementation. All other tests in the chapter pass, including the ones beyond this example.
using System;
using System.Collections.Generic;
namespace The_Ray_Tracer_Challenge
{
public class Cone : Shape
{
public float minimum { get; set; } = float.NegativeInfinity;
public float maximum { get; set; } = float.PositiveInfinity;
public bool closed { get; set; } = false;
public override Intersection[] LocalIntersect(Ray localRay)
{
List<Intersection> xsList = new List<Intersection>();
Tuple o = localRay.Origin;
Tuple d = localRay.Direction;
float a = localRay.Direction.x * localRay.Direction.x - localRay.Direction.y * localRay.Direction.y + localRay.Direction.z * localRay.Direction.z;
float b = 2.0f * localRay.Origin.x * localRay.Direction.x - 2.0f * localRay.Origin.y * localRay.Direction.y + 2.0f * localRay.Origin.z * localRay.Direction.z;
float c = localRay.Origin.x * localRay.Origin.x - localRay.Origin.y * localRay.Origin.y + localRay.Origin.z * localRay.Origin.z;
if (a <= 0 && MathF.Abs(b) > 0)
{
float t = -c / (2 * b);
xsList.Add(new Intersection(t, this));
}
if (a != 0)
{
float disc = (b * b) - 4.0f * a * c;
if (disc >= 0)
{
float t0 = (-b - MathF.Sqrt(disc)) / (2 * a);
float t1 = (-b + MathF.Sqrt(disc)) / (2 * a);
if (t0 > t1)
{
float temp = t0;
t0 = t1;
t1 = temp;
}
float y0 = localRay.Origin.y + t0 * localRay.Direction.y;
if (this.minimum < y0 && y0 < this.maximum)
{
xsList.Add(new Intersection(t0, this));
}
float y1 = localRay.Origin.y + t1 * localRay.Direction.y;
if (this.minimum < y1 && y1 < this.maximum)
{
xsList.Add(new Intersection(t1, this));
}
}
}
IntersectCaps(this, localRay, xsList);
return xsList.ToArray();
}
public override Tuple LocalNormalAt(Tuple localPoint)
{
float dist = localPoint.x * localPoint.x + localPoint.z * localPoint.z;
if (dist < 1 && localPoint.y >= this.maximum - Arithmetic.EPSILON)
{
return new Tuple(0, 1, 0, 0);
}
if (dist < 1 && localPoint.y <= this.minimum + Arithmetic.EPSILON)
{
return new Tuple(0, -1, 0, 0);
}
float y = MathF.Sqrt(dist);
if (localPoint.y > 0)
{
y *= -1;
}
return new Tuple(localPoint.x, y, localPoint.z);
}
private static bool CheckCap(Ray r, float t, float y)
{
float x = r.Origin.x + t * r.Direction.x;
float z = r.Origin.z + t * r.Direction.z;
return (x * x) + (z * z) <= y * y;
}
private static void IntersectCaps(Cone cyl, Ray r, List<Intersection> xsList)
{
if (!cyl.closed || (r.Direction.y) <= Arithmetic.EPSILON)
{
return;
}
float t = (cyl.minimum - r.Origin.y) / r.Direction.y;
if (CheckCap(r, t, cyl.minimum))
{
xsList.Add(new Intersection(t, cyl));
}
t = (cyl.maximum - r.Origin.y) / r.Direction.y;
if (CheckCap(r, t, cyl.minimum))
{
xsList.Add(new Intersection(t, cyl));
}
return;
}
}
}