如何在 3D 空间中放置一个垂直于表面的对象?

问题描述

假设我有一个立方体或球形表面。我有一个对象,我想“坐在”这个表面上,即对象的 y 轴应该等于表面的法线。为了渲染,我使用了一个变换,它需要一个位置向量、3 个旋转角度和一个缩放向量。

之前,我试图计算标准 向量和法线之间的角度,以获得三个角度:a、b、g。然后,我尝试使用这些角度围绕 i、j 和 k 单位向量旋转对象,使其旋转至与法线相等。

这没有用,我猜是因为 arccos 的范围是 [0,180]。所以我的问题是:我需要做哪些数学运算才能将我的对象断言为表面法线?

让我还指定对象围绕法线的旋转无关紧要,我只关心对象是否垂直于表面。

对于规范:我使用的是 Java 和 OpenGL,但这更像是一个基于数学的问题,所以我认为这并不重要。

这是我正在尝试使用的当前代码

    /**
     * generates a vector of rotation to a vector
     * @param v - the vector
     * @return - a vector containing the x,y,z rotations
     */
    public static Vector3f rotationTo(Vector3f v) {

        float x = Vector3f.angleBetween(new Vector3f(0,1,0),new Vector3f(0,v.y,v.z));
        float y = Vector3f.angleBetween(new Vector3f(0,1),new Vector3f(v.x,v.z));
        float z = Vector3f.angleBetween(new Vector3f(0,0));

        return new Vector3f(x,z);
    }



    /**
     * determines the angle between two vectors in degrees
     * @param v - vector 1
     * @param u - vector 2
     * @return - the angle between
     */
    public static float angleBetween(Vector3f v,Vector3f u) {
        return (float) Math.todegrees(
            Math.acos(Vector3f.dot(v,u)
            * quickInverseSqrt(v) 
            * quickInverseSqrt(u))
        );
    }



    /**
     * quickly determines the inverse magnitude of a vector using the
     * Fast Inverse Square Root formula
     * @param v - the vector
     * @return - the magnitude
     */
    public static float quickInverseSqrt(Vector3f v) {
        float val = v.x * v.x + v.y * v.y + v.z * v.z;
        float xHalf = 0.5f * val;
        int i = Float.floatToIntBits(val);
        i = 0x5f3759df - (i >> 1);
        val = Float.intBitsToFloat(i);
        val *= (1.5f - xHalf * val * val);
        return val;
    }

解决方法

我发现的答案不是旋转 3 次不同的时间,(x,y,z) 在 (i,j,k) 上,我通过法向量与垂直分量 j 交叉来确定旋转轴,并且然后我通过使用公式 Cos(t)=v·u 找到了旋转角度。然后,我绕着这个轴旋转了一个角度,这样我就可以相应地创建一个旋转矩阵。