/* Raydium - CQFD Corp. http://raydium.org/ License: GPL - GNU General Public License, see "gpl.txt" file. */ #ifndef DONT_INCLUDE_HEADERS #include "index.h" #else #include "headers/camera.h" #endif // res3 is GLfloat[3] void raydium_camera_vectors(GLfloat *res3) { GLfloat m[16]; GLfloat front[3]={1,0,0}; //GLfloat up[3]={0,0,1}; GLfloat res1[3]; GLfloat res2[3]; raydium_trigo_pos_get_modelview(res1); // get current position raydium_trigo_pos_to_matrix(front,m); // create matrix using front glPushMatrix(); glMultMatrixf(m); // project front raydium_trigo_pos_get_modelview(res2); // get new position glPopMatrix(); // create front vector res3[1]=-(res1[0]-res2[0]); // x res3[2]=(res1[1]-res2[1]); // y res3[0]=(res1[2]-res2[2]); // z // create up vector // fallback res3[3]=res3[4]=0; res3[5]=1; /* raydium_trigo_pos_get_modelview(res1); // get current position raydium_trigo_pos_to_matrix(up,m); // create matrix using front glPushMatrix(); glMultMatrixf(m); // project front raydium_trigo_pos_get_modelview(res2); // get new position glPopMatrix(); res3[4]=(res1[0]-res2[0]); // x res3[5]=-(res1[1]-res2[1]); // y res3[3]=-(res1[2]-res2[2]); // z */ //raydium_log("%f %f %f",res3[3],res3[4],res3[5]); } void raydium_camera_internal_prepare(void) { GLfloat x,y,z; glLoadIdentity(); if(raydium_camera_rumble_remaining>0) { x=raydium_random_f(-raydium_camera_rumble_amplitude,raydium_camera_rumble_amplitude); y=raydium_random_f(-raydium_camera_rumble_amplitude,raydium_camera_rumble_amplitude); z=raydium_random_f(-raydium_camera_rumble_amplitude,raydium_camera_rumble_amplitude); glRotatef(z,0,0,1); glRotatef(x,1,0,0); glRotatef(y,0,1,0); raydium_camera_rumble_remaining-=raydium_frame_time; raydium_camera_rumble_amplitude+=(raydium_camera_rumble_evolution*raydium_frame_time); if(raydium_camera_rumble_amplitude<=0) { raydium_camera_rumble_amplitude=0; raydium_camera_rumble_remaining=0; } } else raydium_camera_rumble_remaining=0; } void raydium_camera_internal(GLfloat x, GLfloat y, GLfloat z) { if(raydium_frame_first_camera_pass) { float pos[3]; float or[6]; pos[0]=x; pos[1]=y; pos[2]=z; if(raydium_sound) { raydium_camera_vectors(or); // get vectors raydium_sound_SetListenerPos(pos); raydium_sound_SetListenerOr(or); } if(raydium_sky_atmosphere_check()) { raydium_sky_box_render(x,y,z); raydium_sky_atmosphere_render(x,y,z,RAYDIUM_SKY_SPHERE_DEFAULT_DETAIL); } else { raydium_sky_box_render(x,y,z); } //raydium_sky_box_render(x,y,z); //raydium_atmosphere_render(x,y,z,SPHERE_DEFAULT_DETAIL); raydium_frame_first_camera_pass=0; raydium_light_update_position_all(); } if(!raydium_camera_pushed) { raydium_camera_pushed=1; raydium_camera_x=x; raydium_camera_y=y; raydium_camera_z=z; glPushMatrix(); memset(raydium_camera_cursor_place,0,3*sizeof(GLfloat)); } else raydium_log("Warning: too many calls to camera_* ! (matrix already pushed)"); } void raydium_camera_place(GLfloat x, GLfloat y, GLfloat z, GLfloat lacet, GLfloat tangage, GLfloat roulis) { //glLoadIdentity(); raydium_camera_internal_prepare(); glRotatef(roulis,0,0,1); glRotatef(tangage,1,0,0); glRotatef(lacet,0,1,0); glTranslatef(x, y, z); glRotatef(90,0,0,1); glRotatef(90,0,1,0); raydium_camera_internal(z,x,-y); } void raydium_camera_look_at(GLfloat x, GLfloat y, GLfloat z, GLfloat x_to, GLfloat y_to, GLfloat z_to) { //glLoadIdentity(); raydium_camera_internal_prepare(); glRotatef(raydium_camera_look_at_roll,0,0,1); raydium_camera_look_at_roll=0; gluLookAt(x,y,z,z_to,x_to,-y_to,0.,0.,1.); raydium_camera_internal(x,y,z); } void raydium_camera_replace(void) { if(raydium_shadow_rendering) { glLoadIdentity(); return; } if(!raydium_camera_pushed) raydium_log("Warning: no camera to replace (matrix stack's empty)"); else { glPopMatrix(); glPushMatrix(); memset(raydium_camera_cursor_place,0,3*sizeof(GLfloat)); } } void raydium_camera_replace_go(GLfloat *pos, GLfloat *R) { // pos[3], R[3*3] GLfloat matrix[16]; raydium_camera_replace(); matrix[0]=R[0]; matrix[1]=R[4]; matrix[2]=R[8]; matrix[3]=0; matrix[4]=R[1]; matrix[5]=R[5]; matrix[6]=R[9]; matrix[7]=0; matrix[8]=R[2]; matrix[9]=R[6]; matrix[10]=R[10]; matrix[11]=0; matrix[12]=pos[0]; matrix[13]=pos[1]; matrix[14]=pos[2]; matrix[15]=1; glMultMatrixf(matrix); memcpy(raydium_camera_cursor_place,pos,3*sizeof(GLfloat)); } void raydium_camera_rumble(GLfloat amplitude, GLfloat ampl_evo, GLfloat secs) { raydium_camera_rumble_amplitude=amplitude; raydium_camera_rumble_evolution=ampl_evo; raydium_camera_rumble_remaining=secs; } void raydium_camera_path_reset(void) { raydium_camera_path_reset_flag=1; } // if step is <= 0, moves will be instaneous // camera will be placed only if step is >=0 (negative steps are used // only to change internal vars) void raydium_camera_smooth(GLfloat px, GLfloat py, GLfloat pz, GLfloat lx, GLfloat ly, GLfloat lz, GLfloat zoom, GLfloat roll, GLfloat step) { static GLfloat opx,opy,opz; static GLfloat olx,oly,olz; static GLfloat ozoom=90; static GLfloat oroll=0; //raydium_log("camera smooth (asked): %.2f %.2f %.2f | %.2f %.2f %.2f | %.2f %.2f",px,py,pz,lx,ly,lz,zoom,step); if(step<=0 || // wow.. smells inf, do a instantaneous step. (and don't place cam) raydium_camera_path_reset_flag) { opx=px; opy=py; opz=pz; olx=lx; oly=ly; olz=lz; ozoom=zoom; oroll=roll; raydium_camera_path_reset_flag=0; } else { opx+=(px-opx)*step; opy+=(py-opy)*step; opz+=(pz-opz)*step; olx+=(lx-olx)*step; oly+=(ly-oly)*step; olz+=(lz-olz)*step; ozoom+=(zoom-ozoom)*step; oroll+=(roll-oroll)*step; if(ozoom<0) ozoom=0; if(ozoom>180) ozoom=270; if(ozoom!=raydium_projection_fov) { raydium_projection_fov=ozoom; raydium_window_view_update(); } } raydium_camera_look_at_roll=oroll; if(step>=0) raydium_camera_look_at(opx,opy,opz,olx,oly,olz); //raydium_log("camera smooth (result): %.2f %.2f %.2f | %.2f %.2f %.2f | %.2f | %.2f",opx,opy,opz,olx,oly,olz,ozoom,step); } void raydium_camera_path_init(int p) { int i; raydium_camera_path[p].name[0]=0; raydium_camera_path[p].steps=-1; for(i=0;i-1) return i; return -1; } int raydium_camera_path_load(char *filename) { FILE *fp; int i=0; GLfloat x,y,z,zoom,roll; int p; fp=raydium_file_fopen(filename,"rt"); if(!fp) { raydium_log("camera: cannot open camera path '%s'",filename); return -1; } for(p=0;p=0 && p=raydium_camera_path[p].steps) { step1-=raydium_camera_path[p].steps; } while(step2>=raydium_camera_path[p].steps) { step2-=raydium_camera_path[p].steps; } vx=raydium_camera_path[p].x[step2]-raydium_camera_path[p].x[step1]; vy=raydium_camera_path[p].y[step2]-raydium_camera_path[p].y[step1]; vz=raydium_camera_path[p].z[step2]-raydium_camera_path[p].z[step1]; vzoom=raydium_camera_path[p].zoom[step2]-raydium_camera_path[p].zoom[step1]; vroll=raydium_camera_path[p].roll[step2]-raydium_camera_path[p].roll[step1]; *x=raydium_camera_path[p].x[step1]+(vx*diff); *y=raydium_camera_path[p].y[step1]+(vy*diff); *z=raydium_camera_path[p].z[step1]+(vz*diff); *zoom=raydium_camera_path[p].zoom[step1]+(vzoom*diff); *roll=raydium_camera_path[p].roll[step1]+(vroll*diff); return 1; } void raydium_camera_smooth_path_to_pos(char *path, GLfloat lx, GLfloat ly, GLfloat lz, GLfloat path_step, GLfloat smooth_step) { GLfloat x,y,z,zoom,roll; if(raydium_camera_smooth_path(path,path_step,&x,&y,&z,&zoom,&roll)==-1) raydium_log("camera path error with '%s'",path); raydium_camera_smooth(x,y,z,ly,-lz,lx,zoom,roll,smooth_step); } void raydium_camera_smooth_pos_to_path(GLfloat lx, GLfloat ly, GLfloat lz, char *path, GLfloat path_step, GLfloat smooth_step) { GLfloat x,y,z,zoom,roll; if(raydium_camera_smooth_path(path,path_step,&x,&y,&z,&zoom,&roll)==-1) raydium_log("camera path error with '%s'",path); raydium_camera_smooth(lx,ly,lz,y,-z,x,zoom,roll,smooth_step); } void raydium_camera_smooth_path_to_path(char *path_from, GLfloat path_step_from, char *path_to, GLfloat path_step_to, GLfloat smooth_step) { GLfloat fx,fy,fz,fzoom,froll; GLfloat tx,ty,tz,tzoom,troll; if(raydium_camera_smooth_path(path_from,path_step_from,&fx,&fy,&fz,&fzoom,&froll)==-1) raydium_log("camera path error with '%s' (from)",path_from); if(raydium_camera_smooth_path(path_to,path_step_to,&tx,&ty,&tz,&tzoom,&troll)==-1) raydium_log("camera path error with '%s' (to)",path_to); raydium_camera_smooth(fx,fy,fz, ty,-tz,tx,fzoom,froll,smooth_step); }