Efficent Camera Movement

I am looking for an efficent way to move the camera around in a first person perspective(including Z ie the person can fly). My method right now uses lots of sin and cos calls and I figure there must be a much more efficent way to do it. Perhaps using gluLookAt and some dot products, but my head just couldn’t think of a good way. Anyone out there got some good way to do this?

here’s what I use… I don’t know if it’s right or wrong… but it seems perfectly ok…

x,y,z = your pos…
this lets you look around freely given the x angle = 0 when looking straight ahead…
and yangle=0 looking straight ahead, yangle is + as you go up… xangle is + as you go to the right…

static GLfloat lookx(0.0f), looky(0.0f), lookz(0.0f);
static GLfloat upx(0.0f), upy(1.0f), upz(0.0f), dist(5.0f);

lookx=x+dist*sinf(xangle)*cosf(yangle);
looky=y+dist*sinf(yangle);
lookz=z+(-1*dist*cosf(xangle)*cosf(yangle)); // I know x+(-y) = x-y

if (yangle>PI/2.0) yangle=PI/2.0;

if (yangle<-PI/2.0) yangle=-PI/2.0;

gluLookAt(x,y,z,lookx,looky,lookz,upx,upy,upz);

the movement is:

	ytheta+=6.28f/20.0f;
	x+=cosf(xangle)*speed;
	z+=sinf(xangle)*speed;
	y=sinf(ytheta)*0.03f;

//don’t confuse the ytheta with yangle, ytheta is for bumping you
// up and down as you move…

adding some equations so you can fly shouldn’t be hard at all fromt his point… by the way, I would rederive all the equations by yourself and then check… =), it’s more fun that way!!

[This message has been edited by ngill (edited 07-08-2000).]

[This message has been edited by ngill (edited 07-08-2000).]

Calling sin, cos, etc is not inefficient. Why?

Sin, etc are just coefficients, or numbers multiplied by whatever parameter you specify.

As they functions are inlined I doubt there is any function call overhead when the code is compiled.

I’m pretty sure that sin and cos are pretty expensive. I suppose I could run a little benchmark. I’ve seen replacement sine and cosine routines that use a table lookup to speed up these computations, that makes me think the default versions are slow. I know dot products are super fast so that is why I’d like to find a way to replace my current method with a dot product method. In the mean time I think I’ll put together a little bench mark. Talk to ya latter

Ok I made the following benchmark.

#include <iostream>
#include <cmath>

#include “bmark.h”

using namespace std;

void main()
{

float bob = 3.14f;
float holder;
Benchmark theBmark;

for(unsigned long int i=0; i&lt;123456789; ++i)
{
	holder=bob*i;
}
cerr &lt;&lt; theBmark.bTime() &lt;&lt; endl;

Benchmark theBmark2;
for(unsigned long int j=0; j&lt;123456789; ++j)
{
	holder=cosf(bob);
}
cerr &lt;&lt; theBmark2.bTime()&lt;&lt; endl;

}

From this code I get the multiplies taking 6.64 seconds. And the cosine taking 57.02 seconds.

ribblem, that’s 57 seconds for 123 million cosines! Exactly how many times per frame do you expect to be moving your camera? Might the answer be “one”? Meaning that your “inefficient” trig code must be costing you, ooh, a few millionths of a second per frame at the very least. Time to break out the assembler, boys.

You’re wasting your time optimizing this code for speed. You should be concentrating on keeping it clear and maintainable, and focusing your optimization efforts on the bits that’ll actually benefit.

As Donald Knuth said, “premature optimization is the root of all evil”.

Ok ngill.
but how can i find the angles(xangle, yangle, zangle ) ?

sorry my stupid question…

cya

You don’t have to “find” them. You can just “get” them from an input device for user input or key framing code for predefined camera path and events. For input devices just simply scale the input device values (relative offsets from previous device position) by some user configurable scale value.

i have to agree with MikeC… trig functions are quite fast. i’ve got a program performing 30 to 40 trig functions, assorted divisions and multiplications, etc, and i’m getting nearly 200fps. your GL state will affect you alot more. worry about efficient OpenGL code long before you worry about your math.

OK DFrey…
So those angle are just variable that i can inc or dec following the keyboard input, for example ?? ahhh nice…

and phlake, how did you get 200 FPS man ???
i`m fighting my machine to get 40…
so poor…

a magic ??
heheh

thanx…

Yeah, right. For user input, I generally would use the input values to affect an applied force (linear or angular) and then derive the velocites and displacements. Though things are a bit more complicated when collision detection is considered but I digress, that is off topic.

[This message has been edited by DFrey (edited 07-10-2000).]

Blza: well, first and foremost: not very many polygons. i’m building a tetris clone. 2nd: i have a geForce DDR. that probably helps. using detonator2 drivers, win2k, and a celeron overclocked to something like 472.6…

i’ll have source available in a week or two. (unfortunately, i’ve got some dns problems right now… emailing me will be difficult… temporarily, you may use nate@24.31.244.201)

No DFrey…
thats not off topic…

i dont know how uses those variables to simulate phisics laws man…

i mean, gravity, friction on body-to-body, etc…
is it hard ???

I suppose the preformance hit isn’t too bad now that I look at it. But I’m definantly talking about more than 1 or 2 trig calls. To obtain free movement in all axis I currently need 6 calls per camera. And since I’m working on realistic shadows and mirrors I need multiple cammeras. It all adds up… You guys are definently right thought that my state has much more effect.

This is what I use…It’s written in Visual Basic, but i’m sure you fancy C++ programmers can figure it out:

angle=(Xangle)(3.1415926/180) // calculate this for movement
angle2=(Zangle)
(3.1415926/180)

GLtranslate(-SavedX,-SavedY,-SavedZ) // translate the scene back to the origin

// Yaw
if keyboard.asynckeyDown(&h56) then
glRotate(2.0, 0.0, 0.0, 1.0)
Xangle=Xangle+2.0
elseif keyboard.asynckeyDown(&h58) then
glRotate(2.0, 0.0, 0.0, -1.0)
Xangle=Xangle-2.0
end if
//

// pitch
if keyboard.asynckeyDown(&h5B) then
glrotate(1.0, cos(angle), sin(-angle), 0)
Zangle=Zangle+1
elseif keyboard.asynckeyDown(&h54) then
glrotate(1.0, -cos(angle), -sin(-angle), 0)
Zangle=Zangle-1
end if
//

GLtranslate(SavedX,SavedY,SavedZ) // put the scene bakc where it was

Vert = Cos(angle2)
gltranslate (MySpeed*sin(angle))Vert, (MySpeedcos(angle))Vert, MySpeed-sin(angle2) // move the scene in the XYZ direction that the player is facing by the increment MySpeed (which, if you haven’t guessed, is the speed at which the player is moving)

SavedX=SavedX+MySpeed*sin(angle)Vert // store the values of where the scene is positioned
SavedY=SavedY+MySpeed
cos(angle)Vert
SavedZ=SavedZ+MySpeed
-sin(angle2)

FYI:
Keyboard.asyncKeydown(&h-whatever) polls the keyboard for the state of the key code passed, in case you were wondering what the heck that was for.

I hope this helps,
-Noah Desch

[This message has been edited by Noah (edited 07-12-2000).]

The sin function code body looks like this:

return parameter * sin_constant;

Any trig function is simple multiplication. Sin is a constant. You see?

Because peeps don’t know what trig is they assume it is slow… for a human, yes, but for a computer, no.

umm… if there was a constant… that would mean that sin, cos would be a linear trig functions!! and they certainly aren’t so… I could see it as a 6+ degree polynomial, which has a period… but that’s different that’s 6 mutliplications, instead of 1!

Easiest optimaization for this -

On construction of your class, app or whatever… build a trig lookup table. That way you’re only doing your “expensive” calls only once during the entire app, at initialization.

Old programming trick…

… old programming trick, which will unfortunately often slow you down on newer systems.

Read just about any book on optimization, and chances are it’ll tell you the same thing. Assume your processor is infinitely fast. It’s memory access that kills you.

When I started this thread I was sure the trig functions use some infinite series to produce the results and I’m still pretty certain that is what is being done. If anyone knows which infinate series is used I’d appricate it if you’d tell me, just so I know.

After seeing how fast these operations are done I would agree with MiceC that the long used trig lookup tables just might be dead since with processors being as fast as they are even a Cache 1 lookup costs many clock cycles.