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();
            }
        }
    }

效果图

 

 

 

posted @ 2021-03-15 11:20  橘猫不太胖  阅读(121)  评论(0)    收藏  举报