使用四元数旋转立方体面向原点

问题描述 投票:1回答:1

我正在为一款游戏建立一个相对简单的基于voxel的世界。高层次的想法是,首先按照斐波那契网格生成体素位置,然后旋转立方体,使斐波那契网格的外表面像一个球体,最后确定立方体的大小,使它们大致覆盖球体的表面(重叠即可)。请看下面沿斐波那契网格生成伏笔的代码。

    public static Voxel[] CreateInitialVoxels(int numberOfPoints, int radius)
    {
        float goldenRatio = (1 + Mathf.Sqrt(5)) / 2;
        Voxel[] voxels = new Voxel[numberOfPoints];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float n = i - numberOfPoints / 2;  // Center at zero
            float theta = 2 * Mathf.PI * n / goldenRatio;
            float phi = (Mathf.PI / 2) + Mathf.Asin(2 * n / numberOfPoints);
            voxels[i] = new Voxel(new Location(theta, phi, radius));
        }
        return voxels;
    }

这将生成一个看起来像楼梯的球体。

enter image description here

所以,我目前的方法是让这个看起来更球形一些,基本上是在每一对轴上旋转每个立方体,然后组合所有的旋转。

private void DrawVoxel(Voxel voxel, GameObject voxelContainer)
{
    GameObject voxelObject = Instantiate<GameObject>(GetVoxelPrefab());

    voxelObject.transform.position = voxel.location.cartesianCoordinates;
    voxelObject.transform.parent = voxelContainer.transform;

    Vector3 norm = voxel.location.cartesianCoordinates.normalized;

    float xyRotationDegree = Mathf.Atan(norm.y / norm.x) * (180 / Mathf.PI);
    float zxRotationDegree = Mathf.Atan(norm.z / norm.x) * (180 / Mathf.PI);
    float yzRotationDegree = Mathf.Atan(norm.z / norm.y) * (180 / Mathf.PI);

    Quaternion xyRotation = Quaternion.AngleAxis(xyRotationDegree, new Vector3(0, 0, 1));
    Quaternion zxRotation = Quaternion.AngleAxis(zxRotationDegree, new Vector3(0, 1, 0));
    Quaternion yzRotation = Quaternion.AngleAxis(yzRotationDegree, new Vector3(1, 0, 0));

    voxelObject.transform.rotation = zxRotation * yzRotation * xyRotation;
}

最主要的是,我发现这些旋转中的每一个似乎都能单独工作,但当把它们结合起来时,事情就会变得有点混乱(如下图),我不确定到底是什么问题。我最好的猜测是,我在我的旋转中做了一些符号旋转的不匹配,所以他们没有正确的结合。我可以让两个工作,但从来没有三个一起。

Success in One AxisView From third axis when two rotations have been successfully appliedStandard Failure Mode when attempting to combine third rotation

上面是一个和两个成功旋转的图片,然后是当我试图结合它们时的错误模式。任何帮助,无论是告诉我我所遵循的方法太过曲折,还是帮助我理解什么是正确的组合这些旋转的方法,都将是非常有用的。下面是笛卡尔坐标转换,供参考。

[System.Serializable]
public struct Location
{
    public float theta, phi, r;
    public Vector3 polarCoordinates;

    public float x, y, z;
    public Vector3 cartesianCoordinates;

    public Location(float theta, float phi, float r)
    {
        this.theta = theta;
        this.phi = phi;
        this.r= r;
        this.polarCoordinates = new Vector3(theta, phi, r);

        this.x = r * Mathf.Sin(phi) * Mathf.Cos(theta);
        this.y = r * Mathf.Sin(phi) * Mathf.Sin(theta);
        this.z = r * Mathf.Cos(phi);
        this.cartesianCoordinates = new Vector3(x, y, z);
    }
}
c# unity3d rotation quaternions
1个回答
0
投票

我设法找到了解决这个问题的方法,不过我还是不清楚上述代码的问题在哪里。

Unity有一个非常方便的函数,叫做 Quaternion.FromToRotation 只要输入适当的目标向量,就会产生适当的旋转。

在我的例子中,我可以只做。voxelObject.transform.rotation = Quaternion.FromToRotation(new Vector3(0, 0, 1), voxel.location.cartesianCoordinates);

© www.soinside.com 2019 - 2024. All rights reserved.