public static void showMat(CMatrix4x4 mat)
 {
     if (isEnable)
     {
         for (int i = 0; i < 4; i++)
         {
             Console.WriteLine("[{0},{1},{2},{3}]", mat[i, 0], mat[i, 1], mat[i, 2], mat[i, 3]);
         }
     }
 }
 /// <summary>
 /// 获取投影矩阵 dx风格, cvv为 x-1,1  y-1,1  z0,1
 /// </summary>
 /// <param name="fov">观察角,弧度</param>
 /// <param name="aspect">长宽比</param>
 /// <param name="zn">近裁z</param>
 /// <param name="zf">远裁z</param>
 /// <returns></returns>
 public static CMatrix4x4 GetProjection(float fov, float aspect, float zn, float zf)
 {
     CMatrix4x4 p = new CMatrix4x4();
     p.SetZero();
     p[0, 0] = (float)(1 / (System.Math.Tan(fov * 0.5f) * aspect));
     p[1, 1] = (float)(1 / System.Math.Tan(fov * 0.5f));
     p[2, 2] = zf / (zf - zn);
     p[2, 3] = 1f;
     p[3, 2] = (zn * zf) / (zn - zf);
     return p;
 }
        public static CMatrix4x4 GetRotateZ(float r)
        {
            CMatrix4x4 rm = new CMatrix4x4();

            rm.Identity();
            rm[0, 0] = (float)(System.Math.Cos(r));
            rm[0, 1] = (float)(-System.Math.Sin(r));
            //
            rm[1, 0] = (float)(System.Math.Sin(r));
            rm[1, 1] = (float)(System.Math.Cos(r));
            return(rm);
        }
        /// <summary>
        /// 获取投影矩阵 dx风格, cvv为 x-1,1  y-1,1  z0,1
        /// </summary>
        /// <param name="fov">观察角,弧度</param>
        /// <param name="aspect">长宽比</param>
        /// <param name="zn">近裁z</param>
        /// <param name="zf">远裁z</param>
        /// <returns></returns>
        public static CMatrix4x4 GetProjection(float fov, float aspect, float zn, float zf)
        {
            CMatrix4x4 p = new CMatrix4x4();

            p.SetZero();
            p[0, 0] = (float)(1 / (System.Math.Tan(fov * 0.5f) * aspect));
            p[1, 1] = (float)(1 / System.Math.Tan(fov * 0.5f));
            p[2, 2] = zf / (zf - zn);
            p[2, 3] = 1f;
            p[3, 2] = (zn * zf) / (zn - zf);
            return(p);
        }
        public static CMatrix4x4 GetRotateX(float r)
        {
            CMatrix4x4 rm = new CMatrix4x4();
            rm.Identity();
            rm[1, 1] = (float)(System.Math.Cos(r));
            rm[1, 2] = (float)(-System.Math.Sin(r));
            //

            rm[2, 1] = (float)(System.Math.Sin(r));
            rm[2, 2] = (float)(System.Math.Cos(r));
            return rm;
        }
 /// <summary>
 /// 矩阵乘法
 /// </summary>
 /// <param name="lhs"></param>
 /// <param name="rhs"></param>
 /// <returns></returns>
 public static CMatrix4x4 operator *(CMatrix4x4 lhs, CMatrix4x4 rhs)
 {
     CMatrix4x4 nm = new CMatrix4x4();
     nm.SetZero();
     for (int i = 0; i < 4; i++)
     {
         for (int j = 0; j < 4; j++)
         {
             for (int k = 0; k < 4; k++)
             {
                 nm._m[i, j] += lhs._m[i,k] * rhs._m[k, j];
             }
         }
     }
     return nm;
 }
        /// <summary>
        /// 矩阵乘法
        /// </summary>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static CMatrix4x4 operator *(CMatrix4x4 lhs, CMatrix4x4 rhs)
        {
            CMatrix4x4 nm = new CMatrix4x4();

            nm.SetZero();
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    for (int k = 0; k < 4; k++)
                    {
                        nm._m[i, j] += lhs._m[i, k] * rhs._m[k, j];
                    }
                }
            }
            return(nm);
        }
 /// <summary>
 /// 获取旋转矩阵
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <param name="z"></param>
 /// <param name="r"></param>
 /// <returns></returns>
 public static CMatrix4x4 GetRotate(float x, float y, float z, float r)
 {
     CMatrix4x4 rm = new CMatrix4x4();
     rm.SetZero();
     rm[0, 0] = (float)(x * x * (1 - System.Math.Cos(r)) + System.Math.Cos(r));
     rm[0, 1] = (float)(x * y * (1 - System.Math.Cos(r)) +  z * System.Math.Sin(r));
     rm[0, 2] = (float)(x * z * (1 - System.Math.Cos(r)) - y * System.Math.Sin(r));
     //
     rm[1, 0] = (float)(y * x * (1 - System.Math.Cos(r)) - z * System.Math.Sin(r));
     rm[1, 1] = (float)(y * y * (1 - System.Math.Cos(r)) + System.Math.Cos(r));
     rm[1, 2] = (float)(y * z * (1 - System.Math.Cos(r)) + z * System.Math.Sin(r));
     //
     rm[2, 0] = (float)(z * x * (1 - System.Math.Cos(r)) + z * System.Math.Sin(r));
     rm[2, 1] = (float)(z * y * (1 - System.Math.Cos(r)) - System.Math.Sin(r));
     rm[2, 2] = (float)(z * z * (1 - System.Math.Cos(r)) + z * System.Math.Cos(r));
     return new CMatrix4x4();
 }
        /// <summary>
        /// 获取旋转矩阵
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <param name="r">弧度</param>
        /// <returns></returns>
        public static CMatrix4x4 GetRotate(float x, float y, float z, float r)
        {
            CMatrix4x4 rm = new CMatrix4x4();

            rm.Identity();
            rm[0, 0] = (float)(x * x * (1 - System.Math.Cos(r)) + System.Math.Cos(r));
            rm[0, 1] = (float)(x * y * (1 - System.Math.Cos(r)) + z * System.Math.Sin(r));
            rm[0, 2] = (float)(x * z * (1 - System.Math.Cos(r)) - y * System.Math.Sin(r));
            //
            rm[1, 0] = (float)(y * x * (1 - System.Math.Cos(r)) - z * System.Math.Sin(r));
            rm[1, 1] = (float)(y * y * (1 - System.Math.Cos(r)) + System.Math.Cos(r));
            rm[1, 2] = (float)(y * z * (1 - System.Math.Cos(r)) + z * System.Math.Sin(r));
            //
            rm[2, 0] = (float)(z * x * (1 - System.Math.Cos(r)) + z * System.Math.Sin(r));
            rm[2, 1] = (float)(z * y * (1 - System.Math.Cos(r)) - System.Math.Sin(r));
            rm[2, 2] = (float)(z * z * (1 - System.Math.Cos(r)) + z * System.Math.Cos(r));
            return(rm);
        }
        /// <summary>
        /// 获取视矩阵
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="lookAt"></param>
        /// <param name="up"></param>
        /// <returns></returns>
        public static CMatrix4x4 GetView(CVector3D pos, CVector3D lookAt, CVector3D up)
        {
            //视线方向
            CVector3D dir   = lookAt - pos;
            CVector3D right = CVector3D.Cross(up, dir);

            right.Normalize();
            //平移部分
            CMatrix4x4 t = new CMatrix4x4(1, 0, 0, 0,
                                          0, 1, 0, 0,
                                          0, 0, 1, 0,
                                          -pos.x, -pos.y, -pos.z, 1);
            //旋转部分
            CMatrix4x4 r = new CMatrix4x4(right.x, up.x, dir.x, 0,
                                          right.y, up.y, dir.y, 0,
                                          right.z, up.z, dir.z, 0,
                                          0, 0, 0, 1);

            return(t * r);
        }
        public static void Test()
        {
            CVector3D a = new CVector3D(1, 2, 1,1);
            CVector3D b = new CVector3D(5, 6, 0,1);
            CVector3D c = new CVector3D(1, 2, 3, 1);

            float r1 = CVector3D.Dot(a,b);
            CVector3D r2 = a - b;
            CVector3D r3 = CVector3D.Cross(a,b);
            Console.WriteLine("a dot b:{0}", r1);
            Console.WriteLine("a - b:({0},{1},{2},{3})", r2.x, r2.y, r2.z, r2.w);
            Console.WriteLine("a X b:({0},{1},{2},{3})", r3.x, r3.y, r3.z, r3.w);
            //
            CMatrix4x4 mat1 = new CMatrix4x4(1,2,3,4,
                                            1,2,3,4,
                                            1,2,3,4,
                                            0,0,0,1);
            CMatrix4x4 mat2 = new CMatrix4x4(1, 2, 3, 4,
                                            1, 2, 3, 4,
                                            1, 2, 3, 4,
                                            1, 2, 3, 4);
            CMatrix4x4 mat3 = new CMatrix4x4();
            mat3.Identity();
            CMatrix4x4 mat4 = new CMatrix4x4(1, 0, 0, 0,
                                           0, 1, 0, 0,
                                           0, 0, 1, 0,
                                           1, 2, 3, 1);
            CMatrix4x4 matr1 = mat1 * mat3;
            Console.WriteLine("mat1 * mat3:");
            showMat(matr1);
            CMatrix4x4 matr2 = mat1 * mat2;
            Console.WriteLine("mat1 * mat2:");
            showMat(matr2);
            CVector3D r4 = a * mat1;
            Console.WriteLine("a * mat1:({0},{1},{2},{3})", r4.x, r4.y, r4.z, r4.w);

            CVector3D r5 = a * mat4;
            Console.WriteLine("a * mat4:({0},{1},{2},{3})", r5.x, r5.y, r5.z, r5.w);
        }
示例#12
0
 private void Draw(CMatrix4x4 m, CMatrix4x4 v, CMatrix4x4 p)
 {
     DrawPanel(0, 1, 2, 3, m, v, p);
     DrawPanel(4, 5, 6, 7, m, v, p);
     DrawPanel(0, 4, 5, 1, m, v, p);
     DrawPanel(1, 5, 6, 2, m, v, p);
     DrawPanel(2, 6, 7, 3, m, v, p);
     DrawPanel(3, 7, 4, 0, m, v, p);
 }
 /// <summary>
 /// 获取视矩阵
 /// </summary>
 /// <param name="pos"></param>
 /// <param name="lookAt"></param>
 /// <param name="up"></param>
 /// <returns></returns>
 public static CMatrix4x4 GetView(CVector3D pos, CVector3D lookAt, CVector3D up)
 {
     //视线方向
     CVector3D dir = lookAt - pos;
     CVector3D right = CVector3D.Cross(up, dir);
     right.Normalize();
     //平移部分
     CMatrix4x4 t = new CMatrix4x4(1,0,0,0,
                                    0,1,0,0,
                                    0,0,1,0,
                                    -pos.x, -pos.y, -pos.z, 1);
     //旋转部分
     CMatrix4x4 r= new CMatrix4x4(right.x,up.x,dir.x,0,
                                    right.y,up.y,dir.y,0,
                                    right.z,up.z,dir.z,0,
                                    0, 0, 0, 1);
     return t * r;
 }
示例#14
0
        /// <summary>
        /// 绘制平面
        /// </summary>
        /// <param name="vIndex1">顶点索引</param>
        /// <param name="vIndex2">顶点索引</param>
        /// <param name="vIndex3">顶点索引</param>
        /// <param name="vIndex4">顶点索引</param>
        /// <param name="mvp">mvp矩阵</param>
        private void DrawPanel(int vIndex1, int vIndex2, int vIndex3, int vIndex4, CMatrix4x4 m, CMatrix4x4 v, CMatrix4x4 p)
        {
            CVertex p1 = new CVertex(mesh[vIndex1]);
            CVertex p2 = new CVertex(mesh[vIndex2]);
            CVertex p3 = new CVertex(mesh[vIndex3]);
            //
            DrawTriangle(p1, p2, p3, m, v, p);
            p1 = new CVertex(mesh[vIndex1]);
            p3 = new CVertex(mesh[vIndex3]);
            CVertex p4 = new CVertex(mesh[vIndex4]);

            DrawTriangle(p3, p4, p1, m, v, p);
        }
示例#15
0
        /// <summary>
        /// 绘制三角形
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <param name="mvp"></param>
        private void DrawTriangle(CVertex p1, CVertex p2, CVertex p3, CMatrix4x4 m, CMatrix4x4 v, CMatrix4x4 p)
        {
            //--------------------几何阶段---------------------------
            //变换到齐次裁剪空
            SetMVPTransform(m, v, p, p1);
            SetMVPTransform(m, v, p, p2);
            SetMVPTransform(m, v, p, p3);

            ////裁剪
            if (Clip(p1) == false || Clip(p2) == false || Clip(p3) == false)
            {
                return;
            }
            //背面消隐
            //if (BackFaceCulling(p1, p2, p3) == false)
            //{
            //    return;
            //}
            //变换到屏幕坐标
            TransformToScreen(p1);
            VectorMatrixTestCase.showVector3(p1.point);
            TransformToScreen(p2);
            VectorMatrixTestCase.showVector3(p2.point);
            TransformToScreen(p3);
            VectorMatrixTestCase.showVector3(p3.point);

            //--------------------光栅化阶段---------------------------
            //todo test
            //_frameBuff.SetPixel((int)p1.point.x, (int)p1.point.y, System.Drawing.Color.White);
            //_frameBuff.SetPixel((int)p2.point.x, (int)p2.point.y, System.Drawing.Color.White);
            //_frameBuff.SetPixel((int)p3.point.x, (int)p3.point.y, System.Drawing.Color.White);

            TriangleRasterization(p1, p2, p3);
        }
示例#16
0
 private void timer1_Tick(object sender, EventArgs e)
 {
     lock (_frameBuff)
     {
         ClearBuff();
         CMatrix4x4 m = new CMatrix4x4();
         m.Identity();
         m[3, 2] = 5;
         rot += 0.1f;
         m = MathUntil.GetRotateY(rot) * m;
         CMatrix4x4 v = MathUntil.GetView(new CVector3D(0, 0, 0, 1), new CVector3D(0, 0, 1, 1), new CVector3D(0, 1, 0, 1));
         CMatrix4x4 p = MathUntil.GetProjection((float)System.Math.PI / 4, this.MaximumSize.Width / (float)this.MaximumSize.Height, 1f, 500f);
         //
         Draw(m, v, p);
         //
         if (g1 == null)
         {
             g1 = this.CreateGraphics();
         }
         g1.Clear(System.Drawing.Color.Black);
         g1.DrawImage(_frameBuff, 0, 0);
     }
     this.Invalidate();
 }
示例#17
0
        /// <summary>
        /// 进行mvp矩阵变换,将顶点变换到齐次裁剪空间
        /// </summary>
        private void SetMVPTransform(CMatrix4x4 m, CMatrix4x4 v, CMatrix4x4 p, CVertex vertex)
        {
            vertex.point = vertex.point * m;
            VectorMatrixTestCase.showVector3(vertex.point);
            vertex.point = vertex.point * v;
            VectorMatrixTestCase.showVector3(vertex.point);
            vertex.point = vertex.point * p;
            VectorMatrixTestCase.showVector3(vertex.point);

                //得到齐次裁剪空间的点 v.point.w 中保存着原来的z(具体是z还是-z要看使用的投影矩阵,我们使用投影矩阵是让w中保存着z)

                //onePerZ 保存1/z,方便之后对1/z关于x’、y’插值得到1/z’
            vertex.onePerZ = 1 / vertex.point.w;
                //校正的推论: s/z、t/z和x’、y’也是线性关系。而我们之前知道1/z和x’、y’是线性关系。则我们得出新的思路:对1/z关于x’、y’插值得到1/z’,然后对s/z、t/z关于x’、y’进行插值得到s’/z’、t’/z’,然后用s’/z’和t’/z’分别除以1/z’,就得到了插值s’和t’
                //这里将需要插值的信息都乘以1/z 得到 s/z和t/z等,方便光栅化阶段进行插值
            vertex.u *= vertex.onePerZ;
            vertex.v *= vertex.onePerZ;
                //
            vertex.color.r *= vertex.onePerZ;
            vertex.color.g *= vertex.onePerZ;
            vertex.color.b *= vertex.onePerZ;
        }