【问题标题】:Capture position and rotation of an object relative to another object捕获一个对象相对于另一个对象的位置和旋转
【发布时间】:2017-10-03 19:47:01
【问题描述】:

我有两个相同的对象和两个相机。我想要实现的目标如下:

1) 捕捉Cube A相对于Camera A的位置和旋转

2) 将其转移到立方体 B,以便在相机 B(我无法移动)中,立方体 B 看起来与立方体 A 在相机 A 中的外观完全相同

我使用以下代码成功地使用了位置:

positionDifference = CubeA.InverseTransformPoint(CameraA.transform.position);

要将它转移到立方体 B,我这样做:

cubeBpos = transform.InverseTransformPoint(CubeB.transform.localPosition);      

while ( Mathf.Abs (cubeBpos.x + positionDifference.x) > 0.01f ) {
    if (cubeBpos.x + positionDifference.x > 0) {
        CubeB.transform.position += new Vector3(-0.01f, 0, 0);
    } 
    else if (cubeBpos.x + positionDifference.x < 0) {
        CubeB.transform.position += new Vector3(+0.01f, 0, 0);  
    }
    cubeBpos = transform.InverseTransformPoint(CubeB.transform.position);
}

这很笨重,但很有效。但是,当我尝试转移旋转时,立方体 B 开始围绕原点旋转。有趣的是,当我在世界坐标中移动立方体 A 时,立方体 B 在本地移动,反之亦然。我怀疑本地到世界坐标转换是一个问题,但我也认为我的旋转代码很幼稚。我尝试以两种方式捕获旋转,首先是这样的:

rotationDifference = Quaternion.Inverse(CubeA.transform.rotation) * CameraA.transform.rotation;

CubeB.transform.rotation = Quaternion.Inverse(rotationDifference);

第二次尝试:

rotationDifference = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);

CubeB.transform.eulerAngles = rotationDifference;

这两种方法都会导致奇怪的旋转偏移。我尝试使用 localPosition 和 localEulerAngles,没有帮助。

我希望有更聪明的方法来做到这一点:)

编辑: 这是项目的 Dropbox link

【问题讨论】:

    标签: c# unity3d rotation quaternions


    【解决方案1】:

    问题是您将位置和旋转分开处理,尽管它们相互影响。让我们把两者放在一起,假设我们有两个相机和两个立方体的模型变换(表示为齐次矩阵;假设列向量)。然后,我们要找到立方体 B TCubeB 的变换,这样:

    TCameraA^-1 * TCubeA = TCameraB^-1 * TCubeB
    

    注意TCamera 是相机的模型变换,而不是视图矩阵。如果您有视图矩阵,只需将逆矩阵放在一边。

    我们可以立即解决TCubeB

    TCameraB * TCameraA^-1 * TCubeA = TCubeB
    

    我对 Unity API 不太熟悉,但您似乎不能直接使用转换矩阵。所以让我们将变换矩阵T拆分为旋转部分R和平移部分Tr

    TrCameraB * RCameraB * (TrCameraA  * RCameraA)^-1 * TrCubeA * RCubeA = TrCubeB * RCubeB
    TrCameraB * RCameraB * RCameraA^-1 * TrCameraA^-1 * TrCubeA * RCubeA = TrCubeB * RCubeB
    

    如果我们只关心旋转,我们可以通过简单地计算相应的四元数:

    QCameraB * QCameraA^-1 * QCubeA = QCubeB
    

    翻译变得有点困难。我们需要找到平移变换,这样

    TrCameraB * RCameraB * RCameraA^-1 * TrCameraA^-1 * TrCubeA * RCubeA * RCubeB^-1 = TrCubeB
    

    要找到平移向量,只需将原点乘以左侧:

    TrCameraB * RCameraB * RCameraA^-1 * TrCameraA^-1 * TrCubeA * RCubeA * RCubeB^-1 * (0, 0, 0, 1)
    

    在伪代码中,这归结为(出现的矩阵代表各自的翻译向量):

    Vector4 translation = (0, 0, 0, 1)
    translation += TrCubeA
    translation -= TrCameraA
    translation = RCameraA.Inverse().Transform(translation)
    translation = RCameraB.Transform(translation)
    translation += TrCameraB
    

    同样,我几乎不了解 Unity API,它可能使用一些与我不同的约定(转换数学中的约定特别棘手)。但我相信如果有不正确的地方,你可以调整上述推导。

    【讨论】:

    • 非常感谢尼科!我不知道如何让它适应 Unity,但我最终得到了这个,它做了我想要的:Vector3 translation = new Vector3(0,0,0);translation += cubeA.transform.position;translation -= cameraA.transform.position;translation -= cameraA.transform.position;translation = cameraA.transform.InverseTransformPoint(translation);translation = cameraB.transform.TransformPoint(translation/2);cubeB.transform.position = translation;cubeB.transform.position = translation;Quaternion rotation = Quaternion.identity;rotation = Quaternion.Inverse(cameraA.transform.rotation);@ 987654342@
    【解决方案2】:

    Nico 的出色回答解决了我的问题,但由于注释部分中的代码格式不是为此而构建的,以下是我根据 Nico 的回答为 Unity 编写的代码:

        Vector3 translation = new Vector3(0,0,0);
        translation += cubeA.transform.position;
        translation -= cameraA.transform.position;
        translation = cameraA.transform.InverseTransformPoint(translation);
        translation = cameraB.transform.TransformPoint(translation/2);
    
        cubeB.transform.position = translation;
    
        Quaternion rotation = Quaternion.identity;
        rotation = cameraB.transform.rotation * Quaternion.Inverse(cameraA.transform.rotation) * cubeA.transform.rotation;
    
        cubeB.transform.rotation = rotation;
    

    它不是一对一的,但它达到了我的期望:如果立方体 A 是静止的,而摄像机 A 围绕它移动,那么立方体 B 相对于摄像机 B 的移动方式使得立方体 A 和立方体 B 总是相对于它们各自的相机具有完全相同的位置和旋转。

    【讨论】:

    • 我认为您应该删除 translation -= cameraA.transform.position 行,因为这已经是以下逆向的一部分。也许这就是你在最后一行有translation/2 的原因?看起来正确,否则。不客气。
    猜你喜欢
    • 2023-01-15
    • 2018-03-12
    • 2016-06-13
    • 2015-11-20
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    相关资源
    最近更新 更多