3

enter image description here

I am working on collision system for my game that uses custom colliders. I used this to create bounding box for collisions.

I am getting problem for the boxes where right and forward values have been used to create box. Otherwise its working fine. Anybody has any idea how to include right and forward vectors in calculating 8 points for the cube.

Below is my code for calculating points:

 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 is changing its position when i apply quaternion to transform

bhupinder
  • 315
  • 1
  • 6
  • 23

2 Answers2

3

You'd need to concatenate the box's orientation (stored as Right and Forward) to the world transform. Something like this should probably work:

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

(since Unity is annoyingly left-handed, you might have to fiddle with signs and the concatenation order a bit, or perhaps use rt instead of fwd in SetLookRotation)

Update: following a discussion in chat, this seems to be the final working version.

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);
Anton Knyazyev
  • 464
  • 4
  • 7
  • hi , I implemented this solution but still there are some box regions which are not getting positioned properly upon applying rotation . Please find attached image , in the image yellow box is rotated but 8 corner points have different positions https://www.dropbox.com/s/ezojb9vdd17nqq2/Screen%20Shot%202015-11-30%20at%204.33.56%20pm.png?dl=0 – bhupinder Nov 30 '15 at 11:08
  • try flipping the concatenation, i.e. tr.rotation = qbox*tr.rotation – Anton Knyazyev Nov 30 '15 at 12:45
  • hmm ok, truth be told, I never used unity myself, but I worked with box transformations and I get the problem you have. There seem to be reports that SetLookRotation is bugged http://forum.unity3d.com/threads/how-to-set-object-rotation-from-2-vectors.167555/ – Anton Knyazyev Nov 30 '15 at 13:20
  • if you have all 3 vectors, you can also build a rotation matrix from them by just setting them as columns (or rows, not sure about how it works in unity). seems to be that col 0=x=right, 1=y=up, 2=z=forward. and the last column should be 'identity' (0,0,0,1) then this matrix should be concatenated with the global matrix – Anton Knyazyev Nov 30 '15 at 13:26
  • Matrix multiplication making things worse, now corners and gameobjects has log distance between their positions. – bhupinder Nov 30 '15 at 15:04
  • hey just had a chance to look at the screenshot (dropbox is blocked at work), and it looks like the orientation is actually correct. i think the offset happens because the box's center shouldn't be transformed by the box's right-forward matrix. i.e. the order of transforms should be (+- size/2 relative to 0),,(rotate by the right-forward quat)..(add center)..(transform by the global matrix). – Anton Knyazyev Nov 30 '15 at 19:37
  • hi I didn't get this point clearly " (+- size/2 relative to 0),,(rotate by the right-forward quat)..(add center).." In which i have to 'add center', i cannot add it in to quat. could you please elaborate it. – bhupinder Dec 01 '15 at 08:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/96660/discussion-between-anton-knyazyev-and-bhupinder). – Anton Knyazyev Dec 01 '15 at 10:28
2

Let's redefine this problem in terms of classes that are available natively within Unity3D's framework. If you understand the math well enough, you can take that and adapt it to these other classes that you're using.

If all you need is an axis-aligned bounding box (or AABB), then you can easily get that from any Renderer or Collider through their respective bounds properties. That's a quick solution that will suffice in many cases.

Some other bounding boxes are expressed in local space -- for example, a Mesh has a bounds property that's in local space. For whatever reason, you will sometimes have a box that is some size up, right, and forward, and you may need to transform the points of that box into world space.

Let's say our box looks like this:

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

Suppose we have a unit cube centered at zero:

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

The box's extents are half of its size:

Vector3 extents = size * 0.5f;

That makes it easy enough to calculate the eight points around the box:

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);

These points are all in local space, still. We just need a transform component to convert them into world space:

for (int i=0; i<8; i++) {
    points[i] = transform.TransformPoint(points[i]);
}
rutter
  • 11,242
  • 1
  • 30
  • 46
  • hi @rutter , My box is custom, i cannot get it from Renderer or collider. My basic requirement is to include right and forward vectors as shown in the image into calculation of 8 points. – bhupinder Nov 18 '15 at 06:50
  • I can't provide an answer using your `BoxRegion` class because you haven't described it in any detail. As I said: if you understand the math well enough, you can take that and adapt it to these other classes that you're using. – rutter Nov 18 '15 at 07:09
  • here is the link for the box region class https://www.dropbox.com/s/36fret8cp0o1lz2/Region.cs?dl=0 I have been trying to achieve for past 2 days and tried may things not getting it right.. – bhupinder Nov 18 '15 at 07:15