# How To: Using up vector for a FlyPath

This topic is 4227 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, I'm coding a FlyPath (at least that's what I call it), you know the type where the camera follows a predetermined track using a set of control points. Each control point consists of an eye position, a look-at position and an up vector. To move the camera/eye I use 4 of the control points as input to form a Catmull-Rom Spline and simply interpolate. I want to use the up vector the "roll" the camera/eye. However, how should I interpolate the up vectors as the camera/eye follows the spline?
struct control_point
{
vec3 position, look_at, up;
};

...

void FlyPath::Animate()
{
lerp = lerp + MY_CTIME;

if (lerp > 1.0f)
{
lerp = 0.0f;

if (++index >= count)
{
index = 0;
}
}

vec3 p0 = step[(index - 1 + count) % count].position;
vec3 p1 = step[(index    ) % count].position;
vec3 p2 = step[(index + 1) % count].position;
vec3 p3 = step[(index + 2) % count].position;

current.position = 0.5f * ((2.0f * p1) +
(-p0 + p2) * lerp +
(2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * pow(lerp, 2.0f) +
(-p0 + 3.0f * p1 - 3.0f * p2 + p3) * pow(lerp, 3.0f));

p0 = step[(index - 1 + count) % count].look_at;
p1 = step[(index    ) % count].look_at;
p2 = step[(index + 1) % count].look_at;
p3 = step[(index + 2) % count].look_at;

current.look_at = 0.5f * ((2.0f * p1) +
(-p0 + p2) * lerp +
(2.0f * p0 - 5.0f * p1 + 4.0f * p2 - p3) * pow(lerp, 2.0f) +
(-p0 + 3.0f * p1 - 3.0f * p2 + p3) * pow(lerp, 3.0f));

// current.up = ?????????????????????????????????????????????????????????

return;
}

void FlyPath::Render()
{
gluLookAt(current.position[x], current.position[y], current.position[z],
current.look_at[x], current.look_at[y], current.look_at[z],
current.up[x], current.up[y], current.up[z]);

return;
}



##### Share on other sites
That would depend on how worried you are about having a constant roll speed. If you don't need a constant roll speed you can interpolate the up vector like everything else and just normalize it before you use it. If that's not good enough you might try looking into quaternions. They're supposed to be good for interpolation.

##### Share on other sites
OK, so how should I proceed if I wanted a constant roll speed?

##### Share on other sites
You can interpolate UP vector just like you´re doing with everything else...

But, I don´t think you´re going to get things smooth...

Using quaternion is the way to do it:

Do it interpolating position using splines but interpolate camera rotation using quaternions.

Heres something you can do:

using UP, AT and EYE you can have camera axis at each point:

-zAxis = at - eye
xAxis = -zAxis ^ upAxis
yAxis = xAxis ^ -zAxis

(^ = vectorial product )

Camera rotation matrix is:
m[16] =
[ xAxis.x, xAxis.y, xAxis.z, 0 ]
[ yAxis.x, yAxis.y, yAxis.z, 0 ]
[ zAxis.x, zAxis.y, zAxis.z, 0 ]
[ 0, 0, 0, 1 ]

( In the code below m.m show up, its only because I have
Struct Matrix
{ m[16]; }; )

Then you can build a quaternion from this matrix:

** STRUCT QUATERNION ***

typedef struct
{

real w;

real x;

real y;

real z;
}
Quat;

** QUATERNION FROM MATRIX **

Quat q;
real tr = m.m[0] + m.m[5] + m.m[10]; /* Matrix trace */
real s;

if ( tr > 0 )
{
s = (real) sqrt(tr + 1);

q.w = 0.5f * s;
s = 0.5f / s;
q.x = (m.m[6] - m.m[9]) * s;
q.y = (m.m[8] - m.m[2]) * s;
q.z = (m.m[1] - m.m[4]) * s;
} else
{
/* Find out the bigger element from diagonal */
real max = m.m[0];
max = (m.m[5] > max ? m.m[5] : max);
max = (m.m[10] > max ? m.m[10] : max);

if ( m.m[0] == max )
{
/* Column 0 */
s = (real) sqrt(m.m[0] - m.m[5] - m.m[10] + 1);

q.x = 0.5f * s;
if ( s != 0 ) s = 0.5f / s;

q.w = (m.m[6] - m.m[9] ) * s;
q.y = (m.m[1] + m.m[4] ) * s;
q.z = (m.m[2] + m.m[8] ) * s;
} else if ( m.m[5] == max )
{
/* Column 1 */
s = (real) sqrt(m.m[5] - m.m[0] - m.m[10] + 1);

q.y = 0.5f * s;
if ( s != 0 ) s = 0.5f / s;

q.w = (m.m[8] - m.m[2]) * s;
q.x = (m.m[1] + m.m[4]) * s;
q.z = (m.m[6] + m.m[9]) * s;
} else
{
/* Column 2: m[10] == max */
s = (real) sqrt(m.m[10] - m.m[0] - m.m[5] + 1);

q.z = 0.5f * s;
if ( s != 0 ) s = 0.5f / s;

q.w = (m.m[1] - m.m[4]) * s;
q.x = (m.m[2] + m.m[8]) * s;
q.y = (m.m[6] + m.m[9]) * s;
}
}
return q;

Ok. Now, with that in hands, you can easily interpolate quaternions by using linear interpolation:

q(t) = aq1 + bq2

b = 1-a

t is the linear parameter

When you have the interpolated quaternion, its easy to get the rotation matrix back, you only need to know that a quaternion is actually:
q = (cos(Theta/2), sin(Theta/2)ê)

ê is the unitary rotation axis.

With that you can build the rotation matrix again..
you transitions between cameras rotations will be very smooth..

[Edited by - hugeride on May 18, 2007 1:51:18 PM]

##### Share on other sites
To get a matrix again from a quaternion just find out how to built a matrix from an angle and an axis (you gonna get angle and axis from final quaternion )

[Edited by - hugeride on May 18, 2007 1:57:36 PM]

1. 1
2. 2
3. 3
4. 4
Rutin
13
5. 5

• 26
• 10
• 9
• 9
• 11
• ### Forum Statistics

• Total Topics
633696
• Total Posts
3013394
×

## Important Information

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!