从方向矢量和向上矢量创建四元数以旋转矩阵

时间:2020-11-08 13:34:43

标签: c# math directx light

如何根据圆锥方向计算旋转矩阵?我有这样定义的聚光灯: enter image description here

我正在为圆锥创建顶点数组以绘制聚光灯形状,然后创建一个缓冲区(线循环模式):

private static float[] createConeVerticesArray(float radius,
                                               float height,
                                               int segments)
{
    Array<Float> verticesArray = new Array<>();

    float angle = 2 * MathUtils.PI / segments;
    float cos = MathUtils.cos(angle);
    float sin = MathUtils.sin(angle);
    float cx = radius, cy = 0;

    for(int i = 0; i < segments; i++)
    {
        verticesArray.add(cx);
        verticesArray.add(cy);
        verticesArray.add(height);

        verticesArray.add(0f);
        verticesArray.add(0f);
        verticesArray.add(0f);

        verticesArray.add(cx);
        verticesArray.add(cy);
        verticesArray.add(height);

        float temp = cx;
        cx = cos * cx - sin * cy;
        cy = sin * temp + cos * cy;

        verticesArray.add(cx);
        verticesArray.add(cy);
        verticesArray.add(height);
    }
    verticesArray.add(cx);
    verticesArray.add(cy);
    verticesArray.add(height);

    cx = radius;
    cy = 0;
    verticesArray.add(cx);
    verticesArray.add(cy);
    verticesArray.add(height);

    float[] result = new float[verticesArray.size];
    for(int i = 0; i < verticesArray.size; i++)
    {
        result[i] = verticesArray.get(i);
    }

    return result;
}

下一步,我将创建三个这样的聚光灯,它们表示绕每个轴旋转3圈:

this.spotLights.add(new CSpotLight(
            new Color(1f, 0f, 0f, 1f), //Color
            new Vector3(0f, 0f, 5000f), //Position
            1f, //Intensity
            new Vector3(0f, 0f, -1f), //Direction
            15f, //Inner angle
            30f, //Outer angle
            4000f, //Radius
            1f)); //Attenuation
    this.spotLights.add(new CSpotLight(
            new Color(1f, 0f, 0f, 1f),
            new Vector3(0f, 5000f, 0f),
            1f,
            new Vector3(0f, -1f, 0f),
            15f,
            30f,
            4000f,
            1f));
    this.spotLights.add(new CSpotLight(
            new Color(1f, 0f, 0f, 1f),
            new Vector3(5000f, 0f, 0f),
            1f,
            new Vector3(-1f, 0f, 0f),
            15f,
            30f,
            4000f,
            1f));

然后我为每个聚光灯计算四元数以创建模型矩阵的旋转矩阵(仅用于顶点着色器):

private static Quaternion quaternionLookRotation(Vector3 direction, Vector3 up)
{
    Vector3 vector = Pools.obtain(Vector3.class).set(direction).nor();
    Vector3 vector2 = Pools.obtain(Vector3.class).set(up).crs(vector).nor();
    Vector3 vector3 = Pools.obtain(Vector3.class).set(vector).crs(vector2);

    float m00 = vector2.x;
    float m01 = vector2.y;
    float m02 = vector2.z;
    float m10 = vector3.x;
    float m11 = vector3.y;
    float m12 = vector3.z;
    float m20 = vector.x;
    float m21 = vector.y;
    float m22 = vector.z;

    Pools.free(vector);
    Pools.free(vector2);
    Pools.free(vector3);

    float num8 = (m00 + m11) + m22;
    Quaternion quaternion = Pools.obtain(Quaternion.class);
    if (num8 > 0f)
    {
        float num = (float) Math.sqrt(num8 + 1f);
        quaternion.w = num * 0.5f;
        num = 0.5f / num;
        quaternion.x = (m12 - m21) * num;
        quaternion.y = (m20 - m02) * num;
        quaternion.z = (m01 - m10) * num;
        return quaternion;
    }
    if ((m00 >= m11) && (m00 >= m22))
    {
        float num7 = (float) Math.sqrt(((1f + m00) - m11) - m22);
        float num4 = 0.5f / num7;
        quaternion.x = 0.5f * num7;
        quaternion.y = (m01 + m10) * num4;
        quaternion.z = (m02 + m20) * num4;
        quaternion.w = (m12 - m21) * num4;
        return quaternion;
    }
    if (m11 > m22)
    {
        float num6 = (float) Math.sqrt(((1f + m11) - m00) - m22);
        float num3 = 0.5f / num6;
        quaternion.x = (m10+ m01) * num3;
        quaternion.y = 0.5f * num6;
        quaternion.z = (m21 + m12) * num3;
        quaternion.w = (m20 - m02) * num3;
        return quaternion;
    }
    float num5 = (float) Math.sqrt(((1f + m22) - m00) - m11);
    float num2 = 0.5f / num5;
    quaternion.x = (m20 + m02) * num2;
    quaternion.y = (m21 + m12) * num2;
    quaternion.z = 0.5f * num5;
    quaternion.w = (m01 - m10) * num2;
    return quaternion;
}

this.rotMatrix.set(quaternionLookRotation(
                spotLight.getDirection(),
                new Vector3(0, 1, 0)));

三个之间的两个旋转完美地起作用。该问题仅出现在应该面对点(0,0,0)的第三个旋转轴上: enter image description here

1 个答案:

答案 0 :(得分:0)

这是我的最终代码,在任何情况下都可以正常工作

@value = 'Yes'

setFromCross从两个矢量的叉积和角度计算轴,如下所示:

1

希望这对某人有帮助:)