00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "rSDL.h"
00033
00034 #ifdef CAMERA_LOGGING
00035 #include <iostream>
00036 #endif
00037
00038 #include "eSensor.h"
00039 #include "eCamera.h"
00040 #include "rScreen.h"
00041 #include "eGameObject.h"
00042 #include "uInputQueue.h"
00043
00044 #include "eTimer.h"
00045 #include "tConfiguration.h"
00046 #include "rSysdep.h"
00047 #include "tConsole.h"
00048 #include "ePlayer.h"
00049 #include "eAdvWall.h"
00050 #include "nConfig.h"
00051 #include "eFloor.h"
00052 #include "eGrid.h"
00053 #include "eDebugLine.h"
00054 #include "tMath.h"
00055 #include "eNetGameObject.h"
00056 #include "nObserver.h"
00057
00058 #include "eSoundMixer.h"
00059 #include "rViewport.h"
00060
00061
00062 static REAL se_hitCacheSpeed = 1;
00063
00064 static REAL se_visibilityWallDistance = .5f;
00065
00066 static REAL se_visibilitySpeed = 40;
00067 static REAL se_visibilityExtension = 1;
00068 static REAL se_visibilitySidewaysSkew = .5;
00069 static bool se_visibilityLowerWall = true;
00070 static bool se_visibilityLowerWallSmart = false;
00071
00072 static tSettingItem<REAL> se_viscs("CAMERA_VISIBILITY_RECOVERY_SPEED", se_hitCacheSpeed );
00073 static tSettingItem<REAL> se_viswd("CAMERA_VISIBILITY_WALL_DISTANCE", se_visibilityWallDistance );
00074 static tSettingItem<REAL> se_viss("CAMERA_VISIBILITY_CLIP_SPEED", se_visibilitySpeed );
00075 static tSettingItem<REAL> se_vise("CAMERA_VISIBILITY_EXTENSION", se_visibilityExtension );
00076 static tSettingItem<REAL> se_vissk("CAMERA_VISIBILITY_SIDESKEW", se_visibilitySidewaysSkew );
00077 static tSettingItem<bool> se_vislw("CAMERA_VISIBILITY_LOWER_WALL", se_visibilityLowerWall );
00078 static tSettingItem<bool> se_vislws("CAMERA_VISIBILITY_LOWER_WALL_SMART", se_visibilityLowerWallSmart );
00079
00080
00081
00082
00083
00084 static bool forbid_camera[CAMERA_COUNT];
00085
00086 class eInitForbidCamera
00087 {
00088 public:
00089 eInitForbidCamera()
00090 {
00091
00092 for ( int i = CAMERA_COUNT-1; i>=0; --i )
00093 {
00094 forbid_camera[i] = false;
00095 }
00096
00097
00098 forbid_camera[ CAMERA_SERVER_CUSTOM ] = true;
00099 }
00100 };
00101 static eInitForbidCamera se_initForbid;
00102
00103
00104 static nSettingItem<bool> a_s
00105 ("CAMERA_FORBID_SMART",
00106 forbid_camera[CAMERA_SMART]);
00107
00108
00109 static nSettingItem<bool> a_i
00110 ("CAMERA_FORBID_IN",
00111 forbid_camera[CAMERA_IN]);
00112
00113
00114 static nSettingItem<bool> a_c
00115 ("CAMERA_FORBID_CUSTOM",
00116 forbid_camera[CAMERA_CUSTOM]);
00117
00118
00119 static nSettingItem<bool> a_sc
00120 ("CAMERA_FORBID_SERVER_CUSTOM",
00121 forbid_camera[CAMERA_SERVER_CUSTOM]);
00122
00123
00124 static nSettingItem<bool> a_f
00125 ("CAMERA_FORBID_FREE",
00126 forbid_camera[CAMERA_FREE]);
00127
00128
00129 static nSettingItem<bool> a_fe
00130 ("CAMERA_FORBID_FOLLOW",
00131 forbid_camera[CAMERA_FOLLOW]);
00132
00133
00134 static nSettingItem<bool> a_ffe
00135 ("CAMERA_FORBID_MER",
00136 forbid_camera[CAMERA_MER]);
00137
00138 #ifndef DEDICATED
00139 #include "rGL.h"
00140 #endif
00141
00142 static REAL lastTime=0;
00143 static const REAL rimDistance = 0.01f;
00144 static const REAL rimDistanceHeight = 0.1f;
00145
00146 REAL se_cameraRise=0;
00147 REAL se_cameraZ=10;
00148
00149
00150
00151 uActionCamera eCamera::se_moveBack("MOVE_BACK",
00152 -10,
00153 uAction::uINPUT_ANALOG);
00154
00155 uActionCamera eCamera::se_moveForward("MOVE_FORWARD",
00156 -20,
00157 uAction::uINPUT_ANALOG);
00158
00159 uActionCamera eCamera::se_moveDown("MOVE_DOWN",
00160 -30,
00161 uAction::uINPUT_ANALOG);
00162
00163 uActionCamera eCamera::se_moveUp("MOVE_UP",
00164 -40,
00165 uAction::uINPUT_ANALOG);
00166
00167
00168 uActionCamera eCamera::se_moveRight("MOVE_RIGHT",
00169 -50,
00170 uAction::uINPUT_ANALOG);
00171
00172 uActionCamera eCamera::se_moveLeft("MOVE_LEFT",
00173 -60,
00174 uAction::uINPUT_ANALOG);
00175
00176 uActionCamera eCamera::se_zoomOut("ZOOM_OUT",
00177 -70,
00178 uAction::uINPUT_ANALOG);
00179
00180 uActionCamera eCamera::se_zoomIn("ZOOM_IN",
00181 -80,
00182 uAction::uINPUT_ANALOG);
00183
00184
00185 class uGlanceAction : public uActionCamera {
00186 public:
00187 eCoord const relDir;
00188 uGlanceAction(char const * name, int priority, eCoord const relativeDirection)
00189 : uActionCamera(name, priority), relDir(relativeDirection) {}
00190 };
00191
00192 uGlanceAction eCamera::se_glance[eCamera::se_glances] = {
00193 uGlanceAction("GLANCE_FORWARD",-85,eCoord(1,0)),
00194 uGlanceAction("GLANCE_BACK",-90,eCoord(-1,0)),
00195 uGlanceAction("GLANCE_RIGHT",-100,eCoord(0,-1)),
00196 uGlanceAction("GLANCE_LEFT",-110,eCoord(0,1))
00197 };
00198
00199
00200
00201 uActionCamera eCamera::se_lookDown("BANK_DOWN",
00202 -120,
00203 uAction::uINPUT_ANALOG);
00204
00205 uActionCamera eCamera::se_lookUp("BANK_UP",
00206 -130,
00207 uAction::uINPUT_ANALOG);
00208
00209 uActionCamera eCamera::se_lookRight("LOOK_RIGHT",
00210 -140,
00211 uAction::uINPUT_ANALOG);
00212
00213 uActionCamera eCamera::se_lookLeft("LOOK_LEFT",
00214 -150,
00215 uAction::uINPUT_ANALOG);
00216
00217
00218 uActionCamera eCamera::se_switchView("SWITCH_VIEW", -160);
00219
00220
00221 static REAL s_startFollowX = -30, s_startFollowY = -30, s_startFollowZ = 80;
00222 static REAL s_startSmartX = 10, s_startSmartY = 30, s_startSmartZ = 2;
00223 static REAL s_startFreeX = 10, s_startFreeY = -70, s_startFreeZ = 100;
00224
00225 static tSettingItem<REAL> s_foX("CAMERA_FOLLOW_START_X", s_startFollowX);
00226 static tSettingItem<REAL> s_smX("CAMERA_SMART_START_X", s_startSmartX);
00227 static tSettingItem<REAL> s_frX("CAMERA_FREE_START_X", s_startFreeX);
00228
00229 static tSettingItem<REAL> s_foY("CAMERA_FOLLOW_START_Y", s_startFollowY);
00230 static tSettingItem<REAL> s_smY("CAMERA_SMART_START_Y", s_startSmartY);
00231 static tSettingItem<REAL> s_frY("CAMERA_FREE_START_Y", s_startFreeY);
00232
00233 static tSettingItem<REAL> s_foZ("CAMERA_FOLLOW_START_Z", s_startFollowZ);
00234 static tSettingItem<REAL> s_smZ("CAMERA_SMART_START_Z", s_startSmartZ);
00235 static tSettingItem<REAL> s_frZ("CAMERA_FREE_START_Z", s_startFreeZ);
00236
00237
00238 static REAL s_customBack = 30, s_customRise = 20, s_customBackSpeed = 0, s_customRiseSpeed = 0 , s_customPitch = -.7, s_customZoom = 0.5, s_customTurnSpeed=40, s_customTurnSpeed180 = 2;
00239 static REAL s_serverCustomBack = 30, s_serverCustomRise = 20, s_serverCustomBackSpeed = 0, s_serverCustomRiseSpeed = 0, s_serverCustomPitch = -.7, s_serverCustomTurnSpeed=-1, s_serverCustomTurnSpeed180 = 2;
00240
00241 static tSettingItem<REAL> s_iBack("CAMERA_CUSTOM_BACK", s_customBack);
00242 static tSettingItem<REAL> s_iRise("CAMERA_CUSTOM_RISE", s_customRise);
00243 static tSettingItem<REAL> s_iBackSpeed("CAMERA_CUSTOM_BACK_FROMSPEED", s_customBackSpeed);
00244 static tSettingItem<REAL> s_iRiseSpeed("CAMERA_CUSTOM_RISE_FROMSPEED", s_customRiseSpeed);
00245 static tSettingItem<REAL> s_iPitch("CAMERA_CUSTOM_PITCH", s_customPitch);
00246 static tSettingItem<REAL> s_iZoom("CAMERA_CUSTOM_ZOOM", s_customZoom);
00247 static tSettingItem<REAL> s_iCustomTurnSpeed("CAMERA_CUSTOM_TURN_SPEED", s_customTurnSpeed);
00248 static tSettingItem<REAL> s_iCustomTurnSpeed180("CAMERA_CUSTOM_TURN_SPEED_180", s_customTurnSpeed180);
00249
00250 static nSettingItem<REAL> s_iSBack("CAMERA_SERVER_CUSTOM_BACK", s_serverCustomBack);
00251 static nSettingItem<REAL> s_iSRise("CAMERA_SERVER_CUSTOM_RISE", s_serverCustomRise);
00252 static nSettingItem<REAL> s_iSBackSpeed("CAMERA_SERVER_CUSTOM_BACK_FROMSPEED", s_serverCustomBackSpeed);
00253 static nSettingItem<REAL> s_iSRiseSpeed("CAMERA_SERVER_CUSTOM_RISE_FROMSPEED", s_serverCustomRiseSpeed);
00254 static nSettingItem<REAL> s_iSPitch("CAMERA_SERVER_CUSTOM_PITCH", s_serverCustomPitch);
00255 static nSettingItem<REAL> s_iSCustomTurnSpeed("CAMERA_SERVER_CUSTOM_TURN_SPEED", s_serverCustomTurnSpeed);
00256 static nSettingItem<REAL> s_iSCustomTurnSpeed180("CAMERA_SERVER_CUSTOM_TURN_SPEED_180", s_serverCustomTurnSpeed180);
00257
00258
00259 static REAL mercamxydist = 20;
00260 static REAL mercamz = 16;
00261
00262 static tSettingItem<REAL> s_mercamxydist("CAMERA_MER_XYDIST",mercamxydist);
00263 static tSettingItem<REAL> s_mercamz("CAMERA_MER_Z",mercamz);
00264
00265
00266 static int glanceMode = 2;
00267 static REAL glanceAngularVelocity = 4*M_PI;
00268 static REAL glanceAngularVelocityBonus = 12.;
00269 static REAL smartcamGlancingBack = 20;
00270 static REAL smartcamGlancingHeight = 10;
00271
00272 static tSettingItem<int> s_glanceMode("CAMERA_GLANCE_MODE",glanceMode);
00273 static tSettingItem<REAL> s_glanceRotSpeed("CAMERA_GLANCE_ANGULAR_VELOCITY",glanceAngularVelocity);
00274 static tSettingItem<REAL> s_glanceRotSpeedBonus("CAMERA_GLANCE_ANGULAR_VELOCITY_BONUS",glanceAngularVelocityBonus);
00275 static tSettingItem<REAL> s_smartcamGlanceBack("CAMERA_SMART_GLANCING_BACK",smartcamGlancingBack);
00276 static tSettingItem<REAL> s_smartcamGlanceHeight("CAMERA_SMART_GLANCING_HEIGHT",smartcamGlancingHeight);
00277
00278
00279 static REAL s_inTurnSpeed=40;
00280 static tSettingItem<REAL> s_iInTurnSpeed("CAMERA_IN_TURN_SPEED", s_inTurnSpeed);
00281
00282 bool eCamera::InterestingToWatch(eGameObject const *g){
00283 return g &&
00284 (g->Alive() ||
00285 (lastTime - g->deathTime<1));
00286 }
00287
00288
00293 inline REAL robust_acos(REAL arg) {
00294 if (arg>=1)
00295 return 0;
00296 else if (arg<=-1)
00297 return M_PI;
00298 else
00299 return acos(arg);
00300 }
00301
00302
00303 eCoord eCamera::nextDirIfGlancing(eCoord const & dir, eCoord const & targetDir, REAL ts) {
00304
00305 switch (glanceMode) {
00306 case 0: {
00307
00308 REAL d = dir*targetDir;
00309 REAL arc = glanceAngularVelocity*ts;
00310 if (fabs(d)<arc && eCoord::F(dir,targetDir)>0) {
00311 return targetDir;
00312 } else {
00313 eCoord newdir = dir.Turn(1,(d>0) ? -arc : arc);
00314 newdir.Normalize();
00315 return newdir;
00316 }
00317 break;
00318 } case 1: {
00319
00320
00321 REAL arc = robust_acos(eCoord::F(dir,targetDir)) * ts * glanceAngularVelocity / (M_PI_2);
00322 if (dir*targetDir>0)
00323 arc=-arc;
00324 return dir.Turn(cos(arc),sin(arc));
00325 } case 2: {
00326
00327
00328 REAL arc = glanceAngularVelocity*ts;
00329 eCoord newdir;
00330 if (eCoord::F(dir,targetDir)>0) {
00331 newdir = dir+targetDir*arc;
00332 } else if (dir*targetDir>0) {
00333 newdir = dir.Turn(1,-arc*glanceAngularVelocityBonus);
00334 } else {
00335 newdir = dir.Turn(1,arc*glanceAngularVelocityBonus);
00336 }
00337 newdir.Normalize();
00338 return newdir;
00339 } default:
00340 return targetDir;
00341 }
00342 }
00343
00344
00345
00346 static nObserverPtr< ePlayerNetID > se_watchedPlayer[ MAX_PLAYERS ];
00347
00348
00349 static nObserverPtr< ePlayerNetID > & se_GetWatchedPlayer( eCamera * cam )
00350 {
00351 static nObserverPtr< ePlayerNetID > dummy;
00352
00353 ePlayer const * localPlayer = cam->LocalPlayer();
00354 if ( !localPlayer )
00355 return dummy;
00356
00357 return se_watchedPlayer[ localPlayer->ID() ];
00358 }
00359
00360
00361 static eGameObject * se_GetWatchedObject( eCamera * cam )
00362 {
00363 ePlayerNetID const * player = se_GetWatchedPlayer( cam );
00364 if ( player )
00365 return player->Object();
00366
00367 return NULL;
00368 }
00369
00370 static void se_SetWatchedObject( eCamera * cam, eGameObject * obj )
00371 {
00372 nObserverPtr< ePlayerNetID > & player = se_GetWatchedPlayer( cam );
00373
00374
00375 if ( !player || ( player->Object() && player->Object()->Alive() ) )
00376 {
00377
00378 for ( int i = se_PlayerNetIDs.Len()-1; i>=0; --i )
00379 {
00380 ePlayerNetID * p = se_PlayerNetIDs(i);
00381 if ( p->Object() == obj )
00382 player = p;
00383 }
00384 }
00385 }
00386
00387 void eCamera::MyInit(){
00388 if (localPlayer){
00389 mode=localPlayer->startCamera;
00390 fov=localPlayer->startFOV;
00391 }
00392
00393
00394 if (bool(netPlayer) && !center)
00395 {
00396 center = netPlayer->Object();
00397 }
00398 else if ( grid->gameObjectsInteresting.Len() > 0 )
00399 {
00400
00401 center = grid->gameObjectsInteresting[0];
00402 }
00403
00404
00405 if (forbid_camera[mode] && bool(netPlayer) && netPlayer->Object()==Center())
00406 SwitchView();
00407
00408 centerPos=eCoord(100,100);
00409 centerSpeedSmooth=0;
00410 if ( Center() )
00411 {
00412 centerPos = Center()->PredictPosition();
00413 centerSpeedSmooth = Center()->Speed();
00414 }
00415
00416 pos=CenterPos();
00417 dir=CenterDir();
00418 centerPosSmooth=pos;
00419 centerDirLast=centerDirSmooth=dir;
00420 lastPos=pos;
00421 zNear=0.1f;
00422
00423 distance=0;
00424 lastrendertime=se_GameTime();
00425 grid->cameras.Add(this,id);
00426
00427 smoothTurning=turning=0;
00428 centerPosLast=centerposLast=CenterPos();
00429 userCameraControl=0;
00430 centerIncam=1;
00431 smartcamSkewSmooth=0;
00432 smartcamIncamSmooth=1;
00433 smartcamFrontSmooth=0;
00434
00435 for(int i = hitCacheSize-1; i>=0; --i)
00436 hitCache_[i] = 1;
00437
00438 switch (mode){
00439 case CAMERA_CUSTOM:
00440 case CAMERA_SERVER_CUSTOM:
00441 case CAMERA_IN:
00442 z=10;
00443 rise=0;
00444 break;
00445 case CAMERA_FOLLOW:
00446 pos=pos+dir.Turn(eCoord(s_startFollowX,s_startFollowY)) ;
00447 z=s_startFollowZ;
00448 break;
00449 case CAMERA_SMART:
00450 pos=pos+dir.Turn(eCoord(s_startSmartX,s_startSmartY)) ;
00451 z=s_startSmartZ;
00452 break;
00453 case CAMERA_FREE:
00454 pos=pos+dir.Turn(eCoord(s_startFreeX,s_startFreeY)) ;
00455 z=s_startFreeZ;
00456 break;
00457 case CAMERA_MER:
00458 pos=pos-dir*mercamxydist;
00459 z=CenterZ();
00460 rise=0;
00461 break;
00462 case CAMERA_SMART_IN:
00463 case CAMERA_COUNT:
00464 break;
00465 }
00466
00467 if ( mode != CAMERA_IN && mode != CAMERA_CUSTOM && mode != CAMERA_SERVER_CUSTOM ){
00468 dir=CenterPos()-pos;
00469 REAL dist=REAL(sqrt(dir.NormSquared()));
00470 if (dist<.001) dist=1;
00471 dir=dir*(1/dist);
00472 rise=(CenterZ()-z)/dist;
00473 }
00474
00475 activeGlanceRequest=NULL;
00476
00477 lastSwitch=-100;
00478 }
00479
00480 const ePlayerNetID* eCamera::Player() const { return netPlayer; }
00481 const ePlayer* eCamera::LocalPlayer() const { return localPlayer; }
00482
00483 eCamera::eCamera(eGrid *g, rViewport *view,ePlayerNetID *p,
00484 ePlayer *lp,eCamMode m)
00485 :id(-1),grid(g),netPlayer(p),localPlayer(lp),
00486
00487 mode(m),pos(0,0),dir(1,0),top(0,0),
00488 vp(view){
00489
00490
00491
00492
00493 MyInit();
00494 }
00495
00496
00497
00498
00499 eCamera::~eCamera(){
00500
00501
00502
00503
00504
00505
00506 grid->cameras.Remove(this, id);
00507
00508 tCHECK_DEST;
00509 }
00510
00511
00512
00513
00514 eGameObject * eCamera::Center() const{
00515 return center;
00516 }
00517
00518 void eCamera::SwitchView(){
00519 zNear = 0.01f;
00520
00521 int count=CAMERA_COUNT * 2;
00522
00523 userCameraControl = 0;
00524
00525
00526
00527 bool imp=true,global_imp=true,both_imp=true;
00528 for (int i=CAMERA_COUNT-1;i>=0;i--){
00529 if (!localPlayer || localPlayer->allowCam[i])
00530 imp=false;
00531 if (!forbid_camera[i] || !netPlayer || netPlayer->Object()!=Center())
00532 global_imp=false;
00533 if ((!forbid_camera[i] || !netPlayer || netPlayer->Object()!=Center())
00534 && (!localPlayer || localPlayer->allowCam[i]))
00535 both_imp=false;
00536 }
00537
00538 if (imp) con << "impossible to meet your needs.\n";
00539 if (global_imp) con << "impossible to meet global needs.\n";
00540 if (both_imp) con << "impossible to meet both needs.\n";
00541
00542 if (both_imp && !global_imp)
00543 imp=true;
00544
00545 do{
00546
00547 int m = mode;
00548 m--;
00549 if ( m<0 )
00550 m = CAMERA_SERVER_CUSTOM;
00551 mode = static_cast< eCamMode >( m );
00552
00553 count--;
00554 }
00555 while ((!imp && count > CAMERA_COUNT && localPlayer && !localPlayer->allowCam[mode])
00556 || (count >0 && !global_imp && forbid_camera[mode] &&
00557 (bool( netPlayer ) && netPlayer->Object()==Center())));
00558
00559 if ( mode == CAMERA_IN || mode == CAMERA_CUSTOM || mode == CAMERA_SERVER_CUSTOM )
00560 rise=0;
00561
00562 if(mode==CAMERA_SMART){
00563 smartcamIncamSmooth=1;
00564 z=z+1;
00565 pos=pos+dir.Turn(-1,.1);
00566 }
00567 }
00568
00569 bool eCamera::Act(uActionCamera *Act,REAL x){
00570 eCoord objdir=CenterCamDir();
00571
00572 int turn=0;
00573 if (eGameObject::se_turnLeft==*reinterpret_cast<uActionPlayer *>(Act)){
00574 turn=-1;
00575 }
00576 if (eGameObject::se_turnRight==*reinterpret_cast<uActionPlayer *>(Act)){
00577 turn=1;
00578 }
00579
00580 if (turn){
00581 eGameObject *cent=NULL;
00582 if (se_GameTime() <= 0 )
00583 turning+=.5;
00584 if (netPlayer) cent=netPlayer->Object();
00585 if (!InterestingToWatch(cent) && x>0)
00586 {
00587 SwitchCenter(turn);
00588 se_SetWatchedObject( this, center );
00589 }
00590 }
00591
00592 REAL ll=0,lu=0,ml=0,mf=0,mu=0,zi=1;
00593
00594 if (se_lookLeft==*Act && x>0)
00595 ll=x;
00596 else if (se_lookRight==*Act && x>0)
00597 ll=-x;
00598 else if (se_lookUp==*Act && x>0)
00599 lu=x;
00600 else if (se_lookDown==*Act && x>0)
00601 lu=-x;
00602 else if (se_zoomIn==*Act && x>0)
00603 zi*=1+zi*.1;
00604 else if (se_zoomOut==*Act && x>0)
00605 zi/=1+zi*.1;
00606
00607 else if (se_moveLeft==*Act && x>0)
00608 ml=x;
00609 else if (se_moveRight==*Act && x>0)
00610 ml=-x;
00611 else if (se_moveForward==*Act && x>0)
00612 mf=x;
00613 else if (se_moveBack==*Act && x>0)
00614 mf=-x;
00615 else if (se_moveUp==*Act && x>0)
00616 mu=x;
00617 else if (se_moveDown==*Act && x>0)
00618 mu=-x;
00619 else if (se_switchView==*Act && x>0)
00620 SwitchView();
00621 else if (se_glance<=Act && Act < se_glance+se_glances) {
00622 uGlanceAction* ga = static_cast<uGlanceAction*>(Act);
00623 eGlanceRequest* gr = &glanceRequests[ga-se_glance];
00624 if (x>0) {
00625 eCoord baseDir = grid->GetDirection(grid->DirectionWinding(dir));
00626 gr->dir = baseDir.Turn(ga->relDir);
00627 gr->Insert(activeGlanceRequest);
00628 } else {
00629 gr->Remove();
00630 }
00631 } else
00632 return false;
00633
00634
00635 userCameraControl+=sqrt(ll*ll+lu*lu+(1-zi)*(1-zi)+ml*ml+mf*mf+mu*mu)/20;
00636
00637 switch(mode){
00638 case CAMERA_IN:
00639 case CAMERA_SMART_IN:
00640 lu+=mu*2;
00641 ll+=ml;
00642 mu=ml=0;
00643 break;
00644 case CAMERA_CUSTOM:
00645 case CAMERA_SERVER_CUSTOM:
00646 case CAMERA_FREE:
00647 break;
00648 case CAMERA_FOLLOW:
00649 case CAMERA_SMART:
00650 case CAMERA_MER:
00651 mu-=lu;
00652 ml-=ll;
00653 lu=ll=0;
00654 break;
00655 case CAMERA_COUNT:
00656 break;
00657 }
00658
00659
00660 dir=dir+dir.Turn(eCoord(0,ll*.2));
00661 rise+=lu/80;
00662 z+=mu*.25;
00663 pos=pos+dir*mf*.25+dir.Turn(eCoord(0,ml*.25));
00664
00665 fov/=zi;
00666 if (fov>120) fov=120;
00667
00668 if (fov<30) fov=30;
00669
00670
00671 switch(mode){
00672 case CAMERA_IN:
00673 case CAMERA_SMART_IN:
00674 {
00675 int x=3;
00676 while (eCoord::F(dir,objdir)<-.51 && x>0){
00677 dir=dir-objdir*(eCoord::F(dir,objdir)+.5);
00678 dir=dir*(1/sqrt(dir.NormSquared()));
00679 x--;
00680 }
00681 }
00682 break;
00683 case CAMERA_CUSTOM:
00684 case CAMERA_SERVER_CUSTOM:
00685 case CAMERA_FREE:
00686 case CAMERA_FOLLOW:
00687 case CAMERA_SMART:
00688 case CAMERA_MER:
00689 break;
00690 case CAMERA_COUNT:
00691 break;
00692 }
00693
00694 Bound(0);
00695
00696 return true;
00697 }
00698
00699 extern REAL upper_height,lower_height;
00700
00701 static bool se_ClampCamera( eCamMode mode )
00702 {
00703 return !(mode == CAMERA_SMART && se_GameTime() > -.5 ? se_visibilityLowerWallSmart : se_visibilityLowerWall);
00704 }
00705
00707 class eCameraSensor: public eSensor
00708 {
00709 public:
00711 eCameraSensor(eGameObject *o,eCoord & camera, const eCoord & target )
00712 :eSensor(o,o->Position(),camera-target), moved_(false),
00713 camPos_(camera), target_(target), zLimit_(2), ratio_(0), camera_(0), lowerWall_( true )
00714 {
00715 #ifdef DEBUG_VISIBILITY_TARGETS
00716 eDebugLine::SetColor( 1,1,1 );
00717 eDebugLine::SetTimeout(.005);
00718 eDebugLine::Draw( target, 0, target, 2 );
00719 #endif
00720 Move( target,0,0 );
00721
00722 }
00723
00725 struct Correction
00726 {
00727 eCoord correctTo;
00728 REAL distance;
00729
00731 void Improve( eCoord correctTo, REAL distance )
00732 {
00733 if ( this->distance > distance )
00734 {
00735 this->distance = distance;
00736 this->correctTo = correctTo;
00737 }
00738 }
00739 };
00740
00749 void LookAround( eWall const * w, int direction, Correction & correction, REAL heightLimit, int recursion, int hardRecursion )
00750 {
00751
00752 if ( recursion < 0 || hardRecursion < 0 )
00753 return;
00754
00755 static int count = 0;
00756 count ++;
00757 if ( count == 35390 )
00758 st_Breakpoint();
00759
00760
00761 if ( lowerWall_ )
00762 {
00763 w->BlocksCamera( camera_, heightLimit );
00764 }
00765
00766
00767 if ( !w || !w->Edge() || !w->Edge()->Other() )
00768 return;
00769
00770
00771
00772 eHalfEdge const * edge = (direction == 0 ? w->Edge() : w->Edge()->Other());
00773 eCoord const & p1 = *edge->Point();
00774 eCoord const & p2 = *edge->Other()->Point();
00775
00776
00777
00778
00779 if ( !lowerWall_ && eCoord::F( camPos_ - p1, target_ - p1 ) > 0 )
00780 return;
00781
00782
00783 eCoord diff = target_ - p1;
00784 diff.Normalize();
00785 eCoord normal = diff.Turn(0,-1);
00786
00787
00788 REAL sideOther=eCoord::F(normal,p2-p1);
00789
00790
00791 {
00792 bool wallContinues = false;
00793 eHalfEdge const * run = edge;
00794 do
00795 {
00796 run = run->Other();
00797 if (run)
00798 run = run->Next();
00799
00800 if (!run || !run->Other() || run == edge)
00801 break;
00802
00803 if ( run->GetWall() || run->Other()->GetWall() )
00804 {
00805
00806 eCoord const & p3 = *run->Other()->Point();
00807
00808
00809 REAL side3=eCoord::F(normal,p3-p1);
00810
00811
00812
00813 if ( side3 * sideOther < 0 )
00814 {
00815 wallContinues = true;
00816
00817
00818 int recursion2 = recursion;
00819 if ( fabs( (p2 - p1)*(p1 - p3) ) >= 10 * EPS * sqrt( (p1-p2).NormSquared() * (p1-p3).NormSquared() ) )
00820 recursion2--;
00821
00822
00823 if ( run->GetWall() )
00824 LookAround( run->GetWall(), 1, correction, heightLimit, recursion2, hardRecursion-1 );
00825 else if ( run->Other()->GetWall() )
00826 LookAround( run->Other()->GetWall(), 0, correction, heightLimit, recursion2, hardRecursion-1 );
00827 }
00828 }
00829 }
00830 while ( true );
00831
00832
00833 if ( wallContinues )
00834 return;
00835 }
00836
00837
00838 REAL side=eCoord::F(normal,camPos_-p1) * (1-ratio_);
00839 correction.Improve( camPos_ - normal * side, fabs( side ) );
00840 }
00841
00847 virtual void PassEdge(const eWall *w,REAL time,REAL alpha,int)
00848 {
00849
00850 REAL objectZ = 1.5;
00851 if ( camera_ )
00852 objectZ = camera_->CenterCamZ() * 2;
00853 REAL heightLimit = ( .5 * zLimit_ * time + objectZ * ( 1 - time ) );
00854
00855
00856 if ( moved_ || !w || !owned->EdgeIsDangerous(w, time, alpha) || w->Height() <= heightLimit )
00857 return;
00858
00859 heightLimit *= .5f;
00860
00861
00862
00863 eCoord const & p1 = w->EndPoint(0);
00864 eCoord const & p2 = w->EndPoint(1);
00865
00866
00867 eCoord diff=p2-p1;
00868 diff=diff*(1/w->Len());
00869 eCoord normal=diff.Turn(0,-1);
00870
00871
00872 REAL side=eCoord::F(normal,camPos_-p1);
00873
00874
00875 Correction correction;
00876 correction.distance = fabs( side ) * 10;
00877 correction.correctTo = camPos_ - normal*(side);
00878
00879
00880 int recursion = lowerWall_? 0 : 2;
00881 LookAround( w, 0, correction, heightLimit, recursion, 1000 );
00882 LookAround( w, 1, correction, heightLimit, recursion, 1000 );
00883
00884
00885 if ( !lowerWall_ )
00886 {
00887 moved_ = correction.distance > .001f;
00888 camPos_ = correction.correctTo;
00889 }
00890 }
00891 bool moved_;
00892
00893 inline eCameraSensor & SetZLimit( REAL const & zLimit );
00894 inline REAL const & GetZLimit( void ) const;
00895 inline eCameraSensor const & GetZLimit( REAL & zLimit ) const;
00896 inline eCameraSensor & SetRatio( REAL const & ratio );
00897 inline REAL const & GetRatio( void ) const;
00898 inline eCameraSensor const & GetRatio( REAL & ratio ) const;
00899 inline eCameraSensor & SetCamera( eCamera * camera );
00900 inline eCamera * GetCamera( void ) const;
00901 inline eCameraSensor const & GetCamera( eCamera * & camera ) const;
00902 inline eCameraSensor & SetLowerWall( bool const & lowerWall );
00903 inline bool const & GetLowerWall( void ) const;
00904 inline eCameraSensor const & GetLowerWall( bool & lowerWall ) const;
00905 private:
00906 eCoord & camPos_;
00907 eCoord target_;
00908 REAL zLimit_;
00909 REAL ratio_;
00910 eCamera * camera_;
00911 bool lowerWall_;
00912 };
00913
00914
00915
00916
00917
00918
00922
00923
00924 REAL const & eCameraSensor::GetZLimit( void ) const
00925 {
00926 return this->zLimit_;
00927 }
00928
00929
00930
00931
00932
00933
00938
00939
00940 eCameraSensor const & eCameraSensor::GetZLimit( REAL & zLimit ) const
00941 {
00942 zLimit = this->zLimit_;
00943 return *this;
00944 }
00945
00946
00947
00948
00949
00950
00955
00956
00957 eCameraSensor & eCameraSensor::SetZLimit( REAL const & zLimit )
00958 {
00959 this->zLimit_ = zLimit;
00960 return *this;
00961 }
00962
00963
00964
00965
00966
00967
00971
00972
00973 REAL const & eCameraSensor::GetRatio( void ) const
00974 {
00975 return this->ratio_;
00976 }
00977
00978
00979
00980
00981
00982
00987
00988
00989 eCameraSensor const & eCameraSensor::GetRatio( REAL & ratio ) const
00990 {
00991 ratio = this->ratio_;
00992 return *this;
00993 }
00994
00995
00996
00997
00998
00999
01004
01005
01006 eCameraSensor & eCameraSensor::SetRatio( REAL const & ratio )
01007 {
01008 this->ratio_ = ratio;
01009 return *this;
01010 }
01011
01012
01013
01014
01015
01016
01020
01021
01022 eCamera * eCameraSensor::GetCamera( void ) const
01023 {
01024 return this->camera_;
01025 }
01026
01027
01028
01029
01030
01031
01036
01037
01038 eCameraSensor const & eCameraSensor::GetCamera( eCamera * & camera ) const
01039 {
01040 camera = this->camera_;
01041 return *this;
01042 }
01043
01044
01045
01046
01047
01048
01053
01054
01055 eCameraSensor & eCameraSensor::SetCamera( eCamera * camera )
01056 {
01057 this->camera_ = camera;
01058 return *this;
01059 }
01060
01061
01062
01063
01064
01065
01069
01070
01071 bool const & eCameraSensor::GetLowerWall( void ) const
01072 {
01073 return this->lowerWall_;
01074 }
01075
01076
01077
01078
01079
01080
01085
01086
01087 eCameraSensor const & eCameraSensor::GetLowerWall( bool & lowerWall ) const
01088 {
01089 lowerWall = this->lowerWall_;
01090 return *this;
01091 }
01092
01093
01094
01095
01096
01097
01102
01103
01104 eCameraSensor & eCameraSensor::SetLowerWall( bool const & lowerWall )
01105 {
01106 this->lowerWall_ = lowerWall;
01107 return *this;
01108 }
01109
01110
01111
01112
01113
01114
01115
01119
01120
01121 void eCamera::Bound( REAL dt )
01122 {
01123 Bound( dt, pos );
01124 }
01125
01126
01127
01128
01129
01130
01140
01141
01142 bool eCamera::Bound( REAL ratio, eCoord & pos, eCoord const & dirFromTarget, REAL & hitCache )
01143 {
01144
01145 eCoord target = CenterPos();
01146
01147
01148 if ( dirFromTarget.NormSquared() > 0.0001f )
01149 {
01150 eSensor test( Center(), target, dirFromTarget );
01151 test.detect( hitCache );
01152 target = test.before_hit * (1-se_visibilityWallDistance) + target * se_visibilityWallDistance;
01153 hitCache = test.hit;
01154 }
01155
01156
01157 eCameraSensor toObject( Center(), pos, target );
01158 toObject.SetZLimit( z ).SetRatio( ratio ).SetCamera( this );
01159
01160
01161
01162
01163 if (!activeGlanceRequest)
01164 {
01165 toObject.SetLowerWall( !se_ClampCamera(mode) );
01166
01167
01168 if ( !toObject.GetLowerWall() )
01169 {
01170 REAL offset = rimDistance + rimDistanceHeight * z;
01171 eWallRim::Bound(pos,offset);
01172 }
01173 }
01174
01175
01176 toObject.detect( 1 );
01177
01178 return toObject.moved_;
01179 }
01180
01181
01182
01183
01184
01185
01190
01191
01192 void eCamera::Bound( REAL dt, eCoord & pos )
01193 {
01194
01195 if (z<.1)
01196 z=.1;
01197
01198
01199 if(mode!=CAMERA_IN && mode !=CAMERA_SMART_IN )
01200 {
01201
01202 if ( Center() )
01203 {
01204
01205 REAL smoothBound = 1/(1+se_visibilitySpeed*dt);
01206 eCoord direction = centerDirSmooth;
01207
01208
01209 direction.Normalize();
01210
01211
01212 Bound( smoothBound, pos, direction * ( CenterSpeed() * se_visibilityExtension ), hitCache_[0] );
01213
01214
01215
01216
01217
01218 int timeout = 4;
01219 bool goon = true;
01220 while (goon && timeout > 0)
01221 {
01222 --timeout;
01223 goon = false;
01224
01225 REAL cache = 1;
01226 if ( Bound( 0, pos, eCoord(0,0), cache ) )
01227 {
01228 goon = true;
01229 break;
01230 }
01231 }
01232 }
01233 }
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 }
01244
01245 bool eCamera::CenterIncamOnTurn(){
01246 if (localPlayer)
01247 return localPlayer->centerIncamOnTurn;
01248 else
01249 return false;
01250 }
01251 bool eCamera::WhobbleIncam(){
01252 if (localPlayer)
01253 return localPlayer->wobbleIncam;
01254 else
01255 return false;
01256 }
01257 bool eCamera::AutoSwitchIncam(){
01258 if (localPlayer)
01259 return localPlayer->autoSwitchIncam;
01260 else
01261 return false;
01262 }
01263
01264 static inline void makefinite(REAL &x,REAL y=2){if (!finite(x)) x=y;}
01265 static inline void makefinite(eCoord &x){makefinite(x.x);makefinite(x.y);}
01266
01267
01268
01269
01270 static REAL se_cameraSmartDistanceScale = .2;
01271 static tSettingItem< REAL > se_confCameraSmartDistanceScale( "CAMERA_SMART_DISTANCESCALE", se_cameraSmartDistanceScale );
01272
01273
01274 static REAL se_cameraSmartMinDistanceScale = 5.0;
01275 static tSettingItem< REAL > se_confCameraSmartMinDistanceScale( "CAMERA_SMART_MIN_DISTANCESCALE", se_cameraSmartMinDistanceScale );
01276
01277
01278 static REAL se_cameraSmartMinDistance = 10.0;
01279 static tSettingItem< REAL > se_confCameraSmartMinDistance( "CAMERA_SMART_MIN_DISTANCE", se_cameraSmartMinDistance );
01280
01281
01282 static REAL se_cameraSmartCycleSpeed = 20.0;
01283 static tSettingItem< REAL > se_confCameraSmartCycleSpeed( "CAMERA_SMART_CYCLESPEED", se_cameraSmartCycleSpeed );
01284
01285
01286 static REAL se_cameraSmartHeight = 2.0;
01287 static tSettingItem< REAL > se_confCameraSmartHeight( "CAMERA_SMART_HEIGHT", se_cameraSmartHeight );
01288
01289 static REAL se_cameraSmartDistance = 4.0;
01290 static tSettingItem< REAL > se_confCameraSmartDistance( "CAMERA_SMART_DISTANCE", se_cameraSmartDistance );
01291
01292 static REAL se_cameraSmartHeightExtra = .5f;
01293 static tSettingItem< REAL > se_confCameraSmartHeightExtra( "CAMERA_SMART_HEIGHT_EXTRA", se_cameraSmartHeightExtra );
01294
01295
01296 static REAL se_cameraSmartHeightTurning = .5;
01297 static tSettingItem< REAL > se_confCameraSmartHeightTurning( "CAMERA_SMART_HEIGHT_TURNING", se_cameraSmartHeightTurning );
01298
01299
01300 static REAL se_cameraSmartHeightGrinding = 0;
01301 static tSettingItem< REAL > se_confCameraSmartHeightGrinding( "CAMERA_SMART_HEIGHT_GRINDING", se_cameraSmartHeightGrinding );
01302
01303
01304 static REAL se_cameraSmartHeightObstacle = 1.0;
01305 static tSettingItem< REAL > se_confCameraSmartHeightObstacle( "CAMERA_SMART_HEIGHT_OBSTACLE", se_cameraSmartHeightObstacle );
01306
01307
01308 static REAL se_cameraSmartAvoidFront = 10.0;
01309 static tSettingItem< REAL > se_confCameraSmartAvoidFront( "CAMERA_SMART_AVOID_FRONT", se_cameraSmartAvoidFront );
01310
01311
01312 static REAL se_cameraSmartAvoidFront2 = 0.1;
01313 static tSettingItem< REAL > se_confCameraSmartAvoidFront2( "CAMERA_SMART_AVOID_FRONT2", se_cameraSmartAvoidFront2 );
01314
01315
01316 static REAL se_cameraSmartTurn = 5.0;
01317 static tSettingItem< REAL > se_confCameraSmartTurn( "CAMERA_SMART_TURN_GRINDING", se_cameraSmartTurn );
01318
01319
01320 static REAL se_cameraSmartCenterPosSmooth = 6.0;
01321 static tSettingItem< REAL > se_confCameraSmartCenterPosSmooth( "CAMERA_SMART_CENTER_POS_SMOOTH", se_cameraSmartCenterPosSmooth );
01322
01323
01324 static REAL se_cameraSmartCenterDirSmooth = 3.0;
01325 static tSettingItem< REAL > se_confCameraSmartCenterDirSmooth( "CAMERA_SMART_CENTER_DIR_SMOOTH", se_cameraSmartCenterDirSmooth );
01326
01327
01328 static REAL se_cameraSmartCenterLookahead = .5;
01329 static tSettingItem< REAL > se_confCameraSmartCenterLookahead( "CAMERA_SMART_CENTER_LOOKAHEAD", se_cameraSmartCenterLookahead );
01330
01331
01332 static REAL se_cameraSmartCenterMaxLookahead = 5;
01333 static tSettingItem< REAL > se_confCameraSmartCenterMaxLookahead( "CAMERA_SMART_CENTER_MAX_LOOKAHEAD", se_cameraSmartCenterMaxLookahead );
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343 static float se_cameraEyeDistance = 0;
01344 static tConfItem<float> secced("CAMERA_EYE_DISTANCE", se_cameraEyeDistance);
01345
01346 static int se_cameraEye1Color = 1;
01347 static tConfItem<int> sece1ca("CAMERA_EYE_1_COLOR", se_cameraEye1Color);
01348 static tConfItem<int> sece1cb("CAMERA_EYE_1_COLOUR", se_cameraEye1Color);
01349
01350 static int se_cameraEye2Color = 6;
01351 static tConfItem<int> sece2ca("CAMERA_EYE_2_COLOR", se_cameraEye2Color);
01352 static tConfItem<int> sece2cb("CAMERA_EYE_2_COLOUR", se_cameraEye2Color);
01353
01354 static float se_cameraInMaxFocusDistance = .5;
01355 static tConfItem<float> secimfd("CAMERA_IN_MAX_FOCUS_DISTANCE", se_cameraInMaxFocusDistance);
01356
01357 #ifndef DEDICATED
01358 bool displaying=false;
01359
01360 void eCamera::Render(){
01361 if (!sr_glOut)
01362 return;
01363 displaying=true;
01364
01365 se_cameraRise=rise;
01366 se_cameraZ=z;
01367
01368
01369 lastrendertime=se_GameTime();
01370
01371 makefinite(pos);
01372 makefinite(lastPos);
01373 makefinite(top);
01374 makefinite(dir);
01375 makefinite(rise,0);
01376 makefinite(z,2);
01377 makefinite(distance,0);
01378 makefinite(smartcamSkewSmooth);
01379 makefinite(smartcamFrontSmooth);
01380 makefinite(smartcamIncamSmooth);
01381 makefinite(centerDirSmooth);
01382 makefinite(centerPosSmooth);
01383 makefinite(centerPosLast);
01384 makefinite(centerIncam);
01385 makefinite(userCameraControl);
01386 makefinite(turning);
01387 makefinite(smoothTurning);
01388 makefinite(fov);
01389 makefinite(distance);
01390 makefinite(lastrendertime);
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407 if (!se_ClampCamera(mode))
01408 Bound(0, pos);
01409
01410
01411
01412 if (z>400) z=300;
01413 if (z<0) z=0;
01414
01415 if (rise<-100) rise=-100;
01416 if (rise>100) rise=100;
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 distance+=sqrt((lastPos-pos).NormSquared())*1.5;
01435 lastPos=pos;
01436
01437 #ifdef DEBUG
01438
01439 #endif
01440
01441 glMatrixMode(GL_PROJECTION);
01442 glLoadIdentity();
01443 glMatrixMode(GL_MODELVIEW);
01444 glLoadIdentity();
01445
01446 if(CenterCockpitFixedBefore()){
01447 vp->Perspective(fov,zNear,1E+20,se_cameraEyeDistance/2.);
01448
01449 gluLookAt(0,
01450 0,
01451 0,
01452
01453 dir.x,
01454 dir.y,
01455 rise,
01456
01457 top.x,top.y,
01458 1);
01459
01460 glTranslatef(-pos.x,-pos.y,-z);
01461 glMatrixMode(GL_MODELVIEW);
01462
01463 bool draw_center=((CenterPos()-pos).NormSquared()>1 ||
01464 fabs(CenterZ() - z)>1);
01465
01466 tJUST_CONTROLLED_PTR< eGameObject > c=Center();
01467 if (!draw_center && c) c->RemoveFromList();
01468
01469 eCoord poscopy = pos;
01470 zNear = - eWallRim::Bound( poscopy, 0.0f );
01471 if (zNear < -.1 )
01472 zNear = .1;
01473
01474 if(se_cameraEyeDistance) {
01475 glColorMask(se_cameraEye1Color & 1, se_cameraEye1Color & 2, se_cameraEye1Color & 4, GL_TRUE);
01476 }
01477 grid->Render( this, id, zNear );
01478
01479 zNear *= .3f;
01480 if ( zNear < 0.0001f )
01481 {
01482 zNear = 0.0001f;
01483 }
01484
01485 if(se_cameraEyeDistance) {
01486 glClear(GL_DEPTH_BUFFER_BIT);
01487 glColorMask(se_cameraEye2Color & 1, se_cameraEye2Color & 2, se_cameraEye2Color & 4, GL_TRUE);
01488 glMatrixMode(GL_PROJECTION);
01489 glLoadIdentity();
01490 glMatrixMode(GL_MODELVIEW);
01491 glLoadIdentity();
01492
01493 vp->Perspective(fov,zNear,1E+20,-se_cameraEyeDistance/2.);
01494
01495 float offset = 0;
01496 if(mode == CAMERA_IN) {
01497 eSensor test(Center(), Center()->Position(), Center()->Direction());
01498 test.detect(se_cameraInMaxFocusDistance*Center()->Speed());
01499 offset = test.hit;
01500 }
01501
01502 gluLookAt(0,
01503 0,
01504 0,
01505
01506 dir.x,
01507 dir.y,
01508 rise,
01509
01510 top.x,top.y,
01511 1);
01512
01513 glTranslatef(-pos.x,-pos.y,-z);
01514 glMatrixMode(GL_MODELVIEW);
01515
01516 draw_center=((CenterPos()-pos).NormSquared()>1 ||
01517 fabs(CenterZ() - z)>1);
01518
01519 tJUST_CONTROLLED_PTR< eGameObject > c=Center();
01520 if (!draw_center && c) c->RemoveFromList();
01521
01522 eCoord poscopy = pos;
01523 zNear = - eWallRim::Bound( poscopy, 0.0f );
01524 if (zNear < -.1 )
01525 zNear = .1;
01526
01527 grid->Render( this, id, zNear );
01528
01529 zNear *= .3f;
01530 if ( zNear < 0.0001f )
01531 {
01532 zNear = 0.0001f;
01533 }
01534 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
01535 }
01536
01537 if (c) c->RenderCockpitVirtual();
01538 if (!draw_center && c) c->AddToList();
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 CenterCockpitFixedAfter();
01550 }
01551 displaying=false;
01552 }
01553
01554 #endif
01555
01556 void eCamera::SwitchCenter(int d){
01557 zNear = 0.01f;
01558
01559 int centerID = 0;
01560 if (center)
01561 centerID = center->interestingID;
01562 center = NULL;
01563
01564 if (centerID>=grid->gameObjectsInteresting.Len())
01565 centerID=0;
01566 if (centerID<0)
01567 centerID=grid->gameObjectsInteresting.Len()-1;
01568
01569 int timeout=(grid->gameObjectsInteresting.Len()+1)*5;
01570 int oldid=centerID;
01571 if (grid->gameObjectsInteresting.Len()>0){
01572 if (!InterestingToWatch(grid->gameObjectsInteresting(centerID)))
01573 grid->gameObjectsInteresting.Remove
01574 (grid->gameObjectsInteresting(centerID),
01575 grid->gameObjectsInteresting(centerID)->interestingID);
01576 do{
01577 timeout--;
01578 centerID+=d;
01579
01580 if (centerID<0)
01581 centerID=grid->gameObjectsInteresting.Len()-1;
01582 if (centerID>=grid->gameObjectsInteresting.Len())
01583 centerID=0;
01584
01585 }while(timeout >0 && grid->gameObjectsInteresting.Len()>0 &&
01586 oldid!=centerID &&
01587 !InterestingToWatch(grid->gameObjectsInteresting(centerID)));
01588 }
01589 else centerID=0;
01590
01591
01592 if ( centerID >= 0 && centerID < grid->gameObjectsInteresting.Len() )
01593 {
01594 center = grid->gameObjectsInteresting(centerID);
01595 lastSwitch=lastTime;
01596 }
01597 }
01598
01599 void eCamera::Timestep(REAL ts){
01600
01601 if (!netPlayer && localPlayer)
01602 {
01603 netPlayer = localPlayer->netPlayer;
01604 }
01605
01606
01607 if (netPlayer)
01608 {
01609 eGameObject * bestCenter = netPlayer->Object();
01610 if ( InterestingToWatch(bestCenter) )
01611 {
01612 if ( bestCenter != center )
01613 {
01614 center = bestCenter;
01615 if ( mode != CAMERA_FREE )
01616 mode=localPlayer->startCamera;
01617 }
01618 }
01619 }
01620
01621 eCamMode newmode = mode;
01622
01624
01626
01627
01628 REAL customBack = 0, customRise = 0, customPitch = 0, customTurnSpeed = s_customTurnSpeed, customTurnSpeed180 = s_customTurnSpeed180;
01629 {
01630 REAL speed = centerSpeedSmooth;
01631 if ( newmode == CAMERA_SERVER_CUSTOM )
01632 {
01633 customBack = s_serverCustomBack + speed * s_serverCustomBackSpeed;
01634 customRise = s_serverCustomRise + speed * s_serverCustomRiseSpeed;
01635 customPitch = s_serverCustomPitch;
01636
01637 if ( s_serverCustomTurnSpeed >= 0 )
01638 {
01639 customTurnSpeed = s_serverCustomTurnSpeed;
01640 customTurnSpeed180 = s_serverCustomTurnSpeed180;
01641 }
01642 }
01643 else
01644 {
01645 customBack = s_customBack + speed * s_customBackSpeed;
01646 customRise = s_customRise + speed * s_customRiseSpeed;
01647 customPitch = s_customPitch;
01648 }
01649 }
01650
01651
01652 if (lastSwitch>lastTime)
01653 lastSwitch=lastTime;
01654
01655 if (!InterestingToWatch(Center()) && lastTime-lastSwitch>2 && (center==0 || lastTime-center->deathTime > 4)){
01656 center = se_GetWatchedObject( this );
01657 if ( !center || !InterestingToWatch(center) )
01658 SwitchCenter(1);
01659
01660 if (!InterestingToWatch(Center()))
01661 {
01662 newmode=CAMERA_FREE;
01663 }
01664
01665
01666
01667
01668
01669
01670
01671
01672 }
01673
01674 if (!Center())
01675 return;
01676
01677
01678 if ( fabs( centerDirLast * Center()->Direction() ) > .01 )
01679 {
01680 turning+=.5;
01681 centerDirLast = Center()->Direction();
01682 }
01683
01684 for(int i = hitCacheSize-1; i>=0; --i)
01685 {
01686 hitCache_[i] += ts * se_hitCacheSpeed;
01687 if (hitCache_[i] > 1)
01688 hitCache_[i] = 1;
01689 }
01690
01691
01692 bool bound = false;
01693
01694 eCoord objdir=CenterCamDir();
01695
01696
01697 if ( Center() )
01698 {
01699 #define SMOOTH_SPEED 1
01700 centerSpeedSmooth = ( centerSpeedSmooth + Center()->Speed() * ts * SMOOTH_SPEED)/( 1 + ts * SMOOTH_SPEED );
01701
01702 centerPos = Center()->PredictPosition();
01703
01704
01705
01706
01707
01708 }
01709 centerPosSmooth=(centerPosSmooth+ CenterPos()*(ts*se_cameraSmartCenterPosSmooth))
01710 *(1/(1+ts*se_cameraSmartCenterPosSmooth));
01711
01712
01713
01714
01715
01716
01717 if (!CenterAlive() && (newmode==CAMERA_IN || newmode==CAMERA_SMART_IN)){
01718 pos=pos-dir.Turn(eCoord(5,1));
01719 z+=2;
01720 newmode=CAMERA_SMART;
01721 }
01722
01723 const REAL dirSmooth = se_cameraSmartCenterDirSmooth;
01724 centerDirSmooth=(centerDirSmooth+(CenterDir()*dirSmooth*ts))*
01725 (1/(1+dirSmooth*ts));
01726
01727
01728 REAL speedFactor = se_GameTime() * this->CenterSpeed() * se_cameraSmartCenterLookahead;
01729 if ( speedFactor < 0.0f )
01730 {
01731 speedFactor = 0.0f;
01732 }
01733 if ( speedFactor > se_cameraSmartCenterMaxLookahead )
01734 {
01735 speedFactor = se_cameraSmartCenterMaxLookahead;
01736 }
01737 eCoord centerpos=CenterPos();
01738
01739
01740 #define SMART_INCAM_SPEED 1
01741 #define SMART_FRONT_SPEED 4
01742
01743 userCameraControl/=(1+ts*5);
01744 #define maxcontrol 10
01745 if (userCameraControl>maxcontrol)
01746 userCameraControl=maxcontrol;
01747
01748 smartcamFrontSmooth/=(1+SMART_FRONT_SPEED*ts);
01749 smartcamSkewSmooth/=(1+2*ts);
01750 smartcamIncamSmooth/=(1+SMART_INCAM_SPEED*ts);
01751
01752 eCoord newpos=pos,newdir=dir;
01753 REAL newz=z,newrise=rise;
01754
01755 eCoord usernewpos=pos;
01756 eCoord usernewdir=dir;
01757 REAL usernewz=z;
01758 REAL usernewrise=rise;
01759
01760 REAL relax=se_cameraSmartDistance;
01761
01762 REAL wish_h=se_cameraSmartHeight*vp->UpDownFOV(fov)/60 * ( this->CenterSpeed() * .02 + SpeedMultiplier() );
01763 REAL min_dist=se_cameraSmartMinDistance;
01764
01765 turning/=(1+2*ts);
01766 smoothTurning+=3*turning*ts;
01767 smoothTurning/=1+ts;
01768
01769 #define maxs 5
01770 if (smoothTurning>maxs) smoothTurning=maxs;
01771
01772 REAL side;
01773 REAL eturn;
01774
01775 top=eCoord(0,0);
01776
01777
01778 eCamMode effectiveMode = mode;
01779 if (!InterestingToWatch(Center()))
01780 {
01781 effectiveMode=CAMERA_FREE;
01782 }
01783
01784 switch (effectiveMode){
01785 case CAMERA_FREE:
01786 newpos=pos;
01787 newdir=dir;
01788 newz=z;
01789 newrise=rise;
01790 break;
01791 case CAMERA_SMART_IN:
01792 case CAMERA_CUSTOM:
01793 case CAMERA_SERVER_CUSTOM:
01794 case CAMERA_IN:
01795 if (WhobbleIncam()){
01796 top=CenterCamTop();
01797 newpos=CenterCamPos();
01798 }
01799 else
01800 newpos=CenterPos();
01801
01802 if (CenterIncamOnTurn() || newmode==CAMERA_SMART_IN || newmode == CAMERA_CUSTOM || newmode == CAMERA_SERVER_CUSTOM )
01803 {
01804
01805 REAL turnSpeed = ( newmode == CAMERA_IN || newmode == CAMERA_SMART_IN ) ? s_inTurnSpeed : customTurnSpeed;
01806
01807 eCoord cycleDir = CenterCamDir();
01808 newdir=dir+cycleDir*(turnSpeed*ts);
01809
01810
01811 REAL wrongDirection = -eCoord::F( cycleDir, newdir );
01812 if ( Center() && wrongDirection > 0 )
01813 {
01814
01815 newdir = newdir + Center()->LastDirection()*(wrongDirection*ts*turnSpeed*s_customTurnSpeed180);
01816 }
01817 }
01818 else
01819 newdir=dir;
01820
01821 if ( newmode == CAMERA_IN || newmode == CAMERA_SMART_IN )
01822 {
01823 const REAL forwardCheck = .1;
01824
01825
01826 eSensor forward( Center(), newpos, newdir );
01827 forward.detect( forwardCheck );
01828 if ( forward.ehit )
01829 {
01830 REAL backwardCheck = ( forwardCheck - forward.hit ) * 2;
01831 eSensor backward( Center(), newpos, -newdir );
01832 backward.detect( backwardCheck );
01833 newpos = newpos - newdir * ( backward.hit * .5 );
01834 }
01835 }
01836
01837 if (newmode != CAMERA_CUSTOM && newmode != CAMERA_SERVER_CUSTOM)
01838 {
01839 newz=CenterCamZ();
01840 newrise=rise;
01841 if (newrise>2) newrise=2;
01842 if (newrise<-2) newrise=-2;
01843
01844 usernewpos=newpos;
01845 usernewz=newz;
01846 }
01847
01848
01849 if (newmode==CAMERA_SMART_IN){
01850 REAL space[2];
01851
01852 REAL dist = CenterSpeed() * .2f;
01853 if (dist < 5)
01854 dist = 5;
01855
01856 for(int i=0;i<2;i++){
01857 eSensor s(Center(),CenterPos(),CenterDir().Turn(1,2*i-1));
01858 s.detect(dist);
01859 space[i]=s.hit;
01860 }
01861 smartcamIncamSmooth+=(space[0]+space[1])*ts*SMART_INCAM_SPEED/dist;
01862
01863 if (smartcamIncamSmooth>.8){
01864 eSensor s(Center(),CenterPos(),CenterCycleDir());
01865 s.detect(5.5);
01866
01867 if (s.hit>5){
01868 newmode=CAMERA_SMART;
01869 usernewz=newz=z+.5;
01870 usernewpos=newpos=pos+dir.Turn(-1,.1);
01871 }
01872 }
01873 }
01874
01875 if (newmode != CAMERA_CUSTOM && newmode != CAMERA_SERVER_CUSTOM)
01876 {
01877 int x=3;
01878 while (eCoord::F(newdir,objdir)<-.5001 && x>0){
01879 newdir=newdir-objdir*(eCoord::F(newdir,objdir)+.5);
01880 newdir=newdir*(1/sqrt(newdir.NormSquared()));
01881 x--;
01882 }
01883 }
01884 else if ( newmode == CAMERA_CUSTOM || newmode == CAMERA_SERVER_CUSTOM )
01885 {
01886 REAL zoom = lastTime > 0 ? 1 : exp( s_customZoom * lastTime );
01887
01888 newdir=newdir*(1/sqrt(newdir.NormSquared()));
01889 newpos = newpos - newdir * customBack * zoom;
01890 usernewpos = usernewpos + CenterPos() - centerPosLast;
01891 newrise = customPitch;
01892 newz = CenterCamZ() + customRise * zoom;
01893 }
01894
01895 break;
01896 case CAMERA_SMART:
01897 if (activeGlanceRequest) {
01898 newdir = dir;
01899 newpos = CenterPos()+newdir*smartcamGlancingBack;
01900 newz = smartcamGlancingHeight;
01901 newrise = (CenterZ()-newz)/smartcamGlancingBack;
01902 } else {
01903 REAL dist = CenterSpeed() * se_cameraSmartDistanceScale;
01904 if (dist < se_cameraSmartMinDistanceScale)
01905 dist = se_cameraSmartMinDistanceScale;
01906
01907 REAL space[2];
01908
01909 for(int i=0;i<2;i++){
01910 eSensor s(Center(),CenterPos(),CenterDir().Turn(1,2*i-1));
01911 s.detect(dist);
01912 space[i]=s.hit;
01913 }
01914
01915 REAL slowFactor = this->CenterSpeed() / se_cameraSmartCycleSpeed;
01916 if ( slowFactor > 1.0f )
01917 {
01918 slowFactor = 1.0f;
01919 }
01920
01921 eSensor front(Center(), CenterPos(), CenterDir());
01922 front.detect(dist * 4);
01923 REAL ff = (4 * dist - front.hit)/(3*dist);
01924 ff *= ff;
01925 smartcamFrontSmooth+=ff*SMART_FRONT_SPEED*ts;
01926
01927 smartcamSkewSmooth+=(space[0]-space[1])*ts * slowFactor;
01928 smartcamIncamSmooth+=(space[0]+space[1])*ts*SMART_INCAM_SPEED/dist;
01929
01930 REAL sk = fabs(smartcamSkewSmooth)/5;
01931 if (sk > 1)
01932 sk = 1;
01933
01934 REAL rf = .15+.1*smoothTurning - sk * .15 - .05 * smartcamFrontSmooth;
01935 if (rf < .05)
01936 rf = .05;
01937
01938 relax*=rf;
01939 relax/=slowFactor;
01940
01941 wish_h*=se_cameraSmartHeightExtra + se_cameraSmartHeightTurning*smoothTurning + se_cameraSmartHeightGrinding * sk + smartcamFrontSmooth * se_cameraSmartHeightObstacle;
01942 min_dist/=3;
01943
01944 {
01945 if (!CenterAlive()) wish_h+=3;
01946 REAL front=eCoord::F(pos-centerpos,CenterDir());
01947 side=((pos-centerpos)*CenterDir()) * front;
01948
01949 eturn=ts/relax * (1 + .5 * smartcamFrontSmooth);
01950 if (side>0) eturn*=-1;
01951
01952 newz=z;
01953
01954
01955
01956
01957 if (front>0){
01958 if (front>2.5) front=2.5;
01959 if (fabs(smartcamSkewSmooth)>1 || smartcamSkewSmooth*eturn>0)
01960 smartcamSkewSmooth*=(1+ts);
01961 if (fabs(smartcamSkewSmooth)<1)
01962 smartcamSkewSmooth -= se_cameraSmartAvoidFront * eturn;
01963 newz+=ts*front*.1;
01964
01965
01966 }
01967
01968 if (se_GameTime()>0){
01969 newpos=pos + CenterDir().Turn(eCoord(0,eturn*se_cameraSmartAvoidFront2));
01970 newpos=newpos+CenterDir().Turn(0,-1)*smartcamSkewSmooth*ts*se_cameraSmartTurn;
01971
01972 newpos=newpos+centerpos*(ts/relax);
01973 newpos=newpos*(1/(1+ts/relax));
01974 }
01975 else{
01976 newpos=pos+ (pos-centerpos).Turn(-ts*.5,ts*.5);
01977 }
01978
01979 if ( userCameraControl < .25 && se_ClampCamera(newmode) )
01980 {
01981 bound = true;
01982 Bound( ts, newpos );
01983
01984 }
01985
01986 newz=newz+(CenterZ()+wish_h)*(ts/relax);
01987 newz=newz/(1+ts/relax);
01988 newdir=centerpos-newpos;
01989 REAL dist=sqrt(newdir.NormSquared());
01990 if (dist<.001) dist=.01;
01991
01992 newdir=dir+newdir*ts*5.0;
01993 newdir=newdir*(1/sqrt(newdir.NormSquared()));
01994
01995 if (dist<min_dist){
01996
01997 REAL dz=(min_dist*min_dist-dist*dist-.5*z*z);
01998 if (dz>0)
01999 newz+=dz*ts;
02000 }
02001
02002 REAL d=eCoord::F(newdir,centerpos - newpos);
02003 if (d<.0001) d=.0001;
02004 newrise=(CenterZ()-newz)/d;
02005
02006 usernewpos=pos + centerpos - centerPosLast;
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044 if (AutoSwitchIncam()){
02045 if (smartcamIncamSmooth<.7 && CenterAlive()){
02046 eSensor s(Center(),CenterPos(),CenterDir());
02047 s.detect(5.5);
02048 if (s.hit>5){
02049 usernewrise=newrise=0;
02050 newmode=CAMERA_SMART_IN;
02051 usernewdir=newdir=objdir;
02052 }
02053 }
02054 }
02055 else
02056 if (smartcamIncamSmooth<.7)
02057 newz+=ts*(.7-smartcamIncamSmooth);
02058 }
02059 }
02060 break;
02061 case CAMERA_FOLLOW:{
02062 newpos=usernewpos=pos + centerpos - centerposLast;
02063 newz=z;
02064 newdir=centerpos-newpos;
02065 REAL dist=sqrt(newdir.NormSquared());
02066 newdir=newdir*(1/dist);
02067 newrise=(CenterZ()-newz)/dist;
02068 }
02069 break;
02070 case CAMERA_MER: {
02071
02072 REAL zoom = lastTime > 0 ? 1 : exp( s_customZoom * lastTime );
02073 REAL dist = mercamxydist*zoom;
02074
02075 eCoord t = CenterPos()-pos;
02076 t.Normalize();
02077
02078
02079 newpos = usernewpos=CenterPos()-t*dist;
02080 newz = CenterZ()*(1-zoom) +mercamz*zoom;
02081 newdir = t;
02082 newrise = (CenterZ()-newz)/dist;
02083 }
02084 break;
02085 case CAMERA_COUNT:
02086 break;
02087 }
02088
02090
02091
02092
02094
02095 if (activeGlanceRequest) {
02096 bool internal = mode==CAMERA_IN || mode==CAMERA_SMART_IN;
02097
02098 if (internal) {
02099 pos = newpos;
02100 dir = nextDirIfGlancing(dir,activeGlanceRequest->dir,ts);
02101 z = newz;
02102 rise = newrise;
02103 } else {
02104 REAL c = 5*ts;
02105 eCoord focusTarget = (mode==CAMERA_SMART) ? centerpos : CenterPos();
02106 eCoord focusTargetLast = (mode==CAMERA_SMART) ? centerposLast : centerPosLast;
02107
02108
02109
02110 REAL focusZ = (newpos-focusTarget).Norm()*newrise+newz;
02111 eCoord focus = dir*((focusZ-z)/rise) + pos;
02112
02113
02114 focus = focus * (1-c) + focusTargetLast * c;
02115
02116
02117 eCoord t = focus-pos;
02118 REAL tnorm = t.Norm();
02119 t.Normalize();
02120 t = nextDirIfGlancing(t,activeGlanceRequest->dir,ts);
02121
02122
02123 focus = focus + focusTarget - focusTargetLast;
02124
02125
02126 tnorm = tnorm * (1-c) + (newpos-focusTarget).Norm() * c;
02127
02128
02129 pos = focus - t * tnorm;
02130 dir = t;
02131 z = z * (1-c) + newz * c;
02132 rise = (focusZ-z) / tnorm;
02133
02134
02135 }
02136
02137 } else {
02138
02139
02140
02141
02142
02143
02144
02145
02146
02147 REAL aratio = exp(-4*userCameraControl);
02148 REAL ratio = 1 - aratio;
02149
02150
02151 pos=newpos*aratio + usernewpos*ratio;
02152 dir=newdir*aratio + usernewdir*ratio;
02153 z =newz *aratio + usernewz *ratio;
02154
02155
02156 if (userCameraControl > .01)
02157 {
02158 rise=newrise + (usernewrise-newrise)*exp(-ts/userCameraControl);
02159 }
02160 else
02161 {
02162 rise=newrise;
02163 }
02164
02165
02166 dir=dir*(1/sqrt(dir.NormSquared()));
02167 }
02168
02169 #ifdef CAMERA_LOGGING
02170 std::cout << (activeGlanceRequest ? "g " : " ") << (pos-CenterPos()).Norm() << " " << (newpos-CenterPos()).Norm() << " " << z << " " << rise << "\n";
02171 #endif
02172 dir.Normalize();
02173 centerposLast=centerpos;
02174 centerPosLast=CenterPos();
02175
02176
02177 if (!bound && se_ClampCamera(mode) )
02178 Bound( ts );
02179 }
02180
02181
02182
02183 void eCamera::s_Timestep(eGrid *grid, REAL time){
02184 if (fabs(time-lastTime)>1) lastTime=time-.1;
02185 if (time>lastTime){
02186 eDebugLine::Update(time-lastTime);
02187
02188 for(int i=grid->cameras.Len()-1;i>=0;i--){
02189
02190 eCamera *c = grid->cameras(i);
02191 c->Timestep(time-lastTime);
02192 su_FetchAndStoreSDLInput();
02193 }
02194 lastTime=time;
02195 }
02196 }
02197
02198
02199 #ifndef DEDICATED
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250 #endif
02251
02252 eCoord eCamera::CenterPos() const{
02253 return centerPos;
02254 }
02255
02256 eCoord eCamera::CenterCycleDir() const{
02257 return CenterDir();
02258 }
02259
02260 eCoord eCamera::CenterDir() const{
02261 eGameObject *go=Center();
02262 if (go)
02263 return go->Direction() ;
02264 else
02265 return eCoord(1,0);
02266 }
02267
02268 eCoord eCamera::CenterCamDir() const{
02269 eGameObject *go=Center();
02270 if (go)
02271 return go->CamDir() ;
02272 else
02273 return eCoord(1,0);
02274 }
02275
02276 eCoord eCamera::CenterCamTop() const{
02277 eGameObject *go=Center();
02278 if (go)
02279 return go->CamTop();
02280 else
02281 return eCoord(0,0);
02282 }
02283
02284 eCoord eCamera::CenterCamPos() const{
02285 eGameObject *go=Center();
02286 if (go)
02287 return go->CamPos();
02288 else
02289 return eCoord(100,100);
02290 }
02291
02292 REAL eCamera::CenterCamZ() const{
02293 eGameObject *go=Center();
02294 if (go)
02295 return go-> CamZ();
02296 else
02297 return 1.5;
02298 }
02299
02300 REAL eCamera::CenterZ() const{
02301 eGameObject *go=Center();
02302 if (go)
02303 return go->z ;
02304 else
02305 return 1.5;
02306 }
02307
02308 REAL eCamera::CenterSpeed() const{
02309 eGameObject *go=Center();
02310 if (go)
02311 return go->Speed();
02312 else
02313 return 20;
02314 }
02315
02316
02317 bool eCamera::CenterAlive() const{
02318 eGameObject *go=Center();
02319 if (go)
02320 return go->Alive() ;
02321 else
02322 return false;
02323 }
02324
02325
02326 bool eCamera::CenterCockpitFixedBefore() const{
02327 eGameObject *go=Center();
02328 if (go)
02329 return go->RenderCockpitFixedBefore();
02330 else
02331 return true;
02332 }
02333
02334 void eCamera::CenterCockpitFixedAfter() const{
02335 eGameObject *go=Center();
02336 if (go)
02337 go->RenderCockpitFixedAfter() ;
02338 else
02339 return;
02340 }
02341
02342