Ticket #36: 3rd_person_camera.patch

File 3rd_person_camera.patch, 10.6 KB (added by Carsten, 21 months ago)
  • Ca3DE/Client/ClientWorld.cpp

     
    2929#include "../NetConst.hpp" 
    3030#include "../Both/EntityManager.hpp" 
    3131#include "ClipSys/CollisionModel_static.hpp" 
     32#include "ClipSys/TraceResult.hpp" 
    3233#include "ConsoleCommands/ConVar.hpp" 
     34#include "MaterialSystem/Material.hpp" 
    3335#include "MaterialSystem/Renderer.hpp" 
     36#include "Math3D/Angles.hpp" 
    3437#include "Math3D/Matrix.hpp" 
    3538#include "Network/Network.hpp" 
    3639#include "SceneGraph/Node.hpp" 
     
    324327 
    325328void CaClientWorldT::Draw(float FrameTime, const EntityStateT* DrawState) 
    326329{ 
     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 
    327390    MatSys::Renderer->SetMatrix(MatSys::RendererI::MODEL_TO_WORLD, MatrixT()); 
    328391 
    329392    MatSys::Renderer->SetMatrix(MatSys::RendererI::WORLD_TO_VIEW,  MatrixT::GetRotateXMatrix(-90.0f));          // Start with the global Ca3DE coordinate system (not the OpenGL coordinate system). 
     
    336399#if SHL_ENABLED 
    337400    MoveSHLSun(FrameTime); 
    338401#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)); 
    340403 
    341404#if 0   // TODO: Move this into the scene graph. 
    342405#ifdef DEBUG 
     
    371434    const float EyeOffsetZ=200.0f*sinf(TotalTime); 
    372435 
    373436    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. 
    375438 
    376     Ca3DEWorld->BspTree->DrawAmbientContrib(DrawState->Origin); 
     439    Ca3DEWorld->BspTree->DrawAmbientContrib(ThirdPersonOrigin); 
    377440 
    378441 
    379442    if (!CurrentFrame.IsValid) 
     
    393456    } 
    394457 
    395458    // Draw the ambient contribution of the entities. 
    396     EntityManager.DrawEntities(OurEntityID, false, DrawState->Origin, CurrentFrame.EntityIDsInPVS); 
     459    EntityManager.DrawEntities(OurEntityID, false, ThirdPersonOrigin, CurrentFrame.EntityIDsInPVS); 
    397460 
    398461 
    399462 
     
    446509                // Our entity casts shadows, except when the light source is he himself. 
    447510                EntityManager.DrawEntities(OurEntityID==BaseEntity->ID ? OurEntityID : 0xFFFFFFFF /* an ugly, dirty, kaum nachvollziehbarer hack */, 
    448511                                           OurEntityID==BaseEntity->ID, 
    449                                            DrawState->Origin, 
     512                                           ThirdPersonOrigin, 
    450513                                           CurrentFrame.EntityIDsInPVS); 
    451514         // } 
    452515         // else 
     
    467530        Ca3DEWorld->BspTree->DrawLightSourceContrib(DrawState->Origin, LightPosition); 
    468531        EntityManager.DrawEntities(OurEntityID, 
    469532                                   false, 
    470                                    DrawState->Origin, 
     533                                   ThirdPersonOrigin, 
    471534                                   CurrentFrame.EntityIDsInPVS); 
    472535    } 
    473536 
     
    476539    MatSys::Renderer->SetCurrentRenderAction(MatSys::RendererI::AMBIENT); 
    477540 
    478541    // Render translucent nodes back-to-front. 
    479     Ca3DEWorld->BspTree->DrawTranslucentContrib(DrawState->Origin); 
     542    Ca3DEWorld->BspTree->DrawTranslucentContrib(ThirdPersonOrigin); 
    480543 
    481544    // Zuletzt halbtransparente HUD-Elemente, Fonts usw. zeichnen. 
    482545    EntityManager.PostDrawEntities(FrameTime, OurEntityID, CurrentFrame.EntityIDsInPVS); 
  • Games/DeathMatch/Code/HumanPlayer.cpp

     
    951951    // of the local client, which gets *predicted*. Thus, there is no point in modifying the 'State' member variable. 
    952952    // Otherwise however, when 'FirstPersonView==false', this is usually a human player entity 
    953953    // 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; 
    961955 
    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; 
    967957 
    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); 
    969961 
    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); 
    973964 
    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); 
    998966} 
    999967 
    1000968