C#实现3D三角形 顶点转换以及投影
2016-04-15 09:47
513 查看
1.向量基本类
2.4X4阶矩阵运算类
3.3D三角形类
4.测试form代码:
实现过程:构造基本的向量和矩阵类
三角形的绘制方法以及提供公有的坐标变换方法
在变换过程中依次实现 模型到世界(缩放 旋转) 世界到相机 相机到投影的变换
最后使用trackbar 测试不同z值 对投影的影响
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值 对投影的影响
相关文章推荐
- C#实现字体旋转的方法
- 基于jQuery实现的旋转彩圈实例
- C++实现一维向量旋转算法
- 使用JavaScript实现旋转的彩圈特效
- jQuery平滑旋转幻灯片特效代码分享
- jquery实现可旋转可拖拽的文字效果代码
- jQuery+CSS3实现3D立方体旋转效果
- C#中图片旋转和翻转(RotateFlipType)用法分析
- Android Tween动画之RotateAnimation实现图片不停旋转效果实例介绍
- Swift中实现点击、双击、捏、旋转、拖动、划动、长按手势的类和方法介绍
- Javascript实现可旋转的圆圈实例代码
- Android编程实现3D滑动旋转效果的方法
- 基于Android 实现图片平移、缩放、旋转同时进行
- Android UI之ImageView实现图片旋转和缩放
- Android编程实现3D旋转效果实例
- Android实现屏幕旋转方法总结
- Android使用RotateImageView 旋转ImageView
- JS实现3D图片旋转展示效果代码
- 详解通过HTML5 Canvas实现图片的平移及旋转变化的方法
- 实例讲解利用HTML5 Canvas API操作图形旋转的方法