C#中正交相机的实现

Implementation of Orthogonal Camera in C#

我正在制作一个简单的光线追踪器,现在我正在尝试制作一个显示球体的简单正交视图,但我得到的不是黑色背景上的红色圆圈,而是一个红色矩形...

在我的球体中class我有一个方法来检查光线是否击中球体:

    public bool IntersectsRay(Ray ray) //c -> origin, R -> radius, o - origin ray, 
    //d - direction ray 
    {
        Vector3 d = ray.direction;
        Vector3 o = ray.origin;
        Vector3 c = origin;
        double R = radius;

        double A = d.DotVector(d); //d^2
        double B = 2 * d.DotVector(o.MinusVector(c)); //2d(o - c)
        double C = (o.MinusVector(c)).DotVector(o.MinusVector(c)) - radius * radius; //(o - c)(o - c) - R^2

        double delta = B * B - 4 * A * C;

        if (delta < 0)
        {
            Console.WriteLine("There are no intersection points");
            return false;
        }
        else
        {
            Console.WriteLine("delta is equal to: {0}", delta);

            double t1 = (-B + Math.Sqrt(delta)) / 2 * A;
            double t2 = (-B - Math.Sqrt(delta)) / 2 * A;

            if (t1.Equals(t2))
            {
                Vector3 P1 = o.PlusVector(d.MultiplyByScalar((float)t1));

                Console.WriteLine("P0: ({0}, {1}, {2})", P1.x, P1.y, P1.z);
                return true;
            }
            else
            {
                Vector3 P1 = o.PlusVector(d.MultiplyByScalar((float)t1));
                Vector3 P2 = o.PlusVector(d.MultiplyByScalar((float)t2));

                Console.WriteLine("P1: ({0}, {1}, {2}), P2: ({3}, {4}, {5})", P1.x, P1.y, P1.z, P2.x, P2.y, P2.z);
                return true;
            }
        }
    }

正交相机class:

public class CamOrthogonal
{
    public Bitmap BM;
    private float pixelWidth;
    private float pixelHeight;
    private float centerPixelX;
    private float centerPixelY;
    private bool intersection;

    public CamOrthogonal()
    {
        this.BM = new Bitmap(240, 240, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    }

    public CamOrthogonal(Img IMG)
    {
        this.BM = IMG.BM;
    }

    public void render(Sphere S)
    {
        pixelWidth = 2.0f / BM.Width;
        pixelHeight = 2.0f / BM.Height;

        for (int i = 0; i < BM.Width; i++)
        {
            for (int j = 0; j < BM.Height; j++)
            {
                centerPixelX = -1.0f + (i + 0.5f) * pixelWidth;
                centerPixelY = 1.0f - (j + 0.5f) * pixelHeight;

                //Ray ray = new Ray(new Vector3(0, 0, 1), new Vector3(centerPixelX, centerPixelX, 0));
                Ray ray = new Ray(new Vector3(centerPixelX, centerPixelX, 0), new Vector3(0, 0, 1));

                /* if (Plane_or_Sphere is Plane)
                {
                    intersection = ((Plane)Plane_or_Sphere).IntersectsRay(ray);
                }
                else if (Plane_or_Sphere is Sphere)
                {
                    intersection = ((Sphere)Plane_or_Sphere).IntersectsRay(ray);
                } */

                intersection = S.IntersectsRay(ray);

                if (intersection == true)
                {
                    this.BM.SetPixel(i, j, Color.Red);
                }
                else 
                {
                    this.BM.SetPixel(i, j, Color.Black);
                }
            }
        }
        this.BM.Save("/Users/Aleksy/Desktop/RT_IMG.jpg");
    }
}

然后,在我的主要 class 我有:

CamOrthogonal CAM = new CamOrthogonal();
Sphere S = new Sphere(0, 0, -10, (float)0.1); //origin - x,y,z & radius
CAM.render(S);

我得到的是那个红色矩形。我哪里做错了?

在您的代码中,您有:

double t1 = (-B + Math.Sqrt(delta)) / 2 * A;

在 C# 中,这是根据 operator precedence rules 计算的,其中规定 */ 是乘法运算符。它还说:

The operators within each section share the same precedence level.

因此,*/具有同等的优先级;他们从左到右评估。因此,您的陈述将得到如下评估:

double t1 = (((-B + Math.Sqrt(delta)) / 2) * A);

然而,你真正要解的二次方程是这样的:

double t1 = (-B + Math.Sqrt(delta)) / (2 * A);

...t2.

也一样

编辑

另外,你的命中条件不正确:

if (t1.Equals(t2))
{
   Vector3 P1 = o.PlusVector(d.MultiplyByScalar((float)t1));
   Console.WriteLine("P0: ({0}, {1}, {2})", P1.x, P1.y, P1.z);
   return true;
}
else
{
   Vector3 P1 = o.PlusVector(d.MultiplyByScalar((float)t1));
   Vector3 P2 = o.PlusVector(d.MultiplyByScalar((float)t2));
   Console.WriteLine("P1: ({0}, {1}, {2}), P2: ({3}, {4}, {5})", P1.x, P1.y, P1.z, P2.x, P2.y, P2.z);
   return true;
}

如果 t1 >= 0t2 >= 0,则射线实际命中。在这种情况下,交点由最小的 t 给出(但仍然 >= 0)。