While building the tree generator I needed to figure out the bounding box for the tree. The problem is that each branch is rotated and translated using Ri calls so that the nurbs tubes themselves are always drawn at (0,0,0) in the Z direction.
Translation was easy but the rotation naturally requires the use of the rotation matrix... ok that's not really that complicated but doing it right, and thus allowing for rotations around an arbitrary axis, requires that all three rotation matrices (i.e. along X, Y, Z) are added... again that's not that difficult but since there are a lot of terms things can get out of control quickly:
1m_Bounds[i] = x*(uX*uX*(1 - c) + c) + y*(uX*uY*(1 - c) - uZ*s) + z*(uX*uZ*(1 - c) + uY*s);
2m_Bounds[i] = x*(uX*uY*(1 - c) + uZ*s) + y*(uY*uY*(1 - c) + c) + z*(uY*uZ*(1 - c) - uX*s);
3m_Bounds[i] = x*(uX*uZ*(1 - c) - uY*s) + y*(uY*uZ*(1 - c) + uX*s) + z*(uZ*uZ*(1 - c) + c);
Anyway so I implemented it and it worked on the first try, using a single branch rotated 90 degrees. But when I tested it with a branch at 45 degrees instead of seeing a 45 degree rotated box inscribing the branch-tube I had a huge flat pizza box:
I checked the matrix and found a small bug in one of the terms but fixing it had no effect... arghh wtf?!?! So I checked the maths three more times using independent sources (MathWorld, Wikipedia, and another website) even looked at my linear algebra and physics textbooks... it was correct. Finall after I tried several different angles it dawned on me it's a bounding box which by definition is composed of the min/max coordinates along each axis so its sides always line up with the world axis... and as such the thing is supposed to look like a pizza box... what a waste of 15 minutes.
Morals (choose one):
- Know what the correct output looks like because it may look wrong... but be right.
- If you expect your code to produce incorrect results you'll believe it has... even when it's right.
- When you think the output is wrong make sure it actually is before looking for problems.