winfrom绘制旋转立方体
四阶矩阵类
class Matrix4x4 { private double[,] pts; public Matrix4x4() { pts = new double[4, 4]; } public double this[int i,int j] { get { return pts[i-1, j-1]; } set { pts[i - 1, j - 1] = value; } } public Matrix4x4 Mul(Matrix4x4 m) { Matrix4x4 newM = new Matrix4x4(); for(int w = 1; w <= 4; w++) { for(int h = 1; h <= 4; h++) { for(int n = 1; n <= 4; n++) { newM[w, h] += this[w, n] * m[n, h]; } } } return newM; } 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; } public Matrix4x4 Transpose() { Matrix4x4 t = new Matrix4x4(); for(int i = 1; i <= 4; i++) { for(int j = 1; j <= 4; j++) { t[i, j] = this[j, i]; } } return t; } }
4维向量类
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; } public static Vector4 operator -(Vector4 a,Vector4 b) { return new Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); } public Vector4 Cross(Vector4 v) { return new Vector4(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x ,0); } public float Dot(Vector4 v) { return (float)(this.x * v.x + this.y * v.y + this.z * v.z); } public Vector4 Normalized { get { double Mod = Math.Sqrt(x * x + y * y + z * z + w * w); return new Vector4(x / Mod, y / Mod, z / Mod, w / Mod); } } }
三角形类
class Triangle3D { public Vector4 A, B, C; public Vector4 a, b, c; public float dot; private bool cullBack = false; public int cr = 255, cg = 70, cb = 30; public Triangle3D() { } public Triangle3D(Vector4 a, Vector4 b, Vector4 c) { this.A = this.a = new Vector4(a); this.B = this.b = new Vector4(b); this.C = this.c = new Vector4(c); } public Triangle3D(Vector4 a,Vector4 b,Vector4 c,Color color) { this.A = this.a = new Vector4(a); this.B = this.b = new Vector4(b); this.C = this.c = new Vector4(c); cr = color.R; cg = color.G; cb = color.B; } public void Transform(Matrix4x4 m) { this.a = m.Mul(this.A); this.b = m.Mul(this.B); this.c = m.Mul(this.C); } public void CaculateLighting(Matrix4x4 _Object2World,Vector4 L) { this.Transform(_Object2World); Vector4 U = this.b - this.a; Vector4 V = this.c - this.a; Vector4 normal = U.Cross(V); dot = normal.Normalized.Dot(L.Normalized); dot = Math.Max(0, dot); Vector4 E = new Vector4(0, 0, -1, 0); cullBack = normal.Normalized.Dot(E) < 0 ? true : false; } public void Draw(Graphics g,bool drawLine) { //g.TranslateTransform(300, 300); PointF[] current = this.Get2DPointFArr(); if (drawLine) { g.DrawLines(new Pen(Color.Red, 2), current); } else { if (!cullBack) { GraphicsPath path = new GraphicsPath(); path.AddLines(current); int tcr = (int)(cr * 2 / 3 * dot) + cr / 3; int tcg = (int)(cg * 2 / 3 * dot) + cg / 3; int tcb = (int)(cb * 2 / 3 * dot) + cb / 3; Color color = Color.FromArgb(tcr, tcg, tcb); Brush br = new SolidBrush(color); g.FillPath(br, path); } } } private PointF[] Get2DPointFArr() { PointF[] arr = new PointF[4]; arr[0] = Get2DPointF(this.a); arr[1] = Get2DPointF(this.b); arr[2] = Get2DPointF(this.c); arr[3] = arr[0]; return arr; } public PointF Get2DPointF(Vector4 v) { PointF p = new PointF(); p.X = (float)(v.x / v.w); p.Y = -(float)(v.y / v.w); return p; } }
立方体类
class Cube { Vector4 a = new Vector4(-0.5, 0.5, 0.5, 1); Vector4 b = new Vector4(0.5, 0.5, 0.5, 1); Vector4 c = new Vector4(0.5, 0.5, -0.5, 1); Vector4 d = new Vector4(-0.5, 0.5, -0.5, 1); Vector4 e = new Vector4(-0.5, -0.5, 0.5, 1); Vector4 f = new Vector4(0.5, -0.5, 0.5, 1); Vector4 g = new Vector4(0.5, -0.5, -0.5, 1); Vector4 h = new Vector4(-0.5, -0.5, -0.5, 1); private Triangle3D[] triangles = new Triangle3D[12]; public Cube() { triangles[0] = new Triangle3D(a, b, c, Color.FromArgb(255, 60, 30)); triangles[1] = new Triangle3D(a, c, d, Color.FromArgb(255, 60, 30)); triangles[2] = new Triangle3D(e, h, f, Color.FromArgb(60, 255, 10)); triangles[3] = new Triangle3D(f, h, g, Color.FromArgb(60, 255, 10)); triangles[4] = new Triangle3D(d, c, g, Color.FromArgb(10, 30, 255)); triangles[5] = new Triangle3D(d, g, h, Color.FromArgb(10, 30, 255)); triangles[6] = new Triangle3D(a, e, b , Color.FromArgb(100, 100, 100)); triangles[7] = new Triangle3D(b, e, f , Color.FromArgb(100, 100, 100)); triangles[8] = new Triangle3D(b, f, c , Color.FromArgb(60, 150, 60)); triangles[9] = new Triangle3D(c, f, g , Color.FromArgb(60, 150, 60)); triangles[10] = new Triangle3D(a, d, h, Color.FromArgb(200, 200, 200)); triangles[11] = new Triangle3D(a, h, e, Color.FromArgb(200, 200, 200)); } public void Transform(Matrix4x4 m) { foreach(Triangle3D t in triangles) { t.Transform(m); } } public void CalculateLighting(Matrix4x4 _Object2World, Vector4 L) { //new Thread(() => //{ // foreach (Triangle3D t in triangles) // { // t.CaculateLighting(_Object2World, L); // } //}).Start(); foreach (Triangle3D t in triangles) { t.CaculateLighting(_Object2World, L); } } public void Draw(System.Drawing.Graphics g,bool drawLine) { g.TranslateTransform(300, 300); foreach (Triangle3D t in triangles) { t.Draw(g,drawLine); } } }
主窗体类
public partial class Form1 : Form { int a = 0; Triangle3D t; Matrix4x4 m_scale; Matrix4x4 m_rotationY; Matrix4x4 m_rotationX; Matrix4x4 m_rotationZ; Matrix4x4 m_view; Matrix4x4 m_projection; Cube cube; 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; m_rotationY = new Matrix4x4(); m_rotationX = new Matrix4x4(); m_rotationZ = new Matrix4x4(); cube = new Cube(); } 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); timer1.Start(); } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED return cp; } } private void Form1_Paint(object sender, PaintEventArgs e) { //t.Draw(e.Graphics);//绘制三角形 cube.Draw(e.Graphics,checkBox4.Checked);//绘制立方体 } private void Timer1_Tick(object sender, EventArgs e) { a += 2; double angle = a / 360.0 * Math.PI; //=============X m_rotationX[1, 1] = 1; m_rotationX[2, 2] = Math.Cos(angle); m_rotationX[2, 3] = Math.Sin(angle); m_rotationX[3, 2] = -Math.Sin(angle); m_rotationX[3, 3] = Math.Cos(angle); m_rotationX[4, 4] = 1; //=============Y m_rotationY[1, 1] = Math.Cos(angle); m_rotationY[1, 3] = Math.Sin(angle); m_rotationY[2, 2] = 1; m_rotationY[3, 1] = -Math.Sin(angle); m_rotationY[3, 3] = Math.Cos(angle); m_rotationY[4, 4] = 1; //=============Z m_rotationZ[1, 1] = Math.Cos(angle); m_rotationZ[1, 2] = Math.Sin(angle); m_rotationZ[2, 1] = -Math.Sin(angle); m_rotationZ[2, 2] = Math.Cos(angle); m_rotationZ[3, 3] = 1; m_rotationZ[4, 4] = 1; //============ if (this.checkBox1.Checked) { Matrix4x4 tx = m_rotationX.Transpose(); m_rotationX = m_rotationX.Mul(tx); } if (this.checkBox2.Checked) { Matrix4x4 tx = m_rotationY.Transpose(); m_rotationY = m_rotationY.Mul(tx); } if (this.checkBox3.Checked) { Matrix4x4 tx = m_rotationZ.Transpose(); m_rotationZ = m_rotationZ.Mul(tx); } Matrix4x4 mall = m_rotationX.Mul(m_rotationY.Mul(m_rotationZ)); Matrix4x4 m = m_scale.Mul(mall); //t.CaculateLighting(m,new Vector4(-1,1,-1,0)); cube.CalculateLighting(m, new Vector4(-1, 1, -1, 0)); Matrix4x4 mv = m.Mul(m_view); Matrix4x4 mvp = mv.Mul(m_projection); //t.Transform(mvp);//绘制三角形 cube.Transform(mvp);//绘制立方体 this.Invalidate(); } private void TrackBar1_Scroll(object sender, EventArgs e) { m_view[4, 3] = (sender as TrackBar).Value; //m_projection[3, 4] = 1.0 / trackBar1.Value; } private void checkBox5_CheckedChanged(object sender, EventArgs e) { if (checkBox5.Checked) { timer1.Stop(); } else { timer1.Start(); } } }
效果图


浙公网安备 33010602011771号