[Algorithms] Re: Bottle placement and rotations
Brought to you by:
vexxed72
|
From: Casey M. <gd...@fu...> - 2002-10-30 20:47:45
|
> Get yourself a quat library, and try something like: for a given
> (normalised) axis and (random) rotation theta:-
>
> float cth = (float) cos(theta); // or whatever
> float sth = (float) sin(theta); // or whatever
> Quat q;
> q.x = x * cth;
> q.y = y * cth;
> q.z = z * cth;
> q.w = sth;
That's the rotation around the axis, not the orientation that puts
something into alignment with that axis. You want:
a <- n x p // determine axis of rotation
t <- asin(|a|) // determine amount of rotation
a <- a / |a| // normalize axis of rotation
q <- {a cos(t/2), sin(t/2)} // q rotates p into n
Where n is the normal along which you want the bottle to point, p is the
primary axis of the bottle you want "pointed" (presumably Z, but could by
Y if you're one of those Y-is-up types), a is thus the axis of rotation,
and t is the amount of rotation necessary to coincide the axes. If you
then want to randomly perturb the bottle, you would introduce a composite
rotation:
u <- rand(-pi, pi) // pick a random angle
r <- {p cos(u/2), sin(u/2)} // generate a random quaternion
q <- q r // pre-rotate by the random quaternion
Note that there's plenty partial-evaluation to be done here, for example
if you knew p to be the Z axis, then the cross products and the quaternion
construction for r have a lot of 0's, as will the resulting concatenation.
You could do it all out and have a very concise formula.
Also, for reference, here is the "most stable bases" generator I use in
Granny for computing coordinate systems where you just have an X axis, and
you want the other two axes to just be the most stable vectors possible.
It came originally from Chris Hecker, who got it from the computational
dynamics book by Shabana, and I've kept it around ever since because it
comes in very handy. It's not particularly fast, since it never gets used
at run-time and thus I've had no reason to optimize it:
void GRANNY
DextralBases(real32 const *XAxis, real32 *YAxis, real32 *ZAxis)
{
real32 CrossVector[3] = {1.0f, 1.0f, 1.0f};
real32 MaximumElement = 0.0f;
int MaximumElementIndex = 0;
{for(int ElementIndex = 0;
ElementIndex < 3;
++ElementIndex)
{
real32 ElementValue = AbsoluteValue(XAxis[ElementIndex]);
if(ElementValue > MaximumElement)
{
MaximumElement = ElementValue;
MaximumElementIndex = ElementIndex;
}
}}
CrossVector[MaximumElementIndex] = 0.0f;
VectorCrossProduct3(YAxis, CrossVector, XAxis);
Normalize3(YAxis);
VectorCrossProduct3(ZAxis, XAxis, YAxis);
Normalize3(ZAxis);
}
- Casey
|