You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Matrix4x4旋转添加相机并正确实现立方体三维旋转?

嘿,你已经靠自己实现了立方体旋转,这很棒!让我帮你解决这两个困扰你的问题:

1. 添加相机与透视效果

要实现透视,你需要引入视图矩阵(模拟相机位置和朝向)和投影矩阵(把3D空间投影到2D屏幕的透视效果),和你现有的世界旋转矩阵组合起来用。

具体步骤:

  • 创建视图矩阵:用Matrix4x4.CreateLookAt来定义相机的位置、看向的目标和向上方向。比如把相机放在Z轴正方向,看向立方体中心:
    var cameraPosition = new Vector3(0, 0, 5); // 相机在(0,0,5)位置
    var lookAtTarget = Vector3.Zero; // 看向立方体中心(原点)
    var upDirection = Vector3.Up; // Y轴为向上方向
    Matrix4x4 viewMatrix = Matrix4x4.CreateLookAt(cameraPosition, lookAtTarget, upDirection);
    
  • 创建透视投影矩阵:用Matrix4x4.CreatePerspectiveFieldOfView生成带透视效果的投影矩阵,需要传入视场角、屏幕宽高比、近远裁剪面:
    float fov = MathF.PI / 4; // 45度视场角
    float aspectRatio = (float)screenWidth / screenHeight; // 替换成你的SDL窗口宽高
    float nearPlane = 0.1f; // 近裁剪面,太近的物体不渲染
    float farPlane = 100f; // 远裁剪面,太远的物体不渲染
    Matrix4x4 projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView(fov, aspectRatio, nearPlane, farPlane);
    
  • 组合变换矩阵:因为System.Numerics.Matrix4x4是列主序矩阵,变换顺序是世界→视图→投影,所以矩阵相乘的顺序是投影 * 视图 * 世界:
    Matrix4x4 worldMatrix = Matrix4x4.Identity;
    worldMatrix *= Matrix4x4.CreateRotationX(deg);
    worldMatrix *= Matrix4x4.CreateRotationY(deg);
    worldMatrix *= Matrix4x4.CreateRotationZ(deg);
    
    // 组合三个矩阵
    Matrix4x4 combinedMatrix = Matrix4x4.Multiply(Matrix4x4.Multiply(projectionMatrix, viewMatrix), worldMatrix);
    
  • 变换顶点并转屏幕坐标:用组合矩阵变换顶点后,需要做齐次除法(把向量的x/y/z除以w分量)得到标准化设备坐标,再转成SDL屏幕坐标:
    foreach (var vertex in cubeVertices)
    {
        // 把Vector3转成Vector4(w=1.0)
        Vector4 transformed = Vector4.Transform(new Vector4(vertex, 1.0f), combinedMatrix);
        // 齐次除法
        float ndcX = transformed.X / transformed.W;
        float ndcY = transformed.Y / transformed.W;
        // 转屏幕坐标(SDL的Y轴向下,所以要翻转)
        int screenX = (int)((ndcX + 1) * screenWidth / 2);
        int screenY = (int)((1 - ndcY) * screenHeight / 2);
        // 用screenX和screenY绘制顶点/连线
    }
    
2. 修复CreateFromAxisAngle的拉伸变形问题

问题出在你传入的轴向量没有归一化!CreateFromAxisAngle要求轴向量是单位长度向量(长度为1),如果向量长度不是1,生成的矩阵会隐含缩放因子,导致立方体拉伸变形。

解决方法:

先把轴向量归一化,再传入方法:

// 先归一化轴向量
Vector3 axis = Vector3.Normalize(new Vector3(2, 2, 2));
// 再创建旋转矩阵
matrix *= Matrix4x4.CreateFromAxisAngle(axis, (float)rad);

Vector3.Normalize会把向量缩放到长度为1,这样生成的矩阵就只会做纯旋转,不会引入缩放,立方体就不会变形了。


内容的提问来源于stack exchange,提问作者CodeOrElse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:27:31