计算包含轮换

时间:2015-11-18 05:43:21

标签: unity3d rotation quaternions bounds qvector3d

enter image description here

我正在为使用自定义对撞机的游戏开发碰撞系统。我使用this创建了碰撞的边界框。

我正在使用右侧和前方值创建框的框出现问题。否则它的工作正常。任何人都知道如何在计算立方体的8个点时包含正向和向前矢量。

以下是我计算积分的代码:

 public static void GetBoundsPointsNoAlloc(BoxRegion bx, Matrix4x4 colliderBox4x4,Vector3[] points, Matrix4x4 mx) {
 Transform tr = Utils.FromMatrix4x4(ref DebugCollisionTestSphere.trans,mx);

 Vector3 v3Center = bx.center;
 Vector3 v3ext = bx.GetExtents();
 Vector3 right = bx.right;
 Vector3 forw = bx.forward;

   //Quaternion qua =Quaternion.LookRotation(bx.forward,Vector3.Cross     (bx.forward, bx.right));

   //tr.TransformDirection (bx.forward);
   //tr.localRotation = qua;
   tr.forward = bx.forward;
   tr.right =   bx.right;
   //tr.rotation = qua;

 points [0] = tr.TransformPoint (new Vector3 (v3Center.x - v3ext.x, v3Center.y + v3ext.y, v3Center.z - v3ext.z));  // Front top left corner
 points [1] = tr.TransformPoint (new Vector3 (v3Center.x + v3ext.x, v3Center.y + v3ext.y, v3Center.z - v3ext.z));  // Front top right corner
 points [2] = tr.TransformPoint (new Vector3 (v3Center.x - v3ext.x, v3Center.y - v3ext.y, v3Center.z - v3ext.z));  // Front bottom left corner
 points [3] = tr.TransformPoint (new Vector3 (v3Center.x + v3ext.x, v3Center.y - v3ext.y, v3Center.z - v3ext.z));  // Front bottom right corner
 points [4] = tr.TransformPoint (new Vector3 (v3Center.x - v3ext.x, v3Center.y + v3ext.y, v3Center.z + v3ext.z));  // Back top left corner
 points [5] = tr.TransformPoint (new Vector3 (v3Center.x + v3ext.x, v3Center.y + v3ext.y, v3Center.z + v3ext.z));  // Back top right corner
 points [6] = tr.TransformPoint (new Vector3 (v3Center.x - v3ext.x, v3Center.y - v3ext.y, v3Center.z + v3ext.z));  // Back bottom left corner
 points [7] = tr.TransformPoint (new Vector3 (v3Center.x + v3ext.x, v3Center.y - v3ext.y, v3Center.z + v3ext.z));  // Back bottom right corner
 }

当我应用四元数转换

时,Box正在改变它的位置

2 个答案:

答案 0 :(得分:3)

您需要将框的方向(存储为右和前)连接到世界变换。这样的事情应该可行:

Vector3 fwd=bx.forward.normalized(), rt=br.right.normalized(), up=fwd.Cross(rt);
Quaternion qbox; qbox.SetLookRotation(fwd,up);
tr.rotation = tr.rotation*qbox;

(因为Unity非常左撇子,你可能不得不在标志和连接顺序中摆弄一下,或者在SetLookRotation中使用rt而不是fwd)

更新:在聊天讨论之后,这似乎是最终的工作版本。

Quaternion quat = Quaternion.identity; 
quat.SetLookRotation(bx.forward, Vector3.Cross(bx.forward,bx.right)); 
points[0] = mx.MultiplyPoint3x4(quat * new Vector3(-bx.width/2,+bx.height/2,-bx.depth/2)+bx.center); 
...
points[7] = mx.MultiplyPoint3x4(quat * new Vector3(+bx.width/2,-bx.height/2,+bx.depth/2)+bx.center);

答案 1 :(得分:1)

让我们根据Unity3D框架内部可用的类重新定义此问题。如果你对数学的理解得足够好,你就可以把它与你正在使用的其他课程相适应。

如果您只需要axis-aligned bounding box(或AABB),那么您可以通过各自的Renderer属性轻松地从Colliderbounds获取该内容。这是一个快速的解决方案,在许多情况下就足够了。

其他一些边界框在本地空间中表示 - 例如,Mesh在本地空间中具有bounds属性。无论出于何种原因,你有时会有一个向上,向右和向前的大小的盒子,你可能需要将那个盒子的点转换成世界空间。

让我们说我们的方框如下:

       size.x
   .+------+
 .' |    .'|
+---+--+'  | size.y      (all around some point 'center')
|   |  |   |
|  ,+--+---+
|.'    | .' size.z 
+------+'   

假设我们有一个以零为中心的单位立方体:

Vector3 center = Vector3.zero;
Vector3 size = Vector3.one;

框的范围是其大小的一半:

Vector3 extents = size * 0.5f;

这样可以轻松计算出方框周围的八个点:

Vector3[] points = new Vector3[8];
points[0] = center + new Vector3( extents.x,  extents.y,  extents.z);
points[1] = center + new Vector3( extents.x,  extents.y, -extents.z);
points[2] = center + new Vector3( extents.x, -extents.y,  extents.z);
points[3] = center + new Vector3( extents.x, -extents.y, -extents.z);
points[4] = center + new Vector3(-extents.x,  extents.y,  extents.z);
points[5] = center + new Vector3(-extents.x,  extents.y, -extents.z);
points[6] = center + new Vector3(-extents.x, -extents.y,  extents.z);
points[7] = center + new Vector3(-extents.x, -extents.y, -extents.z);

这些点仍在当地空间。我们只需要一个transform组件将它们转换为世界空间:

for (int i=0; i<8; i++) {
    points[i] = transform.TransformPoint(points[i]);
}