Post by krystal223 on Jan 17, 2021 23:59:51 GMT
Hello,
I am trying to render a capped cone with min and max of -1 and 1 respectively. However, as seen from the attached image, something goes slightly wrong when rendering the bottom of the cone - the cap seems to cut off a part of the cone. Below is my Cone.h - any help is appreciated!
I am trying to render a capped cone with min and max of -1 and 1 respectively. However, as seen from the attached image, something goes slightly wrong when rendering the bottom of the cone - the cap seems to cut off a part of the cone. Below is my Cone.h - any help is appreciated!
class Cone : public Geometry
{
public:
Cone()
: Geometry(), ymin(-1), ymax(1), closed(true) {}
Cone(float min, float max, bool c = true)
: Geometry(), ymin(min), ymax(max), closed(c) {}
Cone(const Matrix& _transform, const Material& mat)
: Geometry(_transform, mat), ymin(-1), ymax(1), closed(true) {}
Cone(const Matrix& _transform, const Material& mat, float min, float max, bool c = true)
: Geometry(_transform, mat), ymin(min), ymax(max), closed(c) {}
Tuple normalAt(const Tuple& point) const
{
Tuple ObjectNormal = point * inverseTransform;
float dist = ObjectNormal.x * ObjectNormal.x + ObjectNormal.z * ObjectNormal.z;
Tuple t;
if (dist < 1.0f && ObjectNormal.y > ymax)
t = Tuple(0, 1, 0, 0);
else if (dist < 1.0f && ObjectNormal.y < ymin)
t = Tuple(0, -1, 0, 0);
float y = sqrtf(ObjectNormal.x * ObjectNormal.x + ObjectNormal.z * ObjectNormal.z);
if (ObjectNormal.y > 0.0f)
y = -y;
t = Tuple(ObjectNormal.x, y, ObjectNormal.z, 0);
t *= inverseTransform.transposed();
t.w = 0;
return t;
}
std::vector<Intersection> intersects(Ray& r)
{
Ray ray = r.transformed(inverseTransform);
float a = ray.direction.x * ray.direction.x - ray.direction.y * ray.direction.y + ray.direction.z * ray.direction.z;
float b = 2.0f * ray.origin.x * ray.direction.x - 2.0f * ray.origin.y * ray.direction.y + 2.0f * ray.origin.z * ray.direction.z;
float c = ray.origin.x * ray.origin.x - ray.origin.y * ray.origin.y + ray.origin.z * ray.origin.z;
std::vector<Intersection> intersects;
if (fabsf(a) < 0.005f && fabsf(b) >= 0.005f)
intersects.push_back({ -c / 2 * b, this });
if (fabsf(a) >= 0.005f)
{
float disc = b * b - 4 * a * c;
if (disc >= 0.0f)
{
float t0 = (-b - sqrtf(disc)) / (2 * a);
float t1 = (-b + sqrtf(disc)) / (2 * a);
if (t0 > t1)
std::swap(t0, t1);
Tuple nearHit = ray.position(t0);
if (nearHit.y > ymin && nearHit.y < ymax)
intersects.push_back({ t0, this });
Tuple farHit = ray.position(t1);
if (farHit.y > ymin && farHit.y < ymax)
intersects.push_back({ t1, this });
}
}
capIntersects(ray, intersects);
return intersects;
}
float ymin;
float ymax;
bool closed;
private:
bool checkCap(Ray& r, float dist, float y)
{
Tuple t = r.position(dist);
return (t.x * t.x + t.z * t.z) <= (y * y);
}
void capIntersects(Ray& r, std::vector<Intersection>& intersects)
{
if (closed == false || fabsf(r.direction.y) <= 0.005f)
return;
float t0 = (ymin - r.origin.y) / r.direction.y;
if (checkCap(r, t0, ymin))
intersects.push_back({ t0, this });
float t1 = (ymax - r.origin.y) / r.direction.y;
if (checkCap(r, t1, ymax))
intersects.push_back({ t1, this });
}
};