2
votes

I am implementing ray tracing in C++. Spheres are working fine and the cylinders are almost working fine. But ray tracer is not able to find intersections with a cone. After calculations, based on the link here, I created an intersection function. Here is the findIntersection function of my cone class. variable ratio is -1 * radius * radius / (height * height);

virtual double findIntersection(Ray ray){


                Vect ray_origin = ray.getRayOrigin();
                double ray_origin_x = ray_origin.getVectX();
                double ray_origin_y = ray_origin.getVectY();
                double ray_origin_z = ray_origin.getVectZ();

                Vect ray_direction = ray.getRayDirection();
                double ray_direction_x = ray_direction.getVectX();
                double ray_direction_y = ray_direction.getVectY();
                double ray_direction_z = ray_direction.getVectZ();

                Vect cone_center  = center;
                double cone_center_x = center.getVectX();
                double cone_center_y = center.getVectY();
                double cone_center_z = center.getVectZ();

        Vect diff(cone_center_x - ray_origin_x, cone_center_y - ray_origin_y + height, cone_center_z - ray_origin_z);

        //Derive the coefficients of the quadratic equation
        double a = pow(ray_direction_x, 2) + pow(ray_direction_y, 2) * ratio + pow(ray_direction_z, 2);
        double b = diff.getVectX() * ray_direction_x +  diff.getVectY() * ratio * ray_direction_y + diff.getVectZ() * ray_direction_z;

        double c = diff.getVectX() * diff.getVectX() + ratio * diff.getVectY() * diff.getVectY() + diff.getVectZ() * diff.getVectZ();

        double discriminant = b * b - a * c;
        cout << discriminant << "\n";

        if (discriminant > 0){
            //The ray intersects this cone. Find the lower root
            double root_1 = (-1 * b - discriminant)/2 - 0.000001;
                       if (root_1 > 0) {

                                // the first root is the smallest positive root
                                return root_1;
                        }
                        else {
                                // the second root is the smallest positive root
                                double root_2 = ((sqrt(discriminant) - b)/2) - 0.000001;
                                return root_2;
                        }
                }
                else {
                        // the ray missed the cone
                        return -1;

        }

    }

The problem is in the calculation of variable discriminant. They are coming out to be negative and so no intersection is being returned. The intersection functions in this program return the distance from the ray origin to the intersection point.

Please can someone take a look at the cone calculations and tell me if I am doing something wrong.

Regards, Moira

1
What happened to 4 in discriminant formula D = b*b - 4*a*c? Also, why are you not taking sqrt from discriminant when calculating the first root? And why are you not dividing by 2 * a when calculating the roots? - AnT
Thanks for your reply Andrey. I removed 4 in calculating discriminant because I removed the multiplication of 2 in the calculation of b. This was to reduce the extra multiplications. I fixed the sqrt issue and the roots calculation is now divided by 'a' instead of 2 (not by 2a because of the reason mentioned above). Still the determinant values are negative so the code does not event go to calculate the roots coz they will be imaginary values anyways. - Moira
Ah! I found the issue. It was in another function where ratio was being calculated. I was declaring ratio again inside the function so the class member variable ratio was not being updated. The discriminants are positive at least some times. (If not exactly when I wanted.). I will look into it. Thanks for your help. - Moira

1 Answers

0
votes

I couldn't follow that link, but your "discriminant" looks wrong.

Suppose ratio (whatever that is) is 1. Then we have

a = ray2
b = diff . ray
c = diff2

discriminant = b * b - a * c = (diff . ray)2 - diff2ray2

The first term will be at most |diff||ray| (when ray and diff are parallel), so the discriminant will be zero at most.