首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >捕获对象相对于另一个对象的位置和旋转

捕获对象相对于另一个对象的位置和旋转
EN

Stack Overflow用户
提问于 2017-10-03 19:47:01
回答 2查看 1.8K关注 0票数 1

我有两个一模一样的东西和两个摄像头。我想要达到的目标如下:

1)捕捉立方体A相对于相机A的位置和旋转。

2)将其转移到立方体B,以便在照相机B(我不能移动)中,Cube B看起来与A相机中的Cube A完全一样

我成功地使用以下代码进行了定位:

代码语言:javascript
运行
复制
positionDifference = CubeA.InverseTransformPoint(CameraA.transform.position);

为了把它转移到立方体B,我需要:

代码语言:javascript
运行
复制
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在局部移动,反之亦然。我怀疑本地到世界的坐标转换是一个问题,但我也认为我的旋转代码是天真的。我试着用两种方式来捕捉旋转,首先是这样的:

代码语言:javascript
运行
复制
rotationDifference = Quaternion.Inverse(CubeA.transform.rotation) * CameraA.transform.rotation;

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

第二次尝试:

代码语言:javascript
运行
复制
rotationDifference = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);

CubeB.transform.eulerAngles = rotationDifference;

这两种方法都产生了奇怪的旋转偏移。我试着使用localPosition和localEulerAngles,但没有帮助。

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

编辑:下面是这个项目的一个Dropbox 链接

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-03 20:23:13

问题是,虽然位置和旋转相互影响,但它们是分开处理的。让我们将两者结合起来,假设我们有两个摄像机和两个立方体的模型转换(用齐次矩阵表示;假设列向量)。然后,我们要找到多维数据集B TCubeB的转换,这样:

代码语言:javascript
运行
复制
TCameraA^-1 * TCubeA = TCameraB^-1 * TCubeB

请注意,TCamera是相机的模型转换,而不是视图矩阵。如果您有视图矩阵,只需忽略逆。

我们可以立即解决TCubeB

代码语言:javascript
运行
复制
TCameraB * TCameraA^-1 * TCubeA = TCubeB

我不太熟悉Unity,但似乎不能直接使用转换矩阵。让我们把变换矩阵T除以转动部分R和平移部分Tr

代码语言:javascript
运行
复制
TrCameraB * RCameraB * (TrCameraA  * RCameraA)^-1 * TrCubeA * RCubeA = TrCubeB * RCubeB
TrCameraB * RCameraB * RCameraA^-1 * TrCameraA^-1 * TrCubeA * RCubeA = TrCubeB * RCubeB

如果我们只关心旋转,那么只需做以下操作就可以计算出相应的四元数:

代码语言:javascript
运行
复制
QCameraB * QCameraA^-1 * QCubeA = QCubeB

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

代码语言:javascript
运行
复制
TrCameraB * RCameraB * RCameraA^-1 * TrCameraA^-1 * TrCubeA * RCubeA * RCubeB^-1 = TrCubeB

要找到翻译向量,只需将原点乘到左侧:

代码语言:javascript
运行
复制
TrCameraB * RCameraB * RCameraA^-1 * TrCameraA^-1 * TrCubeA * RCubeA * RCubeB^-1 * (0, 0, 0, 1)

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

代码语言:javascript
运行
复制
Vector4 translation = (0, 0, 0, 1)
translation += TrCubeA
translation -= TrCameraA
translation = RCameraA.Inverse().Transform(translation)
translation = RCameraB.Transform(translation)
translation += TrCameraB

再说一遍,我几乎不知道Unity,它可能会使用一些与我不同的约定(转换数学中的约定特别棘手)。但我相信,如果有什么不正确的地方,你可以修改上面的推导。

票数 2
EN

Stack Overflow用户

发布于 2017-10-04 10:11:07

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

代码语言:javascript
运行
复制
    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对各自的相机总是有完全相同的位置和旋转。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46552263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档