计算机图形学(六):1. Triangle类,以及Ray Triangle的求交,画出一个红红的三角形来
作者:互联网
接下来我们开始着手画一个三角形(and 大家不要预设心理障碍,其实挺简单的),首先我们了解图形学和三角形相关的基础知识,重点知识贴图如下:
其次我们定义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;//显示图片
结果如下:
标签:求交,tri,Triangle,double,图形学,viewPlane,new,三角形,Point3D 来源: https://blog.csdn.net/qq_43625888/article/details/117091502