00001
00002
00003
00004
00005 #include "cg_local.h"
00006
00007 #include "bg_saga.h"
00008
00009 #if !defined(CL_LIGHT_H_INC)
00010 #include "cg_lights.h"
00011 #endif
00012
00013 #define MASK_CAMERACLIP (MASK_SOLID|CONTENTS_PLAYERCLIP)
00014 #define CAMERA_SIZE 4
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 void CG_TestModel_f (void) {
00061 vec3_t angles;
00062
00063 memset( &cg.testModelEntity, 0, sizeof(cg.testModelEntity) );
00064 if ( trap_Argc() < 2 ) {
00065 return;
00066 }
00067
00068 Q_strncpyz (cg.testModelName, CG_Argv( 1 ), MAX_QPATH );
00069 cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
00070
00071 if ( trap_Argc() == 3 ) {
00072 cg.testModelEntity.backlerp = atof( CG_Argv( 2 ) );
00073 cg.testModelEntity.frame = 1;
00074 cg.testModelEntity.oldframe = 0;
00075 }
00076 if (! cg.testModelEntity.hModel ) {
00077 CG_Printf( "Can't register model\n" );
00078 return;
00079 }
00080
00081 VectorMA( cg.refdef.vieworg, 100, cg.refdef.viewaxis[0], cg.testModelEntity.origin );
00082
00083 angles[PITCH] = 0;
00084 angles[YAW] = 180 + cg.refdef.viewangles[1];
00085 angles[ROLL] = 0;
00086
00087 AnglesToAxis( angles, cg.testModelEntity.axis );
00088 cg.testGun = qfalse;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098 void CG_TestGun_f (void) {
00099 CG_TestModel_f();
00100 cg.testGun = qtrue;
00101
00102
00103
00104 cg.testModelEntity.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON;
00105 }
00106
00107
00108 void CG_TestModelNextFrame_f (void) {
00109 cg.testModelEntity.frame++;
00110 CG_Printf( "frame %i\n", cg.testModelEntity.frame );
00111 }
00112
00113 void CG_TestModelPrevFrame_f (void) {
00114 cg.testModelEntity.frame--;
00115 if ( cg.testModelEntity.frame < 0 ) {
00116 cg.testModelEntity.frame = 0;
00117 }
00118 CG_Printf( "frame %i\n", cg.testModelEntity.frame );
00119 }
00120
00121 void CG_TestModelNextSkin_f (void) {
00122 cg.testModelEntity.skinNum++;
00123 CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
00124 }
00125
00126 void CG_TestModelPrevSkin_f (void) {
00127 cg.testModelEntity.skinNum--;
00128 if ( cg.testModelEntity.skinNum < 0 ) {
00129 cg.testModelEntity.skinNum = 0;
00130 }
00131 CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
00132 }
00133
00134 static void CG_AddTestModel (void) {
00135 int i;
00136
00137
00138 cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
00139 if (! cg.testModelEntity.hModel ) {
00140 CG_Printf ("Can't register model\n");
00141 return;
00142 }
00143
00144
00145 if ( cg.testGun ) {
00146 VectorCopy( cg.refdef.vieworg, cg.testModelEntity.origin );
00147 VectorCopy( cg.refdef.viewaxis[0], cg.testModelEntity.axis[0] );
00148 VectorCopy( cg.refdef.viewaxis[1], cg.testModelEntity.axis[1] );
00149 VectorCopy( cg.refdef.viewaxis[2], cg.testModelEntity.axis[2] );
00150
00151
00152 for (i=0 ; i<3 ; i++) {
00153 cg.testModelEntity.origin[i] += cg.refdef.viewaxis[0][i] * cg_gun_x.value;
00154 cg.testModelEntity.origin[i] += cg.refdef.viewaxis[1][i] * cg_gun_y.value;
00155 cg.testModelEntity.origin[i] += cg.refdef.viewaxis[2][i] * cg_gun_z.value;
00156 }
00157 }
00158
00159 trap_R_AddRefEntityToScene( &cg.testModelEntity );
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 static void CG_CalcVrect (void) {
00175 int size;
00176
00177
00178 if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
00179 size = 100;
00180 } else {
00181
00182 if (cg_viewsize.integer < 30) {
00183 trap_Cvar_Set ("cg_viewsize","30");
00184 size = 30;
00185 } else if (cg_viewsize.integer > 100) {
00186 trap_Cvar_Set ("cg_viewsize","100");
00187 size = 100;
00188 } else {
00189 size = cg_viewsize.integer;
00190 }
00191
00192 }
00193 cg.refdef.width = cgs.glconfig.vidWidth*size/100;
00194 cg.refdef.width &= ~1;
00195
00196 cg.refdef.height = cgs.glconfig.vidHeight*size/100;
00197 cg.refdef.height &= ~1;
00198
00199 cg.refdef.x = (cgs.glconfig.vidWidth - cg.refdef.width)/2;
00200 cg.refdef.y = (cgs.glconfig.vidHeight - cg.refdef.height)/2;
00201 }
00202
00203
00204
00205
00206
00207
00208 static void CG_StepOffset( void ) {
00209 int timeDelta;
00210
00211
00212 timeDelta = cg.time - cg.stepTime;
00213 if ( timeDelta < STEP_TIME ) {
00214 cg.refdef.vieworg[2] -= cg.stepChange
00215 * (STEP_TIME - timeDelta) / STEP_TIME;
00216 }
00217 }
00218
00219 #define CAMERA_DAMP_INTERVAL 50
00220
00221 static vec3_t cameramins = { -CAMERA_SIZE, -CAMERA_SIZE, -CAMERA_SIZE };
00222 static vec3_t cameramaxs = { CAMERA_SIZE, CAMERA_SIZE, CAMERA_SIZE };
00223 vec3_t camerafwd, cameraup;
00224
00225 vec3_t cameraFocusAngles, cameraFocusLoc;
00226 vec3_t cameraIdealTarget, cameraIdealLoc;
00227 vec3_t cameraCurTarget={0,0,0}, cameraCurLoc={0,0,0};
00228 vec3_t cameraOldLoc={0,0,0}, cameraNewLoc={0,0,0};
00229 int cameraLastFrame=0;
00230
00231 float cameraLastYaw=0;
00232 float cameraStiffFactor=0.0f;
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 extern qboolean gCGHasFallVector;
00249 extern vec3_t gCGFallVector;
00250
00251
00252
00253
00254
00255
00256
00257 static void CG_CalcIdealThirdPersonViewTarget(void)
00258 {
00259
00260 if (gCGHasFallVector)
00261 {
00262 VectorCopy(gCGFallVector, cameraFocusLoc);
00263 }
00264 else
00265 {
00266 VectorCopy(cg.refdef.vieworg, cameraFocusLoc);
00267 }
00268
00269
00270 cameraFocusLoc[2] += cg.snap->ps.viewheight;
00271
00272
00273
00274
00275
00276 VectorCopy( cameraFocusLoc, cameraIdealTarget );
00277
00278 {
00279 float vertOffset = cg_thirdPersonVertOffset.value;
00280
00281 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00282 {
00283 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00284 if (veh->m_pVehicle &&
00285 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00286 {
00287 if ( veh->m_pVehicle->m_pVehicleInfo->cameraPitchDependantVertOffset )
00288 {
00289 if ( cg.snap->ps.viewangles[PITCH] > 0 )
00290 {
00291 vertOffset = 130+cg.predictedPlayerState.viewangles[PITCH]*-10;
00292 if ( vertOffset < -170 )
00293 {
00294 vertOffset = -170;
00295 }
00296 }
00297 else if ( cg.snap->ps.viewangles[PITCH] < 0 )
00298 {
00299 vertOffset = 130+cg.predictedPlayerState.viewangles[PITCH]*-5;
00300 if ( vertOffset > 130 )
00301 {
00302 vertOffset = 130;
00303 }
00304 }
00305 else
00306 {
00307 vertOffset = 30;
00308 }
00309 }
00310 else
00311 {
00312 vertOffset = veh->m_pVehicle->m_pVehicleInfo->cameraVertOffset;
00313 }
00314 }
00315 else if ( veh->m_pVehicle
00316 && veh->m_pVehicle->m_pVehicleInfo
00317 && veh->m_pVehicle->m_pVehicleInfo->type == VH_ANIMAL )
00318 {
00319 vertOffset = 0;
00320 }
00321 }
00322 cameraIdealTarget[2] += vertOffset;
00323 }
00324
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 static void CG_CalcIdealThirdPersonViewLocation(void)
00336 {
00337 float thirdPersonRange = cg_thirdPersonRange.value;
00338
00339 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00340 {
00341 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00342 if (veh->m_pVehicle &&
00343 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00344 {
00345 thirdPersonRange = veh->m_pVehicle->m_pVehicleInfo->cameraRange;
00346 if ( veh->playerState->hackingTime )
00347 {
00348 thirdPersonRange += fabs(((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * 100.0f;
00349 }
00350 }
00351 }
00352
00353 if ( cg.snap
00354 && (cg.snap->ps.eFlags2&EF2_HELD_BY_MONSTER)
00355 && cg.snap->ps.hasLookTarget
00356 && cg_entities[cg.snap->ps.lookTarget].currentState.NPC_class == CLASS_RANCOR )
00357 {
00358
00359 thirdPersonRange = 120.0f;
00360 }
00361
00362 VectorMA(cameraIdealTarget, -(thirdPersonRange), camerafwd, cameraIdealLoc);
00363 }
00364
00365
00366
00367 static void CG_ResetThirdPersonViewDamp(void)
00368 {
00369 trace_t trace;
00370
00371
00372 if (cameraFocusAngles[PITCH] > 89.0)
00373 {
00374 cameraFocusAngles[PITCH] = 89.0;
00375 }
00376 else if (cameraFocusAngles[PITCH] < -89.0)
00377 {
00378 cameraFocusAngles[PITCH] = -89.0;
00379 }
00380
00381 AngleVectors(cameraFocusAngles, camerafwd, NULL, cameraup);
00382
00383
00384 CG_CalcIdealThirdPersonViewTarget();
00385
00386
00387 CG_CalcIdealThirdPersonViewLocation();
00388
00389
00390 VectorCopy(cameraIdealLoc, cameraCurLoc);
00391 VectorCopy(cameraIdealTarget, cameraCurTarget);
00392
00393
00394 CG_Trace(&trace, cameraFocusLoc, cameramins, cameramaxs, cameraCurTarget, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00395 if (trace.fraction <= 1.0)
00396 {
00397 VectorCopy(trace.endpos, cameraCurTarget);
00398 }
00399
00400
00401 CG_Trace(&trace, cameraCurTarget, cameramins, cameramaxs, cameraCurLoc, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00402 if (trace.fraction <= 1.0)
00403 {
00404 VectorCopy(trace.endpos, cameraCurLoc);
00405 }
00406
00407 cameraLastFrame = cg.time;
00408 cameraLastYaw = cameraFocusAngles[YAW];
00409 cameraStiffFactor = 0.0f;
00410 }
00411
00412
00413 static void CG_UpdateThirdPersonTargetDamp(void)
00414 {
00415 trace_t trace;
00416 vec3_t targetdiff;
00417 float dampfactor, dtime, ratio;
00418
00419
00420
00421 CG_CalcIdealThirdPersonViewTarget();
00422
00423 if ( cg.predictedVehicleState.hyperSpaceTime
00424 && (cg.time-cg.predictedVehicleState.hyperSpaceTime) < HYPERSPACE_TIME )
00425 {
00426 VectorCopy(cameraIdealTarget, cameraCurTarget);
00427 }
00428 else if (cg_thirdPersonTargetDamp.value>=1.0||cg.thisFrameTeleport||cg.predictedPlayerState.m_iVehicleNum)
00429 {
00430 VectorCopy(cameraIdealTarget, cameraCurTarget);
00431 }
00432 else if (cg_thirdPersonTargetDamp.value>=0.0)
00433 {
00434
00435 VectorSubtract(cameraIdealTarget, cameraCurTarget, targetdiff);
00436
00437
00438
00439 dampfactor = 1.0-cg_thirdPersonTargetDamp.value;
00440 dtime = (float)(cg.time-cameraLastFrame) * (1.0/(float)CAMERA_DAMP_INTERVAL);
00441
00442
00443
00444 ratio = powf(dampfactor, dtime);
00445
00446
00447 VectorMA(cameraIdealTarget, -ratio, targetdiff, cameraCurTarget);
00449 }
00450
00451
00452
00453
00454 CG_Trace(&trace, cameraFocusLoc, cameramins, cameramaxs, cameraCurTarget, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00455 if (trace.fraction < 1.0)
00456 {
00457 VectorCopy(trace.endpos, cameraCurTarget);
00458 }
00459
00460
00461
00462
00463
00464 }
00465
00466
00467 extern void CG_CalcEntityLerpPositions( centity_t *cent );
00468 static void CG_UpdateThirdPersonCameraDamp(void)
00469 {
00470 trace_t trace;
00471 vec3_t locdiff;
00472 float dampfactor, dtime, ratio;
00473
00474
00475 CG_CalcIdealThirdPersonViewLocation();
00476
00477
00478
00479 dampfactor=0.0;
00480 if ( cg.predictedVehicleState.hyperSpaceTime
00481 && (cg.time-cg.predictedVehicleState.hyperSpaceTime) < HYPERSPACE_TIME )
00482 {
00483 dampfactor = 1.0f;
00484 }
00485 else if (cg_thirdPersonCameraDamp.value != 0.0)
00486 {
00487 float pitch;
00488 float dFactor;
00489
00490 if (!cg.predictedPlayerState.m_iVehicleNum)
00491 {
00492 dFactor = cg_thirdPersonCameraDamp.value;
00493 }
00494 else
00495 {
00496 dFactor = 1.0f;
00497 }
00498
00499
00500 pitch = Q_fabs(cameraFocusAngles[PITCH]);
00501
00502
00503 pitch /= 115.0;
00504 dampfactor = (1.0-dFactor)*(pitch*pitch);
00505
00506 dampfactor += dFactor;
00507
00508
00509 if (cameraStiffFactor > 0.0f)
00510 {
00511 dampfactor += (1.0-dampfactor)*cameraStiffFactor;
00512 }
00513 }
00514
00515 if (dampfactor>=1.0||cg.thisFrameTeleport)
00516 {
00517 VectorCopy(cameraIdealLoc, cameraCurLoc);
00518 }
00519 else if (dampfactor>=0.0)
00520 {
00521
00522 VectorSubtract(cameraIdealLoc, cameraCurLoc, locdiff);
00523
00524
00525
00526 dampfactor = 1.0-dampfactor;
00527 dtime = (float)(cg.time-cameraLastFrame) * (1.0/(float)CAMERA_DAMP_INTERVAL);
00528
00529
00530
00531 ratio = powf(dampfactor, dtime);
00532
00533
00534 VectorMA(cameraIdealLoc, -ratio, locdiff, cameraCurLoc);
00536 }
00537
00538
00539 CG_Trace(&trace, cameraCurTarget, cameramins, cameramaxs, cameraCurLoc, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00540
00541 if (trace.fraction < 1.0)
00542 {
00543 if (trace.entityNum < ENTITYNUM_WORLD &&
00544 cg_entities[trace.entityNum].currentState.solid == SOLID_BMODEL &&
00545 cg_entities[trace.entityNum].currentState.eType == ET_MOVER)
00546 {
00547 centity_t *mover = &cg_entities[trace.entityNum];
00548
00549
00550
00551
00552 if (mover->currentState.pos.trType != TR_STATIONARY &&
00553 mover->currentState.pos.trType != TR_LINEAR)
00554 {
00555 int curTr = mover->currentState.pos.trType;
00556 vec3_t curTrB;
00557
00558 VectorCopy(mover->currentState.pos.trBase, curTrB);
00559
00560
00561 CG_CalcEntityLerpPositions(mover);
00562
00563
00564
00565 mover->currentState.pos.trType = TR_STATIONARY;
00566 VectorCopy(mover->lerpOrigin, mover->currentState.pos.trBase);
00567
00568
00569 CG_Trace(&trace, cameraCurTarget, cameramins, cameramaxs, cameraCurLoc, cg.snap->ps.clientNum, MASK_CAMERACLIP);
00570
00571
00572 mover->currentState.pos.trType = (trType_t) curTr;
00573 VectorCopy(curTrB, mover->currentState.pos.trBase);
00574 }
00575 if (trace.fraction < 1.0f)
00576 {
00577 VectorCopy(trace.endpos, cameraCurLoc);
00578 }
00579 }
00580 else
00581 {
00582 VectorCopy( trace.endpos, cameraCurLoc );
00583 }
00584 }
00585
00586
00587
00588
00589
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601 extern vmCvar_t cg_thirdPersonHorzOffset;
00602 extern qboolean BG_UnrestrainedPitchRoll( playerState_t *ps, Vehicle_t *pVeh );
00603 static void CG_OffsetThirdPersonView( void )
00604 {
00605 vec3_t diff;
00606 float thirdPersonHorzOffset = cg_thirdPersonHorzOffset.value;
00607 float deltayaw;
00608
00609 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00610 {
00611 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00612 if (veh->m_pVehicle &&
00613 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00614 {
00615 thirdPersonHorzOffset = veh->m_pVehicle->m_pVehicleInfo->cameraHorzOffset;
00616 if ( veh->playerState->hackingTime )
00617 {
00618 thirdPersonHorzOffset += (((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * -80.0f;
00619 }
00620 }
00621 }
00622
00623 cameraStiffFactor = 0.0;
00624
00625
00626 VectorCopy( cg.refdef.viewangles, cameraFocusAngles );
00627
00628
00629 if ( cg.snap
00630 && (cg.snap->ps.eFlags2&EF2_HELD_BY_MONSTER)
00631 && cg.snap->ps.hasLookTarget
00632 && cg_entities[cg.snap->ps.lookTarget].currentState.NPC_class == CLASS_RANCOR )
00633 {
00634
00635 centity_t *monster = &cg_entities[cg.snap->ps.lookTarget];
00636 VectorSet( cameraFocusAngles, 0, AngleNormalize180(monster->lerpAngles[YAW]+180), 0 );
00637
00638
00639
00640
00641
00642
00643
00644 }
00645 else if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 )
00646 {
00647 cameraFocusAngles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
00648 }
00649 else
00650 {
00651 cameraFocusAngles[YAW] += cg_thirdPersonAngle.value;
00652 {
00653 float pitchOffset = cg_thirdPersonPitchOffset.value;
00654 if (cg.snap && cg.snap->ps.m_iVehicleNum)
00655 {
00656 centity_t *veh = &cg_entities[cg.snap->ps.m_iVehicleNum];
00657 if (veh->m_pVehicle &&
00658 veh->m_pVehicle->m_pVehicleInfo->cameraOverride)
00659 {
00660 if ( veh->m_pVehicle->m_pVehicleInfo->cameraPitchDependantVertOffset )
00661 {
00662 if ( cg.snap->ps.viewangles[PITCH] > 0 )
00663 {
00664 pitchOffset = cg.predictedPlayerState.viewangles[PITCH]*-0.75;
00665 }
00666 else if ( cg.snap->ps.viewangles[PITCH] < 0 )
00667 {
00668 pitchOffset = cg.predictedPlayerState.viewangles[PITCH]*-0.75;
00669 }
00670 else
00671 {
00672 pitchOffset = 0;
00673 }
00674 }
00675 else
00676 {
00677 pitchOffset = veh->m_pVehicle->m_pVehicleInfo->cameraPitchOffset;
00678 }
00679 }
00680 }
00681 if ( 0 && cg.predictedPlayerState.m_iVehicleNum
00682 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
00683 {
00684 float pitchPerc = ((90.0f-fabs(cameraFocusAngles[ROLL]))/90.0f);
00685 cameraFocusAngles[PITCH] += pitchOffset*pitchPerc;
00686 if ( cameraFocusAngles[ROLL] > 0 )
00687 {
00688 cameraFocusAngles[YAW] -= pitchOffset-(pitchOffset*pitchPerc);
00689 }
00690 else
00691 {
00692 cameraFocusAngles[YAW] += pitchOffset-(pitchOffset*pitchPerc);
00693 }
00694 }
00695 else
00696 {
00697 cameraFocusAngles[PITCH] += pitchOffset;
00698 }
00699 }
00700 }
00701
00702
00703
00704
00705 if (cameraLastFrame == 0 || cameraLastFrame > cg.time)
00706 {
00707 CG_ResetThirdPersonViewDamp();
00708 }
00709 else
00710 {
00711
00712 if ( cg.predictedPlayerState.m_iVehicleNum
00713 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
00714 {
00715
00716 }
00717 else
00718 {
00719 if (cameraFocusAngles[PITCH] > 80.0)
00720 {
00721 cameraFocusAngles[PITCH] = 80.0;
00722 }
00723 else if (cameraFocusAngles[PITCH] < -80.0)
00724 {
00725 cameraFocusAngles[PITCH] = -80.0;
00726 }
00727 }
00728
00729 AngleVectors(cameraFocusAngles, camerafwd, NULL, cameraup);
00730
00731 deltayaw = fabs(cameraFocusAngles[YAW] - cameraLastYaw);
00732 if (deltayaw > 180.0f)
00733 {
00734 deltayaw = fabs(deltayaw - 360.0f);
00735 }
00736 cameraStiffFactor = deltayaw / (float)(cg.time-cameraLastFrame);
00737 if (cameraStiffFactor < 1.0)
00738 {
00739 cameraStiffFactor = 0.0;
00740 }
00741 else if (cameraStiffFactor > 2.5)
00742 {
00743 cameraStiffFactor = 0.75;
00744 }
00745 else
00746 {
00747 cameraStiffFactor = (cameraStiffFactor-1.0f)*0.5f;
00748 }
00749 cameraLastYaw = cameraFocusAngles[YAW];
00750
00751
00752 CG_UpdateThirdPersonTargetDamp();
00753 CG_UpdateThirdPersonCameraDamp();
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763 VectorSubtract(cameraCurTarget, cameraCurLoc, diff);
00764 {
00765 float dist = VectorNormalize(diff);
00766
00767 if ( !dist || (diff[0] == 0 || diff[1] == 0) )
00768 {
00769 VectorCopy( camerafwd, diff );
00770 }
00771 }
00772 if ( 0 && cg.predictedPlayerState.m_iVehicleNum
00773 && BG_UnrestrainedPitchRoll( &cg.predictedPlayerState, cg_entities[cg.predictedPlayerState.m_iVehicleNum].m_pVehicle ) )
00774 {
00775 float sav_Roll = cg.refdef.viewangles[ROLL];
00776 vectoangles(diff, cg.refdef.viewangles);
00777 cg.refdef.viewangles[ROLL] = sav_Roll;
00778 }
00779 else
00780 {
00781 vectoangles(diff, cg.refdef.viewangles);
00782 }
00783
00784
00785 if ( thirdPersonHorzOffset != 0.0f )
00786 {
00787 AnglesToAxis( cg.refdef.viewangles, cg.refdef.viewaxis );
00788 VectorMA( cameraCurLoc, thirdPersonHorzOffset, cg.refdef.viewaxis[1], cameraCurLoc );
00789 }
00790
00791
00792 VectorCopy(cameraCurLoc, cg.refdef.vieworg);
00793
00794 cameraLastFrame=cg.time;
00795 }
00796
00797 void CG_GetVehicleCamPos( vec3_t camPos )
00798 {
00799 VectorCopy( cg.refdef.vieworg, camPos );
00800 }
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 static void CG_OffsetFirstPersonView( void ) {
00900 float *origin;
00901 float *angles;
00902 float bob;
00903 float ratio;
00904 float delta;
00905 float speed;
00906 float f;
00907 vec3_t predictedVelocity;
00908 int timeDelta;
00909 int kickTime;
00910
00911 if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
00912 return;
00913 }
00914
00915 origin = cg.refdef.vieworg;
00916 angles = cg.refdef.viewangles;
00917
00918
00919 if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
00920 angles[ROLL] = 40;
00921 angles[PITCH] = -15;
00922 angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
00923 origin[2] += cg.predictedPlayerState.viewheight;
00924 return;
00925 }
00926
00927
00928 kickTime = (cg.time - cg.kick_time);
00929 if ( kickTime < 800 )
00930 {
00931 float kickPerc = 0.0f;
00932 if ( kickTime <= 200 )
00933 {
00934 kickPerc = kickTime/200.0f;
00935 }
00936 else
00937 {
00938 kickTime = 800 - kickTime;
00939 kickPerc = kickTime/600.0f;
00940 }
00941 VectorMA( angles, kickPerc, cg.kick_angles, angles );
00942 }
00943
00944 if ( cg.damageTime ) {
00945 ratio = cg.time - cg.damageTime;
00946 if ( ratio < DAMAGE_DEFLECT_TIME ) {
00947 ratio /= DAMAGE_DEFLECT_TIME;
00948 angles[PITCH] += ratio * cg.v_dmg_pitch;
00949 angles[ROLL] += ratio * cg.v_dmg_roll;
00950 } else {
00951 ratio = 1.0 - ( ratio - DAMAGE_DEFLECT_TIME ) / DAMAGE_RETURN_TIME;
00952 if ( ratio > 0 ) {
00953 angles[PITCH] += ratio * cg.v_dmg_pitch;
00954 angles[ROLL] += ratio * cg.v_dmg_roll;
00955 }
00956 }
00957 }
00958
00959
00960 #if 0
00961 ratio = ( cg.time - cg.landTime) / FALL_TIME;
00962 if (ratio < 0)
00963 ratio = 0;
00964 angles[PITCH] += ratio * cg.fall_value;
00965 #endif
00966
00967
00968 VectorCopy( cg.predictedPlayerState.velocity, predictedVelocity );
00969
00970 delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[0]);
00971 angles[PITCH] += delta * cg_runpitch.value;
00972
00973 delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[1]);
00974 angles[ROLL] -= delta * cg_runroll.value;
00975
00976
00977
00978
00979 speed = cg.xyspeed > 200 ? cg.xyspeed : 200;
00980
00981 delta = cg.bobfracsin * cg_bobpitch.value * speed;
00982 if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
00983 delta *= 3;
00984 angles[PITCH] += delta;
00985 delta = cg.bobfracsin * cg_bobroll.value * speed;
00986 if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
00987 delta *= 3;
00988 if (cg.bobcycle & 1)
00989 delta = -delta;
00990 angles[ROLL] += delta;
00991
00992
00993
00994
00995 origin[2] += cg.predictedPlayerState.viewheight;
00996
00997
00998 timeDelta = cg.time - cg.duckTime;
00999 if ( timeDelta < DUCK_TIME) {
01000 cg.refdef.vieworg[2] -= cg.duckChange
01001 * (DUCK_TIME - timeDelta) / DUCK_TIME;
01002 }
01003
01004
01005 bob = cg.bobfracsin * cg.xyspeed * cg_bobup.value;
01006 if (bob > 6) {
01007 bob = 6;
01008 }
01009
01010 origin[2] += bob;
01011
01012
01013
01014 delta = cg.time - cg.landTime;
01015 if ( delta < LAND_DEFLECT_TIME ) {
01016 f = delta / LAND_DEFLECT_TIME;
01017 cg.refdef.vieworg[2] += cg.landChange * f;
01018 } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
01019 delta -= LAND_DEFLECT_TIME;
01020 f = 1.0 - ( delta / LAND_RETURN_TIME );
01021 cg.refdef.vieworg[2] += cg.landChange * f;
01022 }
01023
01024
01025 CG_StepOffset();
01026
01027
01028
01029 VectorAdd (origin, cg.kick_origin, origin);
01030
01031
01032 #if 0
01033 {
01034 #define NECK_LENGTH 8
01035 vec3_t forward, up;
01036
01037 cg.refdef.vieworg[2] -= NECK_LENGTH;
01038 AngleVectors( cg.refdef.viewangles, forward, NULL, up );
01039 VectorMA( cg.refdef.vieworg, 3, forward, cg.refdef.vieworg );
01040 VectorMA( cg.refdef.vieworg, NECK_LENGTH, up, cg.refdef.vieworg );
01041 }
01042 #endif
01043 }
01044
01045 static void CG_OffsetFighterView( void )
01046 {
01047 vec3_t vehFwd, vehRight, vehUp, backDir;
01048 vec3_t camOrg, camBackOrg;
01049 float horzOffset = cg_thirdPersonHorzOffset.value;
01050 float vertOffset = cg_thirdPersonVertOffset.value;
01051 float pitchOffset = cg_thirdPersonPitchOffset.value;
01052 float yawOffset = cg_thirdPersonAngle.value;
01053 float range = cg_thirdPersonRange.value;
01054 trace_t trace;
01055 centity_t *veh = &cg_entities[cg.predictedPlayerState.m_iVehicleNum];
01056
01057 AngleVectors( cg.refdef.viewangles, vehFwd, vehRight, vehUp );
01058
01059 if ( veh->m_pVehicle &&
01060 veh->m_pVehicle->m_pVehicleInfo->cameraOverride )
01061 {
01062 horzOffset = veh->m_pVehicle->m_pVehicleInfo->cameraHorzOffset;
01063 vertOffset = veh->m_pVehicle->m_pVehicleInfo->cameraVertOffset;
01064
01065 pitchOffset = veh->m_pVehicle->m_pVehicleInfo->cameraPitchOffset;
01066 range = veh->m_pVehicle->m_pVehicleInfo->cameraRange;
01067 if ( veh->playerState->hackingTime )
01068 {
01069 horzOffset += (((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * -80.0f;
01070 range += fabs(((float)veh->playerState->hackingTime)/MAX_STRAFE_TIME) * 100.0f;
01071 }
01072 }
01073
01074
01075 VectorMA( cg.refdef.vieworg, horzOffset, vehRight, camOrg );
01076 VectorMA( camOrg, vertOffset, vehUp, camOrg );
01077
01078
01079 CG_Trace(&trace, cg.refdef.vieworg, cameramins, cameramaxs, camOrg, cg.snap->ps.clientNum, MASK_CAMERACLIP);
01080 if ( trace.fraction < 1.0 )
01081 {
01082 VectorCopy( trace.endpos, camOrg );
01083 }
01084
01085
01086 cg.refdef.viewangles[YAW] += yawOffset;
01087 cg.refdef.viewangles[PITCH] += pitchOffset;
01088
01089
01090 AngleVectors( cg.refdef.viewangles, backDir, NULL, NULL );
01091 VectorScale( backDir, -1, backDir );
01092
01093 VectorMA( camOrg, range, backDir, camBackOrg );
01094
01095
01096 CG_Trace(&trace, camOrg, cameramins, cameramaxs, camBackOrg, cg.snap->ps.clientNum, MASK_CAMERACLIP);
01097 VectorCopy( trace.endpos, camOrg );
01098
01099
01100
01101 VectorCopy(camOrg, cg.refdef.vieworg);
01102 }
01103
01104
01105 void CG_ZoomDown_f( void ) {
01106 if ( cg.zoomed ) {
01107 return;
01108 }
01109 cg.zoomed = qtrue;
01110 cg.zoomTime = cg.time;
01111 }
01112
01113 void CG_ZoomUp_f( void ) {
01114 if ( !cg.zoomed ) {
01115 return;
01116 }
01117 cg.zoomed = qfalse;
01118 cg.zoomTime = cg.time;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130 qboolean CG_CalcFOVFromX( float fov_x )
01131 {
01132 float x;
01133
01134
01135
01136 float fov_y;
01137 qboolean inwater;
01138
01139 x = cg.refdef.width / tan( fov_x / 360 * M_PI );
01140 fov_y = atan2( cg.refdef.height, x );
01141 fov_y = fov_y * 360 / M_PI;
01142
01143
01144
01145
01146
01147
01148 #if 0
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 #else
01164 inwater = qfalse;
01165 #endif
01166
01167
01168
01169 cg.refdef.fov_x = fov_x;
01170 cg.refdef.fov_y = fov_y;
01171
01172 #ifdef _XBOX
01173 if(cg.widescreen)
01174 cg.refdef.fov_x *= 1.125f;
01175