在C#中实现正交相机

时间:2018-03-27 17:41:07

标签: c# raytracing

我制作了一个简单的光线追踪器,现在我试图制作一个简单的正交视图来显示一个球体但是在黑色背景上没有红色圆圈我得到一个红色矩形... < / p>

在我的球类中,我有一种方法可以检查射线是否击中球体:

    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;
            }
        }
    }

正交相机类:

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");
    }
}

然后,在我的主要课程中我有:

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

我得到的是红色矩形。我在哪里弄错了?

1 个答案:

答案 0 :(得分:1)

在您的代码中,您有:

changeApi

在C#中,这是根据operator precedence rules评估的,{{3}}表示double t1 = (-B + Math.Sqrt(delta)) / 2 * A;*是乘法运算符。它还说:

  

每个部分内的运营商共享相同的优先级。

因此,/*具有相同的优先权;它们从左到右进行评估。因此,您的陈述将被评估如下:

/

但是,您实际想要解决的二次方程是:

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 >= 0,光线会实际点击。在这种情况下,交点由最小的t2 >= 0给出(但仍为t)。