/* Camera Methods.
*
* Copyright (C) 2006 Fixi Studios.
*
* Authors:
* Marvin Stockl Garcia <durmieu@users.sourceforge.net>
* Jeremies Perez Morata <jeremiespm@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "nitrito.h"
void Camera::reset ()
{
glLoadIdentity();
gluPerspective(45.f, (float)options.screen_w/options.screen_h, options.view_close, options.view_far);
glGetFloatv(GL_PROJECTION_MATRIX, cam->proj_matrix);
x = 0; y = 0; z = 0;
h = 0; p = 0; r = 0;
x2 = 0; y2 = 0; z2 = 0;
h2 = 0; p2 = 0; r2 = 0;
xs = 0; ys = 0; zs = 0;
hs = 0; ps = 0; rs = 0;
}
void Camera::set (float cx, float cy, float cz, float ch, float cp, float cr)
{
while (ch<-180) ch += 360;
while (ch> 180) ch -= 360;
x = cx;
y = cy;
z = cz;
h = ch;
p = cp;
r = cr;
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glRotatef (cr, 1,0,0);
glRotatef (cp, 0,1,0);
glRotatef (ch, 0,0,1);
glTranslatef (-cx,-cy,-cz);
glGetFloatv(GL_MODELVIEW_MATRIX, view_matrix);
calculate_bsphere();
}
void Camera::calculate_bsphere()
{
float view_dist;
float vect_x_de_z,vect_y_de_z,vect_z_de_z;
float center_dist;
view_dist = options.view_far-options.view_close;
center_dist = options.view_close + view_dist/2;
vect_x_de_z=view_matrix.data[2];
vect_y_de_z=view_matrix.data[6];
vect_z_de_z=view_matrix.data[10];
bsphere.x=x-vect_x_de_z*center_dist;
bsphere.y=y-vect_y_de_z*center_dist;
bsphere.z=z-vect_z_de_z*center_dist;
bsphere.r=view_dist/2;
}
void Camera::move (float cx, float cy, float cz, float ch, float cp, float cr)
{
x+=cx;
y+=cy;
z+=cz;
h+=ch;
p+=cp;
r+=cr;
set(x,y,z,h,p,r);
}
void Camera::move2 (float cx, float cy, float cz, float ch, float cp, float cr)
{
x+=(cy*sin(h/180.0*M_PI))+(cx*cos(h/180.0*M_PI));
y+=(cy*cos(h/180.0*M_PI))+(cx*-sin(h/180.0*M_PI));;
z+=cz;
h+=ch;
p+=cp;
r+=cr;
set(x,y,z,h,p,r);
}
void Camera::set_mode (int mode)
{
const dReal *m;
const dReal *pos;
m = dBodyGetRotation(coche[0].body[0]);
pos = dBodyGetPosition(coche[0].body[0]);
switch (mode) {
case 0:
break;
case 1:
float a,b;
x2=pos[0]-m[0]*1.0;
y2=pos[1]-m[4]*1.0;
z2=pos[2]+20;
a=(x-pos[0]);
b=(y-pos[1]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=0;
break;
case 2: { //camara trasera muy cerca
float a,b;
x2=pos[0]-m[0]*2.0;
y2=pos[1]-m[4]*2.0;
z2=pos[2]+1;
a=(x-pos[0]);
b=(y-pos[1]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=-90;
break;
}
case 3: { //camara trasera cerca
float a,b;
x2=pos[0]-m[0]*5.0;
y2=pos[1]-m[4]*5.0;
z2=pos[2]+1;
a=(x-pos[0]);
b=(y-pos[1]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=-90;
}
break;
case 4: { //camara traera lejos
float a,b;
x2=pos[0]-m[0]*10.0;
y2=pos[1]-m[4]*10.0;
z2=pos[2]+2;
a=(x-pos[0]);
b=(y-pos[1]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=-90;
}
break;
case 5: { //camara lateral derecha
float a,b;
x2=pos[0]+m[4]*5.0;
y2=pos[1]-m[0]*5.0;
z2=pos[2]-0.5;
a=(x-pos[0]);
b=(y-pos[1]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=-90;
}
break;
case 6: { //camara TV
static float a,b,c,d;
if(c>30) {
x=pos[0]+m[0]*10.0;
y=pos[1]-m[4]*10.0;
z=pos[2]+5;
x2=x; y2=y; z2=z;
a=(x-pos[0]);
b=(y-pos[1]);
c=sqrt(a*a+b*b);
d=(z-cam->z);
h=-atan2(a,-b)*180/M_PI;
p=0;
r=90-atan2(d,-c)*180/M_PI;
}
a=(x-pos[0]);
b=(y-pos[1]);
c=sqrt(a*a+b*b);
d=(z-pos[3]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=90-atan2(d,-c)*180/M_PI;
}
break;
case 7: { //camara especial
float a,b;
x2=pos[0]+m[4]*5.0;
y2=pos[1]-m[0]*5.0;
z2=pos[2]-2;
a=(x-pos[0]);
b=(y-pos[1]);
h2=-atan2(a,-b)*180/M_PI;
p2=0;
r2=-90;
}
default:
break;
}
xs=(x2-x)*world->step_size*3;
ys=(y2-y)*world->step_size*3;
zs=(z2-z)*world->step_size*3;
hs=(h2-h)*world->real_step_size*5;
if(h2<-90 && h> 90) hs=((h2+360)-h)/10;
if(h2> 90 && h<-90) hs=(h2-(h+360))/10;
ps=(p2-p)*world->real_step_size*5;
if(p2<-90 && p> 90) ps=((p2+360)-p)/10;
if(p2> 90 && p<-90) ps=(p2-(p+360))/10;
rs=(r2-r)*world->real_step_size*5;
if(r2<-90 && r> 90) rs=((r2+360)-r)/10;
if(r2> 90 && r<-90) rs=(r2-(r+360))/10;
set(x+xs,y+ys,z+zs,h+hs,p+ps,r+rs);
}