您的位置:首页 > 编程语言 > C#

C#实现3D三角形 顶点转换以及投影

2016-04-15 09:47 513 查看
1.向量基本类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _3DTransform
{
class Vector4
{
public double x, y, z, w;

public Vector4() { }

public Vector4(double x, double y, double z, double w)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}

public Vector4(Vector4 v)
{
this.x = v.x;
this.y = v.y;
this.z = v.z;
this.w = v.w;
}
}
}


2.4X4阶矩阵运算类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _3DTransform
{
class matrix4X4
{
public double[,] pts;

public matrix4X4()
{
pts = new double[4, 4];
}

/// <summary>
/// 访问器便于获取矩阵中的元素
/// </summary>
/// <param name="i"></param>
/// <param name="j"></param>
/// <returns></returns>
public double this[int i, int j]
{
get
{
return pts[i - 1, j - 1];
}
set
{
pts[i - 1, j - 1] = value;
}
}

/// <summary>
/// 矩阵与矩阵相乘
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
public matrix4X4 mul(matrix4X4 m)
{
matrix4X4 newM = new matrix4X4();
for(int h = 1; h<=4; h++)
for(int l=1; l<=4;l++)
for (int i = 1; i <= 4; i++)
{
newM[h, l] += this[h, i] * m[i, l];
}

return newM;
}

/// <summary>
/// 矩阵与向量相乘
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
public Vector4 mul(Vector4 v)
{
Vector4 newV = new Vector4();
newV.x = v.x * this[1, 1] + v.y * this[2, 1] + v.z * this[3, 1] + v.w * this[4, 1];
newV.y = v.x * this[1, 2] + v.y * this[2, 2] + v.z * this[3, 2] + v.w * this[4, 2];
newV.z = v.x * this[1, 3] + v.y * this[2, 3] + v.z * this[3, 3] + v.w * this[4, 3];
newV.w = v.x * this[1, 4] + v.y * this[2, 4] + v.z * this[3, 4] + v.w * this[4, 4];

return newV;
}
}
}


3.3D三角形类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace _3DTransform
{
class Triangle3D
{
public Vector4 A, B, C;
private Vector4 a, b, c; //用来存储变换后的顶点 不影响原始顶点数据(多次变换导致原始顶点误差可能会变大)

public Triangle3D() { }

public Triangle3D(Vector4 _a, Vector4 _b, Vector4 _c)
{
A =a= _a;
B =b= _b;
C =c= _c;
}

/// <summary>
/// 三角形顶点进行顶点变换
/// 实现模型->世界->相机->投影
/// </summary>
/// <param name="m"></param>
public void Transform(matrix4X4 m)
{
a = m.mul(this.A);
b = m.mul(this.B);
c = m.mul(this.C);
}

public void Draw(Graphics g)
{
g.TranslateTransform(300, 300);
g.DrawLines(new Pen(Color.Red, 2), this.Get2DPointFArr());
}

/// <summary>
/// 投影需要取2D(x,y)向量,透视投影需要做透视除法 除以w分量
/// </summary>
/// <param name="v"></param>
/// <returns></returns>
public PointF Get2DPointFFrom(Vector4 v)
{
PointF p = new PointF();
p.X = (float)(v.x / v.w);
p.Y = (float)(v.y / v.w);

return p;
}

public PointF[] Get2DPointFArr()
{
PointF[] arr = new PointF[4];
arr[0] = Get2DPointFFrom(this.a);
arr[1] = Get2DPointFFrom(this.b);
arr[2] = Get2DPointFFrom(this.c);
arr[3] = arr[0];

return arr;
}
}
}


4.测试form代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace _3DTransform
{
public partial class Form1 : Form
{
int a;  //角度
Triangle3D t;
matrix4X4 m_scale;
matrix4X4 m_rotate;
matrix4X4 m_view;
matrix4X4 m_projection;
public Form1()
{
InitializeComponent();

///构造缩放矩阵
m_scale = new matrix4X4();
m_scale[1, 1] = 250;
m_scale[2, 2] = 250;
m_scale[3, 3] = 250;
m_scale[4, 4] = 1;

m_view = new matrix4X4();
m_view[1, 1] = 1;
m_view[2, 2] = 1;
m_view[3, 3] = 1;
m_view[4, 3] = 250;
m_view[4, 4] = 1;

m_projection = new matrix4X4();
m_projection[1, 1] = 1;
m_projection[2, 2] = 1;
m_projection[3, 3] = 1;
m_projection[3, 4] = 1.0 / 250;

}

private void Form1_Load(object sender, EventArgs e)
{
Vector4 a = new Vector4(0, -0.5, 0, 1);
Vector4 b = new Vector4(0.5, 0.5, 0, 1);
Vector4 c = new Vector4(-0.5, 0.5, 0, 1);

t = new Triangle3D(a, b, c);
t.Transform(m_scale);
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
t.Draw(e.Graphics);
}

private void timer1_Tick(object sender, EventArgs e)
{
a+=2;
double angle = a/360.0*Math.PI;
///旋转实时在这里构造
///
m_rotate = new matrix4X4();
m_rotate[1, 1] = Math.Cos(angle);
m_rotate[1, 3] = Math.Sin(angle);
m_rotate[2, 2] = 1;
m_rotate[3, 1] = -Math.Sin(angle);
m_rotate[3, 3] = Math.Cos(angle);
m_rotate[4, 4] = 1;

//t.Transform(m_scale);
//模型->世界
matrix4X4 m = m_scale.mul(m_rotate);
//世界->相机
m=m.mul(m_view);
//相机->投影
m = m.mul(m_projection);
t.Transform(m);
this.Invalidate();
}

private void trackBar1_Scroll(object sender, EventArgs e)
{
m_view[4, 3] = (sender as TrackBar).Value;
}
}
}


实现过程:构造基本的向量和矩阵类

三角形的绘制方法以及提供公有的坐标变换方法

在变换过程中依次实现 模型到世界(缩放 旋转) 世界到相机 相机到投影的变换

最后使用trackbar 测试不同z值 对投影的影响
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  旋转 投影