计算机图形学(六):1. Triangle类,以及Ray Triangle的求交,画出一个红红的三角形来

接下来我们开始着手画一个三角形(and 大家不要预设心理障碍,其实挺简单的),首先我们了解图形学和三角形相关的基础知识,重点知识贴图如下:
计算机图形学(六):1. Triangle类,以及Ray Triangle的求交,画出一个红红的三角形来
计算机图形学(六):1. Triangle类,以及Ray Triangle的求交,画出一个红红的三角形来
计算机图形学(六):1. Triangle类,以及Ray Triangle的求交,画出一个红红的三角形来
其次我们定义Triangle类(三角形类),首先明晰三角形由三个点Point3D p0, p1, p2,以及法线向量normal构成。三个点给出后,法线normal可以利用公式得到。最后编写代码测试上述类定义是否正确:
Triangle类(三角形类)代码:

class Trianglecs
    {
        Point3D p0, p1, p2;
        Vector3D normal;

        internal Point3D P0 { get => p0; set => p0 = value; }
        internal Point3D P1 { get => p1; set => p1 = value; }
        internal Point3D P2 { get => p2; set => p2 = value; }
        internal Vector3D Normal { get => normal; set => normal = value; }
        //构造类一
        public Trianglecs()
        {
            p0 = new Point3D(0, 0, 0);
            p1 = new Point3D(0,0,1);
            p2 = new Point3D(1,0,0);
            normal = new Vector3D(0,1,0);
        }
        //构造类一
        public Trianglecs(Point3D a,Point3D b,Point3D c)
        {
            p0 = a;
            p1 = b;
            p2 = c;
            normal = (p1 - p0) ^ (p2 - p0);
            normal.Normlize();
        }

    }

然后调试看代码是否正确
然后在Ray类中编写bool ray.hit(Triangle tri)方法。该方法返回一条光线是否与三角形相交。
三角形的击中方法代码如下:

//编写bool ray.hit(Triangle tri)方法。该方法返回一条光线是否与三角形相交。
        public bool Hit(Trianglecs tri)
        {
            //根据pdf提供的数学公式计算
            double a = tri.P0.X - tri.P1.X;
            double b = tri.P0.X - tri.P2.X;
            double c = _direction.I;
            double d = tri.P0.X - _origin.X;
            double e = tri.P0.Y - tri.P1.Y;
            double f = tri.P0.Y - tri.P2.Y;
            double g = _direction.J;
            double h = tri.P0.Y - _origin.Y;
            double i = tri.P0.Z - tri.P1.Z;
            double j = tri.P0.Z - tri.P2.Z;
            double k = _direction.K;
            double L = tri.P0.Z - _origin.Z;


            double m = f * k - g * j;
            double n = h * k - g * L;
            double p = f * L - h * j;
            double q = g * i - e * k;
            double s = e * j - f * i;


            double inv_denom = 1.0 / (a * m + b * q + c * s);

            double el = d * m - b * n - c * p;
            double beta = el * inv_denom;

            if(beta <0.0)//根据pdf提供的三个不等式条件判断
            {
                return false;
            }
            double r = e * L - h * i;
            double e2 = a * n + d * q + c * r;
            double gamma = e2 * inv_denom;

            if(gamma <0.0)//根据pdf提供的三个不等式条件判断
            {
                return false;
            }
            if(beta +gamma>1.0)//根据pdf提供的三个不等式条件判断
            {
                return false;
            }
            double e3 = a * p - b * r + d * s;
            double t = e3 * inv_denom;
            if (t < kEpisilon)
            {
                return false;
            }
            double tim = t;//得到不知名参数t值
            Point3D hitpoint = _origin + t * _direction;//得到光线与三角形的击中点
            return true;

        }

最后以之前的代码为基础,实际的在场景中放置一个三角形,并类似渲染一个球一样,将该三角形渲染出来。其中三角形为红色,背景为灰色,或者渲染成自己喜欢的颜色。
渲染代码如下:

Point3D eye = new Point3D(0, 0, 0);//起始点
            ViewPlane viewPlane = new ViewPlane();//实例化
            viewPlane.Position = new Point3D(-2, 1, -1);//网格的左上角位置
            viewPlane.ResW = 800;
            viewPlane.ResH = 600;
            viewPlane.W = 4;
            viewPlane.H = 2;
            Sphere sphere = new Sphere(new Point3D(0,0,-2),0.5);//实例化一个球
            Ray primaryRay ;
            Trianglecs trianglecs = new Trianglecs(new Point3D(0,1,-3),new Point3D(-1,0,-3),new Point3D(1,0,-3));//实例化一个三角形
            
            for (int i=0;i<viewPlane.ResW;i++)
            {
                /*
               int R =random();
                int G = random();
                int B = random();
                Color color = Color.FromArgb(R, G, B);
                */
                for (int j = 0; j < viewPlane.ResH; j++)
                {

                    Point3D viewpoint = new Point3D(viewPlane.Position.X + i * (viewPlane.W / viewPlane.ResW), viewPlane.Position.Y - j * (viewPlane.H / viewPlane.ResH), viewPlane.Position.Z);//计算viewplane的每一个网格点
                    Vector3D primaryVector = viewpoint - eye;//计算初始向量
                    primaryRay = new Ray(eye, primaryVector);//计算初始光线
                    /*
                     *
                     //击中球渲染
                    if (primaryRay.Hit(sphere))
                    {
                        bitmap.SetPixel(i, j, Color.Red);
                    }
                    else
                    {
                        bitmap.SetPixel(i,j,Color.Gray);
                    }
                   // bitmap.SetPixel(j, i, color);//设置颜色
                    */
                    //击中三角形渲染
                    if(primaryRay.Hit(trianglecs))//如果击中则显示为红色
                    {
                        bitmap.SetPixel(i, j, Color.Red);
                    }
                    else//否则显示为灰色
                    {
                        bitmap.SetPixel(i, j, Color.Gray);
                    }
                }
            }
            picBox.BackgroundImage = bitmap;//显示图片

结果如下:
计算机图形学(六):1. Triangle类,以及Ray Triangle的求交,画出一个红红的三角形来

上一篇:算法:杨辉三角(Pascal's Triangle)


下一篇:自考新教材-p328_5(1)