Unity下的ICP坐标变换

希望求得Unity场景中物体A与物体B的变换,通过ICP迭代求得。
已知:
B的局部坐标:Vector3[] vertices_model = modelObject.GetComponent<MeshFilter>().mesh.vertices;,A的局部坐标Vector3[] vertices_sample = sampleObject.GetComponent<MeshFilter>().mesh.vertices;
将两物体的局部坐标变换为世界坐标:

Matrix4x4 localToWorld_model = modelObject.transform.localToWorldMatrix;
for (int i = 0; i < vertices_model.Length; i++)
{
    Vector3 world_v = localToWorld_model.MultiplyPoint3x4(vertices_model[i]);
    Model_points[0, i] = world_v.x; Model_points[1, i] = world_v.y; Model_points[2, i] = world_v.z;
}

Matrix4x4 localToWorld_sample = sampleObject.transform.localToWorldMatrix;
for (int i = 0; i < vertices_sample.Length; i++)
{
    Vector3 world_v = localToWorld_sample.MultiplyPoint3x4(vertices_sample[i]);
    Sample_points[0, i] = world_v.x; Sample_points[1, i] = world_v.y; Sample_points[2, i] = world_v.z;
}

使用ICP算法求得A的世界坐标到B的世界坐标的变换:Rt = ICP.ICP_run(Model_points, Sample_points, threshold, max_itr, true);

整个变换过程为:
在这里插入图片描述
一:B不动,保持A的局部坐标不变,变换A的局部坐标系,使物体A变换到物体B上。

该过程的含义为,将物体A的局部坐标变换到B的世界坐标上,变换矩阵为:
在这里插入图片描述

Matrix<double> Rt_localToWorld = m.Dense(4, 4, 0);
Matrix<double> Rt_coordinate = m.Dense(4, 4, 0);//坐标系变换
Rt_localToWorld[0, 0] = localToWorld_sample[0, 0]; Rt_localToWorld[1, 0] = localToWorld_sample[1, 0]; Rt_localToWorld[2, 0] = localToWorld_sample[2, 0]; Rt_localToWorld[3, 0] = localToWorld_sample[3, 0];
Rt_localToWorld[0, 1] = localToWorld_sample[0, 1]; Rt_localToWorld[1, 1] = localToWorld_sample[1, 1]; Rt_localToWorld[2, 1] = localToWorld_sample[2, 1]; Rt_localToWorld[3, 1] = localToWorld_sample[3, 1];
Rt_localToWorld[0, 2] = localToWorld_sample[0, 2]; Rt_localToWorld[1, 2] = localToWorld_sample[1, 2]; Rt_localToWorld[2, 2] = localToWorld_sample[2, 2]; Rt_localToWorld[3, 2] = localToWorld_sample[3, 2];
Rt_localToWorld[0, 3] = localToWorld_sample[0, 3]; Rt_localToWorld[1, 3] = localToWorld_sample[1, 3]; Rt_localToWorld[2, 3] = localToWorld_sample[2, 3]; Rt_localToWorld[3, 3] = localToWorld_sample[3, 3];
//计算Sample到Model的变换矩阵
Rt = ICP.ICP_run(Model_points, Sample_points, threshold, max_itr, true);
//计算局部坐标系的变换
Rt_coordinate = Rt.Multiply(Rt_localToWorld);

Matrix4x4 transform_coordinate = Matrix4x4.identity;
transform_coordinate[0, 0] = (float)Rt_coordinate[0, 0]; transform_coordinate[1, 0] = (float)Rt_coordinate[1, 0]; transform_coordinate[2, 0] = (float)Rt_coordinate[2, 0]; transform_coordinate[3, 0] = (float)Rt_coordinate[3, 0];
transform_coordinate[0, 1] = (float)Rt_coordinate[0, 1]; transform_coordinate[1, 1] = (float)Rt_coordinate[1, 1]; transform_coordinate[2, 1] = (float)Rt_coordinate[2, 1]; transform_coordinate[3, 1] = (float)Rt_coordinate[3, 1];
transform_coordinate[0, 2] = (float)Rt_coordinate[0, 2]; transform_coordinate[1, 2] = (float)Rt_coordinate[1, 2]; transform_coordinate[2, 2] = (float)Rt_coordinate[2, 2]; transform_coordinate[3, 2] = (float)Rt_coordinate[3, 2];
transform_coordinate[0, 3] = (float)Rt_coordinate[0, 3]; transform_coordinate[1, 3] = (float)Rt_coordinate[1, 3]; transform_coordinate[2, 3] = (float)Rt_coordinate[2, 3]; transform_coordinate[3, 3] = (float)Rt_coordinate[3, 3];

//变换物体A在Unity中的坐标
sampleObject.transform.position = new Vector3(transform_coordinate[0, 3], transform_coordinate[1, 3], transform_coordinate[2, 3]);
sampleObject.transform.rotation = transform_coordinate.rotation;

二:保持A不动,使物体B变换到物体A上。

该过程的含义为将物体B的局部坐标变换到物体A的世界坐标
在这里插入图片描述
下面场景中由于得到的是物体B的世界坐标,因此只计算TICP的逆矩阵即可:

Matrix<double> Rt_Inverse = Inverse(Rt);
Matrix4x4 transform_coordinate = Matrix4x4.identity;
 transform_coordinate[0, 0] = (float)Rt_Inverse[0, 0]; transform_coordinate[1, 0] = (float)Rt_Inverse[1, 0]; transform_coordinate[2, 0] = (float)Rt_Inverse[2, 0]; transform_coordinate[3, 0] = (float)Rt_Inverse[3, 0];
transform_coordinate[0, 1] = (float)Rt_Inverse[0, 1]; transform_coordinate[1, 1] = (float)Rt_Inverse[1, 1]; transform_coordinate[2, 1] = (float)Rt_Inverse[2, 1]; transform_coordinate[3, 1] = (float)Rt_Inverse[3, 1];
transform_coordinate[0, 2] = (float)Rt_Inverse[0, 2]; transform_coordinate[1, 2] = (float)Rt_Inverse[1, 2]; transform_coordinate[2, 2] = (float)Rt_Inverse[2, 2]; transform_coordinate[3, 2] = (float)Rt_Inverse[3, 2];
transform_coordinate[0, 3] = (float)Rt_Inverse[0, 3]; transform_coordinate[1, 3] = (float)Rt_Inverse[1, 3]; transform_coordinate[2, 3] = (float)Rt_Inverse[2, 3]; transform_coordinate[3, 3] = (float)Rt_Inverse[3, 3];
        
modelObject.transform.position = new Vector3(transform_coordinate[0, 3], transform_coordinate[1, 3], transform_coordinate[2, 3]);
modelObject.transform.rotation = transform_coordinate.rotation;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值