坐标系转换历程
模型坐标系 -> 世界坐标系 -> 摄像机坐标系 -> 视口(屏幕)坐标系
变换
仿射变换和线性变换
线性:旋转 缩放 镜像 切变
放射: 平移
平移
2D变换矩阵
3D变换矩阵
旋转
2D旋转矩阵
//2D 旋转private (float,float) VertexRotate(float angle ,float x,float y){float newX = (float)(x * Math.Cos(angle) - y * Math.Sin(angle));float newY = (float)(x * Math.Sin(angle) + y * Math.Cos(angle));return (newX,newY);}public void Rotate(int degree){float angle = (float)(degree / 360.0f * Math.PI);//a点float newX, newY;(newX,newY) = VertexRotate(angle, A.X, A.Y);A.X = newX;A.Y = newY;//b点(newX, newY) = VertexRotate(angle, B.X, B.Y);B.X = newX;B.Y = newY;//C点(newX, newY) = VertexRotate(angle, C.X, C.Y);C.X = newX;C.Y = newY;}
e.Graphics.TranslateTransform(200, 200);调整坐标中心到屏幕中央
3D 旋转矩阵
组合变换(平移 + 旋转)
dx dy dz是平移分量
矩阵乘积表示 组合变换比如
先旋转 再平移
可以看出左上角是旋转变换,最后一行是平移的变换
//矩阵相乘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.x = v.x * this[1,2] + v.y * this[2,2] + v.z * this[3,2] + v.w * this[4,2];newV.x = v.x * this[1,3] + v.y * this[2,3] + v.z * this[3,3] + v.w * this[4,3];newV.x = v.x * this[1,4] + v.y * this[2,4] + v.z * this[3,4] + v.w * this[4,4];return newV;}
//三角形利用矩阵乘法进行变换public void Transform(Matrix4X4 m){this.a = this.A = m.Mul(this.A);this.b = this.B = m.Mul(this.B);this.c = this.C = m.Mul(this.C);}public void Draw(Graphics g){g.DrawLines(new Pen(Color.Red,2),this.Get2DPointFArr());}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;}private PointF Get2DPointF(Vector4 v){PointF p = new PointF();p.X = (float)(v.x / v.w);p.Y = (float)(v.y / v.w);return p;}
此时只有单纯的旋转。
如果在Z方向上添加透视投影矩阵
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;
即可。
透视投影
小孔成像。利用相似三角形计算物体轮廓
透视投影矩阵
最终只有x y表达,实际的x 坐标需要 透视除法 (x / (z/d))
撤销变换
变换矩阵A * 变换矩阵A的逆矩阵