public static void Test() { Vector3D a = new Vector3D(1, 2, 1,1); Vector3D b = new Vector3D(5, 6, 0,1); Vector3D c = new Vector3D(1, 2, 3, 1); float r1 = Vector3D.Dot(a,b); Vector3D r2 = a - b; Vector3D r3 = Vector3D.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); // Matrix4x4 mat1 = new Matrix4x4(1,2,3,4, 1,2,3,4, 1,2,3,4, 0,0,0,1); Matrix4x4 mat2 = new Matrix4x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4); Matrix4x4 mat3 = new Matrix4x4(); mat3.Identity(); Matrix4x4 mat4 = new Matrix4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1); Matrix4x4 mat5 = new Matrix4x4(1, 2, 3, 4, 4, 3, 2, 1, 0, -1, 2, 0, 1, 6, 4, -2); Console.WriteLine("mat5 Determinate:" + mat5.Determinate()); Console.WriteLine("mat5 GetAdjoint:"); showMat(mat5.GetAdjoint()); Console.WriteLine("mat5 Inverse:" ); showMat(mat5.Inverse()); Console.WriteLine("mat5 * mat5 Inverse:"); showMat(mat5 * mat5.Inverse()); Console.WriteLine("mat2 Transpose:"); showMat(mat2.Transpose()); Matrix4x4 matr1 = mat1 * mat3; Console.WriteLine("mat1 * mat3:"); showMat(matr1); Matrix4x4 matr2 = mat1 * mat2; Console.WriteLine("mat1 * mat2:"); showMat(matr2); Vector3D r4 = a * mat1; Console.WriteLine("a * mat1:({0},{1},{2},{3})", r4.x, r4.y, r4.z, r4.w); Vector3D r5 = a * mat4; Console.WriteLine("a * mat4:({0},{1},{2},{3})", r5.x, r5.y, r5.z, r5.w); }
public static void showMat(Matrix4x4 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> /// 矩阵乘法 /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> /// <returns></returns> public static Matrix4x4 operator *(Matrix4x4 lhs, Matrix4x4 rhs) { Matrix4x4 nm = new Matrix4x4(); 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="p"></param> /// <param name="vertex"></param> private void SetProjectionTransform(Matrix4x4 p,ref Vertex vertex) { vertex.point = vertex.point * p; //得到齐次裁剪空间的点 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.vcolor *= vertex.onePerZ; // vertex.lightingColor *= vertex.onePerZ; }
/// <summary> /// 进行mv矩阵变换,从本地模型空间到世界空间,再到相机空间 /// </summary> private void SetMVTransform(Matrix4x4 m, Matrix4x4 v,ref Vertex vertex) { vertex.point = vertex.point * m * v; }
/// <summary> /// 实现了“基础光照模型”,在世界空间进行顶点光照处理 /// </summary> /// <param name="v"></param> private void Lighting(Matrix4x4 m, Vector3D worldEyePositon ,ref Vertex v) { Vector3D worldPoint = v.point * m;//世界空间顶点位置 Vector3D normal = v.normal * m.Inverse().Transpose();//模型空间法线乘以世界矩阵的逆转置得到世界空间法线 normal = normal.Normalize(); SoftRenderer.RenderData.Color emissiveColor = _mesh.material.emissive;//自发光 SoftRenderer.RenderData.Color ambientColor = _ambientColor * _mesh.material.ka;//环境光 Vector3D inLightDir = (_light.worldPosition - worldPoint).Normalize(); float diffuse = Vector3D.Dot(normal, inLightDir); if(diffuse < 0) { diffuse = 0; } SoftRenderer.RenderData.Color diffuseColor = _mesh.material.diffuse * diffuse * _light.lightColor;//漫反射 // Vector3D inViewDir = (worldEyePositon - worldPoint).Normalize(); Vector3D h = (inViewDir + inLightDir).Normalize(); float specular = 0; if(diffuse != 0) {//防止出现光源在物体背面产生高光的情况 specular = (float)System.Math.Pow(MathUntil.Range(Vector3D.Dot(h, normal), 0, 1), _mesh.material.shininess); } SoftRenderer.RenderData.Color specularColor = _mesh.material.specular * specular * _light.lightColor;//镜面高光 // v.lightingColor = emissiveColor + ambientColor + diffuseColor + specularColor; }
/// <summary> /// 绘制三角形 /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> /// <param name="p3"></param> /// <param name="mvp"></param> private void DrawTriangle(Vertex p1, Vertex p2, Vertex p3, Matrix4x4 m, Matrix4x4 v, Matrix4x4 p) { //--------------------几何阶段--------------------------- if (_lightMode == LightMode.On) {//进行顶点光照 Lighting(m, _camera.pos, ref p1); Lighting(m, _camera.pos, ref p2); Lighting(m, _camera.pos, ref p3); } //变换到相机空间 SetMVTransform(m, v,ref p1); SetMVTransform(m, v, ref p2); SetMVTransform(m, v, ref p3); //在相机空间进行背面消隐 if (BackFaceCulling(p1, p2, p3) == false) { return; } //变换到齐次剪裁空间 SetProjectionTransform(p, ref p1); SetProjectionTransform(p, ref p2); SetProjectionTransform(p, ref p3); //裁剪 if (Clip(p1) == false || Clip(p2) == false || Clip(p3) == false) { return; } //变换到屏幕坐标 TransformToScreen(ref p1); TransformToScreen(ref p2); TransformToScreen(ref p3); //--------------------光栅化阶段--------------------------- if(_currentMode == RenderMode.Wireframe) {//线框模式 BresenhamDrawLine(p1, p2); BresenhamDrawLine(p2, p3); BresenhamDrawLine(p3, p1); } else { TriangleRasterization(p1, p2, p3); } }
private void Draw(Matrix4x4 m, Matrix4x4 v, Matrix4x4 p) { _showTrisCount = 0; for (int i = 0; i + 2 < _mesh.vertices.Length; i += 3) { DrawTriangle(_mesh.vertices[i], _mesh.vertices[i + 1], _mesh.vertices[i + 2], m, v, p); } Console.WriteLine("显示的三角形数:"+ _showTrisCount); }
/// <summary> /// 获取当前矩阵的伴随矩阵 /// </summary> /// <returns></returns> public Matrix4x4 GetAdjoint() { int x,y; float[,] tempM = new float[3,3]; Matrix4x4 result = new Matrix4x4(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 3; k++) { for (int t = 0; t < 3; ++t) { x = k >= i ? k + 1 : k; y = t >= j ? t + 1 : t; tempM[k,t] = _m[x,y]; } } result._m[i, j] = (float)System.Math.Pow(-1, (1 + j) + (1 + i)) * Determinate(tempM, 3); } } return result.Transpose(); }