|
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
|
10-27-2008 08:01
I have two normalized vectors, P1 and P2 (representing directions from the object center).
I need to generate N new vectors that evenly divide the angle between these two. Simplest case is where N is 1, where the new vector bisects the angle between the two.
I know how to calculate the angle between them using dot product and arccos, but can't quite figure out how to use this to create the new vector. I'm sure I learned this in high school, but I seem to have lost it somewhere over the last 30 years -- probably, the day after the final exam. I'd appreciate any help.
Thanks!
|
|
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
|
10-27-2008 09:11
If they only need to be ROUGHLY distributed evenly, you can normalize an affine combination of the two as follows: // param vecA - The first unit vector (assumed unit; not checked by function). // param vecB - The last unit vector (assumed unit; not checked by function). // param nSteps - The number of steps between vecA and vecB // param step - Which step to return the vector for. 0 results in vecA; 'nSteps' results in vecB; anything inbetween will result in a (not-quite-linear) interpolation between the two. Values outside this range will result in undefined behavior vector stepInterpolatedVector(vector vecA, vector vecB, integer nSteps, integer step) { float t = ((float)step)/nSteps; vector comb = t*vecA+(1.0-t)*vecB; return llVecNorm(comb); }
If you want a more precise answer, you'll want to decompose the rotation between the two into axis and angle, interpolate the angle linearly, then convert back to a vector. // param vecA - The first unit vector (assumed unit; not checked by function). // param vecB - The last unit vector (assumed unit; not checked by function). // param nSteps - The number of steps between vecA and vecB // param step - Which step to return the vector for. 0 results in vecA; 'nSteps' results in vecB; anything inbetween will result in a (not-quite-linear) interpolation between the two. Values outside this range will result in undefined behavior vector stepInterpolatedVector(vector vecA, vector vecB, integer nSteps, integer step) { // Easier than llRotBetween() and then decomposing into axis/angle vector axis = llVecNorm(vecA%vecB); float angle = llAcos(vecA*vecB);
float t = ((float)step)/nSteps;
float theta = t*angle; rotation rot = llAxisAngle2Rot(axis, theta);
return vecA*rot; }
Note that either way you are going to run into problems when the two vectors are parallel (point in the same direction or opposite directions). The first function will have a fit half-way between when it tries to normalize a zero-vector. The second function will have a fit calculating the axis because the cross product will be a zero-vector. So you might want to add checks for that situation in either. When the vectors are identical (point in the same direction), it should be obvious what to do (all interpolation results will be identical and equal to the inputs). What you do when they point in opposite directions will have to be a design decision as there is no obvious, unambiguous answer.
|
|
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
|
10-27-2008 09:12
I kee thinking I can get away with... x = ( (vecA - vecB) / n ) * nX + vecA where nX is the number of the subdivided vector starting closest to vecA little fuzzy this morning so if I royally screwed that up, someone beat me with a stick EDIT: nvm, hewee's faster on the draw than I, let the beating commence and then I remembered http://wiki.secondlife.com/wiki/Slerp
_____________________
| | . "Cat-Like Typing Detected" | . This post may contain errors in logic, spelling, and | . grammar known to the SL populace to cause confusion | | - Please Use PHP tags when posting scripts/code, Thanks. | - Can't See PHP or URL Tags Correctly? Check Out This Link... | - 
|
|
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
|
10-27-2008 11:12
Thanks, both. I thought that this would work, but the arc of objects rezzed at the vectors don't lie on a great circle around the object origin: vector subrotate(vector p1, vector p2, float frac) { rotation rot = llEuler2Rot( llRot2Euler( llRotBetween(llVecNorm(p1), llVecNorm(p2)) ) * frac); return p1 * rot; }
I guess dividing the Euler by a scaler isn't quite what I'd hoped. (It is in some cases ... but not all!) So, there's no simple way to divide a rotation by a scalar -- yielding that fraction of the rotation? Sheesh! Thanks Jeff
|
|
Lear Cale
wordy bugger
Join date: 22 Aug 2007
Posts: 3,569
|
10-27-2008 12:05
Woot! Thanks Hewee, works great!
|
|
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
|
10-27-2008 13:52
Glad to hear it.  There's one useful mantra to learn when dealing with rotations. Repeat after me: Euler angles are worthless; Euler angles are worthless; Euler angles are worthless.  And yeah, you can't quite just multiply a quaternion by a scalar multiple either. I guess they COULD have implemented it that way, but it would have been a pretty high-level operation (not that transforming a vector with a rotation isn't, but at least that one is the most expected and only real useful result of such multiplication).
|