Ticket #36: 3rd_person_camera.patch
| File 3rd_person_camera.patch, 10.6 KB (added by Carsten, 21 months ago) |
|---|
-
Ca3DE/Client/ClientWorld.cpp
29 29 #include "../NetConst.hpp" 30 30 #include "../Both/EntityManager.hpp" 31 31 #include "ClipSys/CollisionModel_static.hpp" 32 #include "ClipSys/TraceResult.hpp" 32 33 #include "ConsoleCommands/ConVar.hpp" 34 #include "MaterialSystem/Material.hpp" 33 35 #include "MaterialSystem/Renderer.hpp" 36 #include "Math3D/Angles.hpp" 34 37 #include "Math3D/Matrix.hpp" 35 38 #include "Network/Network.hpp" 36 39 #include "SceneGraph/Node.hpp" … … 324 327 325 328 void CaClientWorldT::Draw(float FrameTime, const EntityStateT* DrawState) 326 329 { 330 // Below are three pre-set variants of a third person camera. 331 // The first is aiming at the player directly. It's the most simple one, 332 // but cannot be used in shooters, since you can't see where you're aiming. 333 // The second one is aiming over the players head, similar to Tomb Raider. 334 // The third is an over-the-shoulder view, as you see it in many current shooters. 335 Vector3dT ThirdPersonOrigin=DrawState->Origin; 336 const double TO_RAD=cf::math::AnglesdT::PI/32768.0; 337 338 static ConVarT ThirdPersonVariant("cl_3rdPerson", 0, ConVarT::FLAG_MAIN_EXE, "Determines the third person camera mode that should be used (0, 1 or 2).", 0, 2); 339 340 switch (ThirdPersonVariant.GetValueInt()) 341 { 342 case 0: 343 { 344 // No shooting. 345 const double CameraDistance=1600.0; 346 const double CameraOffset = 300.0; 347 348 ThirdPersonOrigin.x -= sin(DrawState->Heading*TO_RAD) * CameraDistance * cos(DrawState->Pitch*TO_RAD); 349 ThirdPersonOrigin.y -= cos(DrawState->Heading*TO_RAD) * CameraDistance * cos(DrawState->Pitch*TO_RAD); 350 ThirdPersonOrigin.z += sin(DrawState->Pitch *TO_RAD) * CameraDistance; 351 break; 352 } 353 354 case 1: 355 { 356 // Over the head. 357 const double CameraDistance=1600.0; 358 const double CameraOffset = 300.0; 359 360 ThirdPersonOrigin.x -= sin(DrawState->Heading*TO_RAD) * CameraDistance * cos(DrawState->Pitch*TO_RAD); 361 ThirdPersonOrigin.y -= cos(DrawState->Heading*TO_RAD) * CameraDistance * cos(DrawState->Pitch*TO_RAD); 362 ThirdPersonOrigin.z = (ThirdPersonOrigin.z + CameraOffset) + sin(DrawState->Pitch*TO_RAD) * CameraDistance; 363 break; 364 } 365 366 default: 367 { 368 // Over the shoulder. 369 const double CameraDistance=600.0; 370 const double CameraOffset =150.0; 371 372 ThirdPersonOrigin.x -= CameraOffset * sin(DrawState->Heading*TO_RAD - cf::math::AnglesdT::PI/2.0); 373 ThirdPersonOrigin.y -= CameraOffset * cos(DrawState->Heading*TO_RAD - cf::math::AnglesdT::PI/2.0); 374 375 ThirdPersonOrigin.x -= sin(DrawState->Heading*TO_RAD) * CameraDistance * cos(DrawState->Pitch*TO_RAD); 376 ThirdPersonOrigin.y -= cos(DrawState->Heading*TO_RAD) * CameraDistance * cos(DrawState->Pitch*TO_RAD); 377 ThirdPersonOrigin.z += sin(DrawState->Pitch *TO_RAD) * CameraDistance; 378 break; 379 } 380 } 381 382 // This checks for collision between camera an world, and moves the camera closer to the player if necessary. 383 cf::ClipSys::TraceResultT Result; 384 Ca3DEWorld->CollModel->TraceRay(DrawState->Origin, ThirdPersonOrigin - DrawState->Origin, MaterialT::Clip_AllBlocking, Result); 385 386 Result.Fraction*=0.85; // Otherwise we would still be able to see through the walls. 387 ThirdPersonOrigin=ThirdPersonOrigin*Result.Fraction + DrawState->Origin*(1.0-Result.Fraction); 388 389 327 390 MatSys::Renderer->SetMatrix(MatSys::RendererI::MODEL_TO_WORLD, MatrixT()); 328 391 329 392 MatSys::Renderer->SetMatrix(MatSys::RendererI::WORLD_TO_VIEW, MatrixT::GetRotateXMatrix(-90.0f)); // Start with the global Ca3DE coordinate system (not the OpenGL coordinate system). … … 336 399 #if SHL_ENABLED 337 400 MoveSHLSun(FrameTime); 338 401 #endif 339 MatSys::Renderer->Translate(MatSys::RendererI::WORLD_TO_VIEW, -float( DrawState->Origin.x), -float(DrawState->Origin.y), -float(DrawState->Origin.z));402 MatSys::Renderer->Translate(MatSys::RendererI::WORLD_TO_VIEW, -float(ThirdPersonOrigin.x), -float(ThirdPersonOrigin.y), -float(ThirdPersonOrigin.z)); 340 403 341 404 #if 0 // TODO: Move this into the scene graph. 342 405 #ifdef DEBUG … … 371 434 const float EyeOffsetZ=200.0f*sinf(TotalTime); 372 435 373 436 MatSys::Renderer->SetCurrentRenderAction(MatSys::RendererI::AMBIENT); 374 MatSys::Renderer->SetCurrentEyePosition(float( DrawState->Origin.x), float(DrawState->Origin.y), float(DrawState->Origin.z)+EyeOffsetZ); // Also required in some ambient shaders.437 MatSys::Renderer->SetCurrentEyePosition(float(ThirdPersonOrigin.x), float(ThirdPersonOrigin.y), float(ThirdPersonOrigin.z)+EyeOffsetZ); // Also required in some ambient shaders. 375 438 376 Ca3DEWorld->BspTree->DrawAmbientContrib( DrawState->Origin);439 Ca3DEWorld->BspTree->DrawAmbientContrib(ThirdPersonOrigin); 377 440 378 441 379 442 if (!CurrentFrame.IsValid) … … 393 456 } 394 457 395 458 // Draw the ambient contribution of the entities. 396 EntityManager.DrawEntities(OurEntityID, false, DrawState->Origin, CurrentFrame.EntityIDsInPVS);459 EntityManager.DrawEntities(OurEntityID, false, ThirdPersonOrigin, CurrentFrame.EntityIDsInPVS); 397 460 398 461 399 462 … … 446 509 // Our entity casts shadows, except when the light source is he himself. 447 510 EntityManager.DrawEntities(OurEntityID==BaseEntity->ID ? OurEntityID : 0xFFFFFFFF /* an ugly, dirty, kaum nachvollziehbarer hack */, 448 511 OurEntityID==BaseEntity->ID, 449 DrawState->Origin,512 ThirdPersonOrigin, 450 513 CurrentFrame.EntityIDsInPVS); 451 514 // } 452 515 // else … … 467 530 Ca3DEWorld->BspTree->DrawLightSourceContrib(DrawState->Origin, LightPosition); 468 531 EntityManager.DrawEntities(OurEntityID, 469 532 false, 470 DrawState->Origin,533 ThirdPersonOrigin, 471 534 CurrentFrame.EntityIDsInPVS); 472 535 } 473 536 … … 476 539 MatSys::Renderer->SetCurrentRenderAction(MatSys::RendererI::AMBIENT); 477 540 478 541 // Render translucent nodes back-to-front. 479 Ca3DEWorld->BspTree->DrawTranslucentContrib( DrawState->Origin);542 Ca3DEWorld->BspTree->DrawTranslucentContrib(ThirdPersonOrigin); 480 543 481 544 // Zuletzt halbtransparente HUD-Elemente, Fonts usw. zeichnen. 482 545 EntityManager.PostDrawEntities(FrameTime, OurEntityID, CurrentFrame.EntityIDsInPVS); -
Games/DeathMatch/Code/HumanPlayer.cpp
951 951 // of the local client, which gets *predicted*. Thus, there is no point in modifying the 'State' member variable. 952 952 // Otherwise however, when 'FirstPersonView==false', this is usually a human player entity 953 953 // of another client, which is *NOT* predicted. Thus, we may modify the 'State' member variable up to a certain extend. 954 if (FirstPersonView) 955 { 956 // Draw "view" model of the weapon 957 if (State.HaveWeapons & (1 << State.ActiveWeaponSlot)) // Only draw the active weapon if we actually "have" it 958 { 959 Vector3fT LgtPos(MatSys::Renderer->GetCurrentLightSourcePosition()); 960 Vector3fT EyePos(MatSys::Renderer->GetCurrentEyePosition()); 954 if (State.StateOfExistance!=StateOfExistance_Alive && State.StateOfExistance!=StateOfExistance_Dead) return; 961 955 962 // The translation is not actually required, but gives the weapon a very nice 'shifting' effect when the player looks up/down. 963 // If there ever is a problem with view model distortion, this may be a cause. 964 LgtPos.z+=0.5f; 965 EyePos.z+=0.5f; 966 MatSys::Renderer->Translate(MatSys::RendererI::MODEL_TO_WORLD, 0.0f, 0.0f, -0.5f); 956 const float OffsetZ=(State.StateOfExistance!=StateOfExistance_Dead) ? -32.0f : -32.0f+float(State.Dimensions.Min.z+1728.8)/25.4f; 967 957 968 const float DegPitch=float(State.Pitch)/8192.0f*45.0f; 958 MatSys::Renderer->GetCurrentLightSourcePosition()[2]-=OffsetZ; 959 MatSys::Renderer->GetCurrentEyePosition ()[2]-=OffsetZ; 960 MatSys::Renderer->Translate(MatSys::RendererI::MODEL_TO_WORLD, 0.0f, 0.0f, OffsetZ); 969 961 970 LgtPos=LgtPos.GetRotY(-DegPitch); 971 EyePos=EyePos.GetRotY(-DegPitch); 972 MatSys::Renderer->RotateY(MatSys::RendererI::MODEL_TO_WORLD, DegPitch); 962 // Draw the own player body model and the "_p" (player) model of the active weapon as sub-model of the body. 963 ModelProxyT& PlayerModel=GetModelFromPlayerModelIndex(State.ModelIndex); 973 964 974 MatSys::Renderer->SetCurrentLightSourcePosition(LgtPos.x, LgtPos.y, LgtPos.z); 975 MatSys::Renderer->SetCurrentEyePosition(EyePos.x, EyePos.y, EyePos.z); 976 977 978 ModelProxyT& WeaponModelView=CarriedWeaponT::GetCarriedWeapon(State.ActiveWeaponSlot)->GetViewWeaponModel(); 979 980 WeaponModelView.Draw(State.ActiveWeaponSequNr, State.ActiveWeaponFrameNr, LodDist); 981 } 982 } 983 else 984 { 985 if (State.StateOfExistance!=StateOfExistance_Alive && State.StateOfExistance!=StateOfExistance_Dead) return; 986 987 const float OffsetZ=(State.StateOfExistance!=StateOfExistance_Dead) ? -32.0f : -32.0f+float(State.Dimensions.Min.z+1728.8)/25.4f; 988 989 MatSys::Renderer->GetCurrentLightSourcePosition()[2]-=OffsetZ; 990 MatSys::Renderer->GetCurrentEyePosition ()[2]-=OffsetZ; 991 MatSys::Renderer->Translate(MatSys::RendererI::MODEL_TO_WORLD, 0.0f, 0.0f, OffsetZ); 992 993 // Draw the own player body model and the "_p" (player) model of the active weapon as sub-model of the body. 994 ModelProxyT& PlayerModel=GetModelFromPlayerModelIndex(State.ModelIndex); 995 996 PlayerModel.Draw(State.ModelSequNr, State.ModelFrameNr, LodDist, (State.HaveWeapons & (1 << State.ActiveWeaponSlot)) ? &CarriedWeaponT::GetCarriedWeapon(State.ActiveWeaponSlot)->GetPlayerWeaponModel() : NULL); 997 } 965 PlayerModel.Draw(State.ModelSequNr, State.ModelFrameNr, LodDist, (State.HaveWeapons & (1 << State.ActiveWeaponSlot)) ? &CarriedWeaponT::GetCarriedWeapon(State.ActiveWeaponSlot)->GetPlayerWeaponModel() : NULL); 998 966 } 999 967 1000 968
