Search code examples
mathrotationtrigonometryquaternionsbounding-box

3D bounding box for an item with three axis rotations


I'm trying to find the <x,y,z> size of what would end up being a bounding box for a rotated shape in all three axis rotations. Though to help keep it simple, the example demonstrated below has only the x axis rotated.

vector Size = <10,1,0.5>; vector Deg = <22.5,0,0>
if(Deg.x > 0 && Deg.y == 0 && Deg.z == 0){
  Y1 = Cos(Deg.x) * Size.y + Sin(Deg.x) * Size.z;
  Z1 = Cos(Deg.x) * Size.z + Sin(Deg.x) * Size.y;}

Below are for the y and z rotations, that is if you decided to change the degrees to say <0,22.5,0> and <0,0,22.5>.

if(Deg.y > 0 && Deg.x == 0 && Deg.z == 0){
  X2 = Cos(Deg.y) * Size.x + Sin(Deg.y) * Size.z;
  Z2 = Cos(Deg.y) * Size.z + Sin(Deg.y) * Size.x;}
if(Deg.z > 0 && Deg.x == 0 && Deg.y == 0){
  X3 = Cos(Deg.z) * Size.x + Sin(Deg.z) * Size.y;
  Y3 = Cos(Deg.z) * Size.y + Sin(Deg.z) * Size.x;}

Though the part I get lost at is, where do I go from here if when you have the rotation in two or three axis. Such as <22.5,22.5,0> or <22.5,22.5.22.5>

Is there a website with a tutorial or example equations I could review or are there any hints or ideas of what I could do to figure this out.

EDIT:

I do want to add that the comment from Nico helped, in that what I'm asking about is called: Axis-Aligned Bounding Box or AABB for short.

As for JohanC comment about the 22.5, yes the Deg = Degree. Also yes you'll have to turn the Degree into Radians, but I put it as Degree in the example for the Sin and Cos input to keep it simple.

If you're wondering how this question might be useful. Well as an example you'd need to know the AABB to help in an equation to keep the item in question flush with the surface its sitting on if you were to say resize the item while it had <x,y,z> rotations that weren't at perfect zero rotations.


Solution

  • I found my own solution after a lot of testing and debugging. I'll show and explain a small portion of the script I created since functions and options from coding language to language may vary.

    A few details about the example script below. Deg = Degrees. Though yes what JohanC mentioned about radians is correct, since even the language I'm using I have to convert degrees to radians with a function. Not every language or calculator is like that, yet for intents and purposes to make it easier to read, I did take out the excess while keeping the meat of the code/equation intact so to speak. Also in this example, I'm rotating it in the Z axis to demonstrate and as a starting point.

    vector Size = <10,1,0.5>; //Insert your own coding language function
    //for splitting the size in half with positive and negative halves.
    vector min = <-5,-0.5,-0.25>; vector max = <5,0.5,0.25>;
    //You'll need at least 8 points in total to do this correctly.
    //I already have 8 points added down below, labeled p1 - p8
    vector p1 = <max.x,max.y,max.z>; vector p2 = <max.x,min.y,max.z>;
    vector p3 = <max.x,max.y,min.z>; vector p4 = <max.x,min.y,min.z>;
    vector p5 = <min.x,max.y,max.z>; vector p6 = <min.x,min.y,max.z>;
    vector p7 = <min.x,max.y,min.z>; vector p8 = <min.x,min.y,min.z>;
    vector Deg = <0,0,22.5>
    //This will give you an idea of how to setup the x,y,z for each point
    //equation to make / change to fit the rotations. Plus to make it compact
    //I suggest that you use list, a while loop, and etc.
    x1 = p1.x * llCos(Deg.z) - p1.y * llSin(Deg.z);
    y1 = p1.y * llCos(Deg.z) + p1.x * llSin(Deg.z);
    

    A lot of what I kept out of the example above is several list, true and false statements, a while loop, and few other things. Though it's kept simple to show the less complicated portion of it and the fact that not every language has the same functions available.

    Though once when you get all of the location data of the 8 points collected, you can then put each of the x, y, z point information into its own list. Then run the equation (edited as needed for each rotation). After that, get the max and min from each axis rotation output. Then take the maximum and minus the minimum from it since the minimum will always be a negative. That right there will give you the <x,y,z> size of your bounding box.

    I do want to add that the link from Nico helped slightly, though the only flaw in it is "if" the language you're using allows a matrix or "if" you're able to create a multidimensional array. If you can manage that, then use the link Nico gave to see if it helps.

    Also some of JohanC tips/hints helped as well. Speaking of which, the part about "using the output of the vector from one rotation to the next" works well if and only if you're using the 8 points method. Otherwise if you try it with the bounding box size of one to the next, the first rotation to the second will work fine because its only moving in 2D at that point, but by the time you try to make the third rotation with the second rotations bounding box it won't work because it'll be going from 2D to 3D.

    Note - If you think you have a better way to do the equation or simpler way to explain it, feel free to add in your own answer.