Advertisement

Writing my own camera class... Problems

Started by October 24, 2004 04:09 AM
12 comments, last by hang3r 20 years, 4 months ago
I have a problem when translating, im trying to make my class similer to that of the "Quaternion Camera Class", but it seems that there is somthing wrong with the way i am calculating the ypos... Bellow is my equivalent to the setPerspective function in the Quaternion Camera Class.

void positionWorld()
{

	glRotatef(pitch,1.0f,0,0);
	glRotatef(heading,0,1.0f,0);

	if ((velocity > 0) || (velocity < 0))
	{
     	        xpos += (float)sin(heading*piover180) * velocity;
		zpos -= (float)cos(heading*piover180) * velocity;
		ypos -= (float)sin(pitch*piover180)* velocity;
	}

	glTranslatef(-xpos, -ypos, -zpos);	
}

-Nathan
Could you describe what happens and what should happen?
Advertisement
pitching up or down 180o feels like you traviling backwards and everything is inverted... I also noticed this a little as i approach 180, it just doesnt have the same feel as the "Quaternion Camera Class".

camera motions are hard, you need to fiddle with them.

rx,ry,rz = rotations(heading, pitch, bank)
xb = forward velocity
yb = up/down velocity
zb = strafe velocity
t = timestep

I use these in my engine to move the camera(and it's not pretty)
xv=(sin(-rx/(180/3.1415))*(xb*t))-(sin(+(rx+90)/(180/3.1415))*(zb*t));
yv=(sin(ry/(180/3.1415))*(xb*t))+(yb*t);
zv=(-(cos(-rx/(180/3.1415))*(xb*t)))-(cos(+(rx+90)/(180/3.1415))*(zb*t));

x=x+xv;
z=z+zv;
y=y+yv;

I use these to find out the current heading vector(and it's pretty mutch the same as yours only different).

v[0]=(sin(-rx/(180/3.1415))*(1));
v[1]=(sin(ry/(180/3.1415))*(1));
v[2]=(-(cos(-rx/(180/3.1415))*(1)));

Use these if you like, otherwise, just start fiddeling with them until it works.
yeah thanks for that, but it sorta translates to exactly what i already have... lol...
lc_overlord:

That's one ugly piece of code!
First the realtime cos and sin funtions(big performance no-no), then the realtime divisions(performance no-no), and best for last =), the absolutely cryptic huge lines of code.

*G*
lax=px+(tcos[anglex]*tncos[angley]);laz=pz+(tsin[anglex]*tncos[angley]);lay=py+tsin[angley];

Woudln't something like this be prettier?
Of course with this one there is no velocity control, but you get the picture. =)
Advertisement
I know it's not pretty, it's only temoprary code, infact my entire update/input fuction is one big horrific mess, Only 50% of all the stuff in it actuarly does something and it uses a spiderwebb of different variabls.
Just look at this mess.

Globals:
GL_Window*	g_window;Keys*		g_keys;double x=0,y=0,z=0,rx=0,ry=0,rz=0,xb=0,yb=0,zb=0,acc=60,yg=0;double g[3],op[3],fpsf[5];int fpsi=0,fpsit=0,textpos,textpos2,blurmethod=1;int lastm_y=0;int filter[2][10];float p[5000][3],tc=0,df=10,blurlength=0,bmhold=0;int llist[256];unsigned int b,b2,s,s2;unsigned int ptex;shader tx;screen sx;sky skyx;camera cam;light lx;CFsound sn;CFlog lg;CFdraw dm;CFgsv gsv;CFhud hud;


Update func:
void Update (DWORD milliseconds)								// Perform Motion Updates Here{	double t2,xv,yv,zv,lp[3],fo;	t2=(double)milliseconds/1000;	double t,gpoint[3],mvec[4];	float f[2];	int done=0,i=0;	if (g_keys->keyDown [VK_ESCAPE] == TRUE)					// Is ESC Being Pressed?	{		TerminateApplication (g_window);						// Terminate The Program	}		//	mousefilter	filter[0][0]=filter[0][1];	filter[0][1]=filter[0][2];	filter[0][2]=filter[0][3];	filter[0][3]=filter[0][4];	filter[0][4]=filter[0][5];	filter[0][5]=filter[0][6];	filter[0][6]=filter[0][7];	filter[0][7]=filter[0][8];	filter[0][8]=filter[0][9];	filter[0][0]=mouse_x-300;	f[0]=filter[0][0]+filter[0][1]+filter[0][2]+filter[0][3]+filter[0][4]+filter[0][5]+filter[0][6]+filter[0][7]+filter[0][8]+filter[0][9];	filter[1][0]=filter[1][1];	filter[1][1]=filter[1][2];	filter[1][2]=filter[1][3];	filter[1][3]=filter[1][4];	filter[1][4]=filter[1][5];	filter[1][5]=filter[1][6];	filter[1][6]=filter[1][7];	filter[1][7]=filter[1][8];	filter[1][8]=filter[1][9];	filter[1][0]=mouse_y-300;	f[1]=filter[1][0]+filter[1][1]+filter[1][2]+filter[1][3]+filter[1][4]+filter[1][5]+filter[1][6]+filter[1][7]+filter[1][8]+filter[1][9];	fpsf[0]=fpsf[1];	fpsf[1]=fpsf[2];	fpsf[2]=fpsf[3];	fpsf[3]=fpsf[4];	fpsf[4]=t2;		t=((fpsf[0]+fpsf[1]+fpsf[2]+fpsf[3]+fpsf[4])/5);	tc+=t2;	fpsit++;	if (tc>1){tc-=1; fpsi=fpsit; fpsit=0;}//	fpsi=(int)(1/t);		rx -= (f[0]*10*t);	ry -= (f[1]*10*t);	SetCursorPos(300,300);	if (rx<0) rx=rx+360;	if (rx>360) rx=rx-360;	if (xb>0) xb-=(acc*t);	else if (xb<-0) xb+=(acc*t);	if ((xb>-acc*t/2) && (xb<acc*t/2)) xb=0;	if (GetAsyncKeyState(VK_HOME)) xb=xb+(acc*t*2);	if (GetAsyncKeyState(VK_END)) xb=xb-(acc*t*2);	if (xb>30) xb=30;	if (xb<-30) xb=-30;			if (zb>0) zb-=(acc*t);	else if (zb<-0) zb+=(acc*t);	if ((zb>-acc*t/2) && (zb<acc*t/2)) zb=0;	if (GetAsyncKeyState(VK_DELETE)) zb=zb+(acc*t*2);	if (GetAsyncKeyState(VK_NEXT)) zb=zb-(acc*t*2);	if (zb>30) zb=30;	if (zb<-30) zb=-30;	if (yb>0) yb-=(acc*t);	else if (yb<-0) yb+=(acc*t);	if ((yb>-acc*t/2) && (yb<acc*t/2)) yb=0;	if (GetAsyncKeyState(VK_RETURN)) yb=yb+(acc*t*2);	if (GetAsyncKeyState(VK_INSERT)) yb=yb-(acc*t*2);	if (yb>15) yb=15;	if (yb<-15) yb=-15;	lx.setLight(llist[1]);	lp[0]=lx.getPos(0);	lp[1]=lx.getPos(1);	lp[2]=lx.getPos(2);//	fo=lx.getFalloff();		bmhold+=t;	if ((g_keys->keyDown ['B']) && (bmhold>0.1))	{		if (blurmethod==0) blurmethod=1;		else blurmethod=0;		bmhold=0;	}			if (g_keys->keyDown ['A']) blurlength+=0.3;	if (g_keys->keyDown ['Z']) blurlength-=0.3;	if (blurlength<0) blurlength=0;	if (blurlength>40) blurlength=40;	if (g_keys->keyDown [VK_UP]) lp[0]+=1;	if (g_keys->keyDown [VK_ADD]) lp[1]+=1;	if (g_keys->keyDown [VK_RIGHT]) lp[2]+=1;	if (g_keys->keyDown [VK_DOWN]) lp[0]-=1;	if (g_keys->keyDown [VK_SUBTRACT]) lp[1]-=1;	if (g_keys->keyDown [VK_LEFT]) lp[2]-=1;		if (g_keys->keyDown [VK_MULTIPLY]) df+=0.1;	if (g_keys->keyDown [VK_DIVIDE]) df-=0.1;	lx.setPos(lp[0],lp[1],lp[2]);	lx.setDifuse(df,df,df,1);	//lx.setFalloff(fo);//	yg -=(0.5*t);		double v[3];	xv=(sin(-rx/(180/3.1415))*(xb*t))-(sin(+(rx+90)/(180/3.1415))*(zb*t));	yv=(sin(ry/(180/3.1415))*(xb*t))+(yb*t);	zv=(-(cos(-rx/(180/3.1415))*(xb*t)))-(cos(+(rx+90)/(180/3.1415))*(zb*t));	v[0]=(sin(-rx/(180/3.1415))*(1));	v[1]=(sin(ry/(180/3.1415))*(1));	v[2]=(-(cos(-rx/(180/3.1415))*(1)));	normalize(v,1);	cam.setCameraPos(x,y,z);	cam.setCameraAngle(rx,ry,rz);	cam.setCameraVector(v);//	sn.setListnerCamv(x,y,z,rx,ry,rz,xb);		op[0]=x; 	op[1]=y;	op[2]=z;	x=x+xv; 	z=z+zv; 	y=y+yv;	dm.setTime(t);			if (g_keys->keyDown [VK_F1] == TRUE)						// Is F1 Being Pressed?	{		ToggleFullscreen (g_window);							// Toggle Fullscreen Mode	}}



But as i said it's only temps, it will be rewritten eventualy(allthough probobly sometime 2007)
Yeah i realise the performance hits, but at the momment im only concerned with get it to actualy work...

i still havent solved the problem...


-Nathan
@xor : Hmmm I'm not sure lookup tables are still a good idea for sin and cos functions :
- your solution will only give an approximation of sin and cos (at least, you should interpolate to get a decent value) ;
- some processors now have sin/cos functions and I'm not sure they are much slower than reading tables in memory ; for processors that don't there are approximations for those functions that are more cache-friendly that a LUT.

BTW, the "ugly division" in his code is not a division. Any decent compiler will calculate 1/(180/pi) statically and generate a product instead.

Just my 0.02 €

[Edited by - rodzilla on October 24, 2004 11:31:11 PM]
SaM3d!, a cross-platform API for 3d based on SDL and OpenGL.The trouble is that things never get better, they just stay the same, only more so. -- (Terry Pratchett, Eric)
rodzilla:

Why do you say something like that? It SO obvious that the code is poorly written that even the author admits it.
Have you ever tried booth ways? Using trignometric instructions instead of a table. Because i have, and i _know_ it's better.

Quote:

your solution will only give an approximation of sin and cos (at least, you should interpolate to get a decent value) ;


Actually it won't. It will give me a value with the precision of a double for the exact angle i'm asking for. I only need, in this case in particular, 2048 angle positions. They are all stored in a table.

Quote:

some processors now have sin/cos functions and I'm not sure they are much slower than reading tables in memory ; for processors that don't there are approximations for those functions that are more cache-friendly that a LUT.


Some processor NOW have sin/cos?! Processor have sin/cos and more trignometric funtions since the introduction of FPU's wich remounts to the age of the 386!
As for the speed, have you checked recently any latency tables for cpu/fpu operations? An addition takes a cycle to compute, a multiplication 10, and a division over 50 IRC. Sin and cos operations take between 160 and 280 cycles, some other trignometric operations can go up to 300 cycles. There is a big diference.

Quote:

BTW, the "ugly division" in his code is not a division. Any decent compiler will calculate 1/(180/pi) statically and generate a product instead.


(rx+90)/(180/3.1415))
This first division won't be compiled statically,
(-rx/(180/3.1415))
And this first one won't either. It's ugly enough.

--edit--
I should note those cycles are for Pentium 4 processors.
--edit--

[Edited by - xor on October 25, 2004 8:14:30 AM]

This topic is closed to new replies.

Advertisement