PDA

View Full Version : Moving the camera with a constant velocity



Ehsan Kamrani
02-15-2006, 03:49 AM
I want to move the camera on a curve with a constant velocity. As you know, V = dy/dx . If i want to move the camera on the following curve, V is not constant:

Y = 4 * X^2 + sin( 2 * X )

How can i solve this problem?
-Ehsan-

RigidBody
02-15-2006, 04:47 AM
you want to move the camera with a constant velocity with respect to the curve's arc length s: v = ds/dt.

ds can be calculated as ds=sqrt(dx^2+dy^2). this can be transformed:

ds=dx*sqrt(1+(dy/dx)^2)=dx*sqrt(1+(y')^2)

y'=dy/dx is the curve's derivative.

for y = 4*x^2+sin(2*x), the curve's derivative is y'=dy/dx=8*x+2*cos(2*x),

since ds = v*dt:

dx = (v*dt) / sqrt(1+(y')^2)

this means that for a given x-coordinate, you can calculate y'(x). with a given v and dt you'll get a value for dx, from which you can calculate dy=y'*dx. now all you have to do is to move your camera by dx and dy.

hope that helps.

Ehsan Kamrani
02-15-2006, 05:37 AM
So can i use from this function to move in a curve with a constant velocity?

void MoveCamera( GLfloat dt, GLfloat v )
{
x += X_MOVE;
temp = 8 * x + 2 cos( 2 * x * piover180 );
GLfloat dx = ( dt * v )/ sqrt( 1 + pow( temp ) );

GLfloat dy = temp * dx;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( dx, dy, 2, 0, 0, 0, 0, 1, 0 );
}

And in my Render function i call the function MoveCamera:

void Render()
{
...
MoveCamera( 0.01, 0.1 );

}

Am i correct?
-Ehsan-

RigidBody
02-15-2006, 05:54 AM
not quite, i guess.

1. i'm not sure where X_MOVE comes from.

2. if y=4*x^2+sin(2*x), y'=8*x+2*cos(2*x),
but if y=4*x^2+sin(2*x*piover180), then y'=8*x+2*piover180*cos(2*x*piover180)

3. the exponent is missing in the pow() function

assuming that the camera position is (x,y) and you want to look along the curve direction:

void MoveCamera( GLfloat dt, GLfloat v ){
GLfloat temp = 8 * x + 2*piover180*cos(2*x*piover180);
GLfloat dx = (dt*v)/sqrt(1.+pow(temp,2.));
GLfloat dy = temp * dx;

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt( x, y, 1, x+dx, y+dy, 0, 0, 0, 1 );

x += dx;
y = 4.*x*x+sin(2.*x*piover180);
}

i'm not using 'y += dy', since the new camera position could possibly not be on the curve anymore due to the linearization.

jide
02-15-2006, 06:59 AM
From the equation you stippled at the first post:

Y = 4 * X^2 + sin( 2 * X )

There's nothing meaning the velocity neither the time (you just have y = func (x)). Maybe if you calculate x depending on the velocity and time you'll might have what you want. Something like x = 0.01*t might 'help'.

General law of motion is like this:

a = dv/dt
v = dp/dt

where a is the acceleration, v the velocity and p the position and du/dt means the derivative of u regarding t (the time). a,v and p are all vectors.

But if the equation you have describes the movement of your object, you might not need to do any derivatives or integrals at all.

It really depends on your objectives. Something like:

x = cos (t)
y = sin (t)
z = 1

is also fine.

Hope that could help a bit.

Ehsan Kamrani
02-15-2006, 06:59 AM
RigidBody, Jide
Can i send my questions about this topic to your mail? This question doesn't refer to OpenGL ;)
-Ehsan-

RigidBody
02-15-2006, 07:28 AM
maybe it should rather be in the math & algorithms forum, but i'm not that picky...did you try the version that i posted?

RigidBody
02-15-2006, 09:08 AM
if you move with a constant speed in x-direction like x=0.01*t, the velocity with which you move along the curve will not be constant (unless it is not a curve, but a straight line). that's what ehsan said at the beginning.

by the way:

x = cos (t)
y = sin (t)

is a circle. that is not what ehsan wants, i guess.

in 2D, velocity is a vector with 2 components:

v=[dx/dt dy/dt]

the absolute value is

|v|=sqrt((dx/dt)^2+(dy/dt)^2)

this is equivalent to

|v|=sqrt(dx^2+dy^2)/dt

as i mentioned above, this can be transformed to

|v|=dx*sqrt(1+(y')^2)/dt

with y'=dy/dx

for an explicitely given curve y=f(x) you can calculate y'. for ehsan's curve y=4*x^2+sin(2*x) the derivative is y'=8*x+2*cos(2*x)

so what you have to do is to choose a constant velocity |v|, pick an arbitrary starting point on the curve and for each time you move the camera:

1. calculate y' at the current x-position
2. calculate dx=|v|*dt/sqrt(1+(y')^2)
3. calculate dy=y'*dx
4. use x,y,dx,dy in gluLookAt as i showed above: gluLookAt(x,y,1.,x+dx,y+dy,0.,0.,0.,1.)
5. move the camera into direction of [dx dy]. as i said, first add dx to the current x position. if you add dy to the current y position, the new point is no longer on the curve. so it is better to calculate the new y-position using the function y=f(x) with the new x-position. this is a bit inaccurate (depending on the time step and the curvature), but it should work.

RigidBody
02-15-2006, 09:33 AM
so here it is. in the above post i forgot that you should normalize the [dx dy] vector. in the gluLookAt function, the view is from z=10. to z=9.9. if these values are not close enough, you might see only the ground...


double funcY(double lx) { // RETURN Y AS FUNCTION OF X
return(4.*lx*lx + sin(2.*lx)); }

double funcDyDx(double lx) { // RETURN THE DERIVATIVE
return(8.*lx + 2.*cos(2.*lx)); }

double X = 0., Y = funcY(X), V = 3.; // SET INITIAL CAMERA POSITION AND VELOCITY

void MoveCamera(double dt) { // MOVE THE CAMERA

double dydx = funcDyDx(X); // CALCULATE DERIVATIVE
double dx = V*dt / sqrt(1+dydx*dydx); // CALCULATE DX
double dy = dydx*dx; // CALCULATE DY
double l = sqrt(dx*dx + dy*dy); // LENGTH OF [DX DY] FOR NORMALIZATION

dx /= l; // NORMALIZE THE DERIVATIVE
dy /= l; // TO UNIT LENGTH

glMatrixMode(GL_MODELVIEW); // SET CAMERA POSITION
glLoadIdentity();
gluLookAt(X, Y, 10., X+dx, Y+dy, 9.9, 0., 0., 1.);

X += V*dx*dt; // CALCULATE NEW X POSITION
Y = funcY(X); // CALCULATE NEW Y POSITION USING funcY
}

Ehsan Kamrani
02-16-2006, 06:56 AM
Thank you. I tried it and it works great. But now i have no idea about the parametric equations such as w(t) = x(t) i + y(t) j + z(t) k :confused:
Note: Is there a book about such topics?
-Ehsan-

RigidBody
02-16-2006, 11:10 AM
now i'm a bit confused. i assume that w(t) equation belongs to a different topic- what's it about?

jide
02-16-2006, 11:42 PM
Originally posted by Ehsan Kamrani:
Thank you. I tried it and it works great. But now i have no idea about the parametric equations such as w(t) = x(t) i + y(t) j + z(t) k :confused:
Note: Is there a book about such topics?
-Ehsan-w(t) does not fill well, you really should have something like that (a parametric equation):

x(t) = func1 (t)
y(t) = func2 (t)
z(t) = func3 (t)

Doing so, you won't need to do any derivative/integrals. I guess this is best.

By the way, what w(t) refers to ? a vector depending on the time ? Or is it only the name of the equation ? Also, if you could give the entire function, it might help.

i,j,k are of course the unit vectors of your basis, respectively for (x,y,z) coordinates.

RigidBody
02-17-2006, 08:09 AM
ähm, no...if you want to move with constant velocity, you need to know the actual velocity at any point of the curve, which means that you need a derivative.

if you have a curve y=f(x), the velocity is v=[dx/dt dy/dt], |v|=sqrt((dx/dt)^2+(dy/dt)^2) (or |v|=dx/dt*sqrt(1+(y')^2), as i posted before).

if you have a curve c=[x(t) y(t)], the velocity is v=[dx(t)/dt dy(t)/dt], |v|=sqrt((dx(t)/dt)^2+(dy(t)/dt)^2).