BVB Source Codes

CRYENGINE Show VehicleViewSteer.cpp Source code

Return Download CRYENGINE: download VehicleViewSteer.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.    Description: Implements a third person view for vehicles
  8.  
  9. *************************************************************************/
  10. #include "StdAfx.h"
  11.  
  12. #include "IViewSystem.h"
  13. #include "IVehicleSystem.h"
  14. #include "VehicleSeat.h"
  15. #include "IWeapon.h"
  16. #include "VehicleViewSteer.h"
  17. #include "IActorSystem.h"
  18.  
  19. #include <CryMath/Cry_GeoIntersect.h>
  20.  
  21. const char* CVehicleViewSteer::m_name = "SteerThirdPerson";
  22.  
  23. static float g_SteerCameraRadius = 0.2f;
  24.  
  25. //------------------------------------------------------------------------
  26. CVehicleViewSteer::CVehicleViewSteer()
  27. {
  28.         m_pAimPart = NULL;
  29.         m_position.zero();
  30.         m_angReturnSpeed = 0.0f;
  31.         m_angReturnSpeed1 = 0.0f;
  32.         m_angReturnSpeed2 = 0.0f;
  33.         m_angSpeedCorrection = 0.0f;
  34.         m_angSpeedCorrection0 = 0.0f;
  35.         m_lookAt0 = Vec3(0.0f, 0.0f, 1.5f);
  36.         m_localSpaceCameraOffset = Vec3(0.0f, -3.0f, 1.0f);
  37.         m_maxRotation.Set(10.0f, 0.0f, 90.0f);
  38.         m_maxRotation2.zero();
  39.         m_stickSensitivity.Set(0.5f, 0.5f, 0.5f);
  40.         m_stickSensitivity2.Set(0.5f, 0.5f, 0.5f);
  41.         m_inheritedElev = 0.2f;
  42.         m_pivotOffset = 0.f;
  43.         m_flags = eVCam_goingForwards | eVCam_canRotate;
  44.         m_forwardFlags = eVCam_rotationSpring | eVCam_rotationClamp;
  45.         m_backwardsFlags = m_forwardFlags;
  46.         m_radiusRelaxRate = 10.f;
  47.         m_radiusDampRate = 1.f;
  48.         m_radiusVel = 0.0f;
  49.         m_radiusVelInfluence = 0.1f;
  50.         m_radiusMin = 0.9f;
  51.         m_radiusMax = 1.1f;
  52.         m_radius = 1.0f;
  53.         m_curYaw = 0.0f;
  54. }
  55.  
  56. //------------------------------------------------------------------------
  57. CVehicleViewSteer::~CVehicleViewSteer()
  58. {
  59. }
  60.  
  61. static void getFlag(CVehicleParams& params, const char* key, int& flags, int flag)
  62. {
  63.         int tmp = flags & flag;
  64.         params.getAttr(key, tmp);
  65.         if (tmp)
  66.                 flags |= flag;
  67.         else
  68.                 flags &= ~flag;
  69. }
  70.  
  71. //------------------------------------------------------------------------
  72. bool CVehicleViewSteer::Init(IVehicleSeat* pSeat, const CVehicleParams& table)
  73. {
  74.         if (!CVehicleViewBase::Init(pSeat, table))
  75.                 return false;
  76.  
  77.         m_pAimPart = pSeat->GetAimPart();
  78.  
  79.         CVehicleParams params = table.findChild(m_name);
  80.         if (!params)
  81.                 return false;
  82.  
  83.         CVehicleParams posParams = params.findChild("Pos");
  84.         CVehicleParams rotationParams = params.findChild("Rotation");
  85.         CVehicleParams motionParams = params.findChild("Motion");
  86.         CVehicleParams backwardsParams = params.findChild("Backwards");
  87.         CVehicleParams radiusParams = params.findChild("Radius");
  88.  
  89.         if (posParams)
  90.         {
  91.                 posParams.getAttr("offset", m_localSpaceCameraOffset);
  92.                 posParams.getAttr("aim", m_lookAt0);
  93.                 posParams.getAttr("pivotOffset", m_pivotOffset);
  94.         }
  95.  
  96.         if (rotationParams)
  97.         {
  98.                 rotationParams.getAttr("rotationMax", m_maxRotation);
  99.                 if (rotationParams.haveAttr("rotationMax2"))
  100.                 {
  101.                         rotationParams.getAttr("rotationMax2", m_maxRotation2);
  102.                 }
  103.                 else
  104.                 {
  105.                         m_maxRotation2 = m_maxRotation / 3.0f;
  106.                 }
  107.                 m_maxRotation = DEG2RAD(m_maxRotation);
  108.                 m_maxRotation2 = DEG2RAD(m_maxRotation2);
  109.                 rotationParams.getAttr("stickSensitivity", m_stickSensitivity);
  110.                 rotationParams.getAttr("stickSensitivity2", m_stickSensitivity2);
  111.                 rotationParams.getAttr("inheritedElev", m_inheritedElev);
  112.                 getFlag(rotationParams, "canRotate", m_flags, eVCam_canRotate);
  113.                 m_inheritedElev = clamp_tpl(m_inheritedElev, 0.f, 1.f);
  114.         }
  115.  
  116.         if (motionParams)
  117.         {
  118.                 motionParams.getAttr("returnSpeed", m_angReturnSpeed1);
  119.                 motionParams.getAttr("returnSpeed2", m_angReturnSpeed2);
  120.                 motionParams.getAttr("angFollow", m_angSpeedCorrection0);
  121.         }
  122.  
  123.         if (backwardsParams)
  124.         {
  125.                 getFlag(backwardsParams, "clamp", m_backwardsFlags, eVCam_rotationClamp);
  126.                 getFlag(backwardsParams, "returnSpring", m_backwardsFlags, eVCam_rotationSpring);
  127.         }
  128.  
  129.         if (radiusParams)
  130.         {
  131.                 radiusParams.getAttr("min", m_radiusMin);
  132.                 radiusParams.getAttr("max", m_radiusMax);
  133.                 radiusParams.getAttr("relaxRate", m_radiusRelaxRate);
  134.                 radiusParams.getAttr("dampRate", m_radiusDampRate);
  135.                 radiusParams.getAttr("velInfluence", m_radiusVelInfluence);
  136.         }
  137.  
  138.         Reset();
  139.         return true;
  140. }
  141.  
  142. //------------------------------------------------------------------------
  143. bool CVehicleViewSteer::Init(CVehicleSeat* pSeat)
  144. {
  145.         if (!CVehicleViewBase::Init(pSeat))
  146.                 return false;
  147.  
  148.         Reset();
  149.         return true;
  150. }
  151.  
  152. //------------------------------------------------------------------------
  153. void CVehicleViewSteer::Reset()
  154. {
  155.         CVehicleViewBase::Reset();
  156.  
  157.         IEntity* pEntity = m_pVehicle->GetEntity();
  158.         assert(pEntity);
  159.         m_position = pEntity->GetWorldTM() * m_localSpaceCameraOffset;
  160.         Vec3 entityPos = pEntity->GetPos();
  161.         CalcLookAt(pEntity->GetWorldTM());
  162.         m_lastOffset = m_position - m_lookAt;
  163.         m_lastOffsetBeforeElev = m_lastOffset;
  164.         m_angReturnSpeed = 0.f;
  165.         m_angSpeedCorrection = 0.f;
  166.         // Going Forwards
  167.         m_flags &= ~m_backwardsFlags;
  168.         m_flags |= eVCam_goingForwards | m_forwardFlags;
  169.         m_radius = fabsf(m_localSpaceCameraOffset.y);
  170.         m_curYaw = 0.f;
  171.         m_lastVehVel.zero();
  172.         m_radiusVel = 0.f;
  173. }
  174.  
  175. void CVehicleViewSteer::CalcLookAt(const Matrix34& entityTM)
  176. {
  177.         Vec3 tmp(m_lookAt0.x, m_lookAt0.y, m_lookAt0.z + m_pivotOffset);
  178.         m_lookAt = entityTM * tmp;
  179.         m_lookAt.z -= m_pivotOffset;
  180. }
  181.  
  182. //------------------------------------------------------------------------
  183. void CVehicleViewSteer::OnAction(const TVehicleActionId actionId, int activationMode, float value)
  184. {
  185.         CVehicleViewBase::OnAction(actionId, activationMode, value);
  186.  
  187.         if (!(m_flags & eVCam_canRotate))
  188.         {
  189.                 m_rotatingAction.zero();
  190.         }
  191. }
  192.  
  193. //------------------------------------------------------------------------
  194. void CVehicleViewSteer::OnStartUsing(EntityId passengerId)
  195. {
  196.         CVehicleViewBase::OnStartUsing(passengerId);
  197. }
  198.  
  199. //------------------------------------------------------------------------
  200. void CVehicleViewSteer::OnStopUsing()
  201. {
  202.         CVehicleViewBase::OnStopUsing();
  203. }
  204.  
  205. //------------------------------------------------------------------------
  206. void CVehicleViewSteer::Update(float dt)
  207. {
  208.         IEntity* pEntity = m_pVehicle->GetEntity();
  209.         assert(pEntity);
  210.  
  211.         IVehicleMovement* pVehicleMovement = m_pVehicle->GetMovement();
  212.         if (pVehicleMovement == NULL)
  213.                 return;
  214.  
  215.         IPhysicalEntity* pPhysEntity = pEntity->GetPhysics();
  216.         if (!pPhysEntity)
  217.                 return;
  218.  
  219.         pe_status_dynamics dynStatus;
  220.         pPhysEntity->GetStatus(&dynStatus);
  221.  
  222.         SMovementState movementState;
  223.         pVehicleMovement->GetMovementState(movementState);
  224.         const float pedal = pVehicleMovement->GetEnginePedal();
  225.         const float maxSpeed = movementState.maxSpeed;
  226.         const Matrix34& pose = m_pAimPart ? m_pAimPart->GetWorldTM() : pEntity->GetWorldTM();
  227.         const Vec3 entityPos = pose.GetColumn3();
  228.         const Vec3 xAxis = pose.GetColumn0();
  229.         const Vec3 yAxis = pose.GetColumn1();
  230.         const Vec3 zAxis = pose.GetColumn2();
  231.         const float forwardSpeed = dynStatus.v.dot(yAxis);
  232.         const float speedNorm = clamp_tpl(forwardSpeed / maxSpeed, 0.0f, 1.0f);
  233.         const Vec3 maxRotation = m_maxRotation + speedNorm * (m_maxRotation2 - m_maxRotation);
  234.  
  235.         CalcLookAt(pose);
  236.         if (m_lookAt.IsValid())
  237.         {
  238.                 if (!m_lastOffset.IsValid())
  239.                 {
  240.                         m_position = pose * m_localSpaceCameraOffset;
  241.                         m_lastOffset = m_position - m_lookAt;
  242.                         m_lastOffsetBeforeElev = m_lastOffset;
  243.                 }
  244.  
  245.                 Vec3 offset = m_lastOffsetBeforeElev;
  246.  
  247.                 if (pedal < 0.1f && forwardSpeed < 1.0f)
  248.                 {
  249.                         // Going Backwards
  250.                         m_flags &= ~(eVCam_goingForwards | m_forwardFlags);
  251.                         m_flags |= m_backwardsFlags;
  252.                 }
  253.  
  254.                 if (offset.dot(yAxis) < 0.8f && forwardSpeed > 1.f)
  255.                 {
  256.                         // Going Forwards
  257.                         m_flags &= ~m_backwardsFlags;
  258.                         m_flags |= eVCam_goingForwards | m_forwardFlags;
  259.                 }
  260.  
  261.                 float sensitivity = (1.f - speedNorm) * m_stickSensitivity.z + speedNorm * m_stickSensitivity2.z;
  262.                 float rotate = -m_rotatingAction.z * sensitivity;
  263.                 rotate = rotate * dt;
  264.  
  265.                 if (zAxis.z > 0.1f)
  266.                 {
  267.                         // Safe to update curYaw
  268.                         Vec3 projectedX = xAxis;
  269.                         projectedX.z = 0.f;
  270.                         Vec3 projectedY = yAxis;
  271.                         projectedY.z = 0.f;
  272.                         const float newYaw = atan2_tpl(offset.dot(projectedX), -(offset.dot(projectedY)));
  273.                         const float maxChange = DEG2RAD(270.f) * dt;
  274.                         const float delta = clamp_tpl(newYaw - m_curYaw, -maxChange, +maxChange);
  275.                         m_curYaw += delta;
  276.                 }
  277.  
  278.                 // Rotation Action
  279.                 {
  280.                         if (m_flags & eVCam_rotationClamp)
  281.                         {
  282.                                 float newYaw = clamp_tpl(m_curYaw + rotate, -maxRotation.z, +maxRotation.z);
  283.                                 rotate = newYaw - m_curYaw;
  284.                                 rotate = clamp_tpl(newYaw - m_curYaw, -fabsf(rotate), +fabsf(rotate));
  285.                                 m_rotation.z += rotate;
  286.                         }
  287.                         else
  288.                         {
  289.                                 m_rotation.z = 0.f;
  290.                         }
  291.  
  292.                         if (speedNorm > 0.1f)
  293.                         {
  294.                                 float reduce = dt * 1.f;
  295.                                 m_rotation.z = m_rotation.z - reduce * m_rotation.z / (fabsf(m_rotation.z) + reduce);
  296.                         }
  297.                 }
  298.  
  299.                 // Ang Spring
  300.                 {
  301.                         float angSpeedCorrection = dt * dt * m_angSpeedCorrection / (dt * m_angSpeedCorrection + 1.f) * dynStatus.w.z;
  302.                         if ((m_flags & eVCam_rotationSpring) == 0)
  303.                         {
  304.                                 m_angReturnSpeed = 0.f;
  305.                                 angSpeedCorrection = 0.f;
  306.                         }
  307.  
  308.                         float difference = m_rotation.z - m_curYaw;
  309.                         float relax = difference * (m_angReturnSpeed * dt) / ((m_angReturnSpeed * dt) + 1.f);
  310.  
  311.                         const float delta = +relax + angSpeedCorrection + rotate;
  312.                         m_curYaw += delta;
  313.  
  314.                         Matrix33 rot = Matrix33::CreateRotationZ(delta);
  315.                         offset = rot * offset;
  316.  
  317.                         // Lerp the spring speed
  318.                         float angSpeedTarget = m_angReturnSpeed1 + speedNorm * (m_angReturnSpeed2 - m_angReturnSpeed1);
  319.                         m_angReturnSpeed += (angSpeedTarget - m_angReturnSpeed) * (dt / (dt + 0.3f));
  320.                         m_angSpeedCorrection += (m_angSpeedCorrection0 - m_angSpeedCorrection) * (dt / (dt + 0.3f));
  321.                 }
  322.  
  323.                 if (!offset.IsValid()) offset = m_lastOffset;
  324.  
  325.                 // Velocity influence
  326.                 Vec3 displacement = -((2.f - speedNorm) * dt) * dynStatus.v;// - yAxis*(0.0f*speedNorm*(yAxis.dot(dynStatus.v))));
  327.  
  328.                 float dot = offset.dot(displacement);
  329.                 if (dot < 0.f)
  330.                 {
  331.                         displacement = displacement + offset * -0.1f * (offset.dot(displacement) / offset.GetLengthSquared());
  332.                 }
  333.                 offset = offset + displacement;
  334.  
  335.                 const float radius0 = fabsf(m_localSpaceCameraOffset.y);
  336.                 const float minRadius = radius0 * m_radiusMin;
  337.                 const float maxRadius = radius0 * m_radiusMax;
  338.                 float radiusXY = sqrtf(sqr(offset.x) + sqr(offset.y));
  339.  
  340.                 Vec3 offsetXY = offset;
  341.                 offsetXY.z = 0.f;
  342.                 Vec3 accelerationV = (dynStatus.v - m_lastVehVel);
  343.                 float acceleration = offsetXY.dot(accelerationV) / radiusXY;
  344.  
  345.                 m_lastVehVel = dynStatus.v;
  346.                 m_radiusVel -= acceleration;
  347.                 m_radius += m_radiusVel * dt - dt * m_radiusVelInfluence * offsetXY.dot(dynStatus.v) / radiusXY;
  348.                 m_radiusVel *= expf(-dt * m_radiusDampRate);
  349.                 m_radius += (radius0 - m_radius) * (dt * m_radiusRelaxRate) / (dt * m_radiusRelaxRate + 1.f);
  350.                 m_radius = clamp_tpl(m_radius, minRadius, maxRadius);
  351.                 offset = offset * (m_radius / radiusXY);
  352.  
  353.                 // Vertical motion
  354.                 float targetOffsetHeight = m_localSpaceCameraOffset.z * (m_radius / radius0);
  355.                 float oldOffsetHeight = offset.z;
  356.                 offset.z += (targetOffsetHeight - offset.z) * (dt / (dt + 0.3f));
  357.                 Limit(offset.z, targetOffsetHeight - 2.f, targetOffsetHeight + 2.f);
  358.                 float verticalChange = offset.z - oldOffsetHeight;
  359.  
  360.                 m_lastOffsetBeforeElev = offset;
  361.  
  362.                 // Add up and down camera tilt
  363.                 {
  364.                         offset.z -= verticalChange;
  365.                         m_rotation.x += dt * m_stickSensitivity.x * m_rotatingAction.x;
  366.                         m_rotation.x = clamp_tpl(m_rotation.x, -maxRotation.x, +maxRotation.x);
  367.  
  368.                         float elevAngleVehicle = m_inheritedElev * yAxis.z;     // yAxis.z == approx elevation angle
  369.  
  370.                         float elevationAngle = m_rotation.x - elevAngleVehicle;
  371.  
  372.                         float sinElev, cosElev;
  373.                         sincos_tpl(elevationAngle, &sinElev, &cosElev);
  374.                         float horizLen = sqrtf(offset.GetLengthSquared2D());
  375.                         float horizLenNew = horizLen * cosElev - sinElev * offset.z;
  376.                         if (horizLen > 1e-4f)
  377.                         {
  378.                                 horizLenNew /= horizLen;
  379.                                 offset.x *= horizLenNew;
  380.                                 offset.y *= horizLenNew;
  381.                                 offset.z = offset.z * cosElev + sinElev * horizLen;
  382.                         }
  383.                         offset.z += verticalChange;
  384.                 }
  385.  
  386.                 if (!offset.IsValid()) offset = m_lastOffset;
  387.  
  388.                 m_position = m_lookAt + offset;
  389.  
  390.                 // Perform world intersection test.
  391.                 {
  392.                         // Initialise sphere and direction.
  393.                         primitives::sphere sphere;
  394.  
  395.                         sphere.center = m_lookAt;
  396.                         sphere.r = g_SteerCameraRadius;
  397.  
  398.                         Vec3 direction = m_position - m_lookAt;
  399.  
  400.                         // Calculate camera bounds.
  401.                         AABB localBounds;
  402.  
  403.                         //Get the bounding box of the model which is in the first place of the render nodes
  404.                         m_pVehicle->GetEntity()->GetRenderNode()->GetLocalBounds(localBounds);
  405.  
  406.                         const float cameraBoundsScale = 0.75f;
  407.  
  408.                         localBounds.min *= cameraBoundsScale;
  409.                         localBounds.max *= cameraBoundsScale;
  410.  
  411.                         OBB cameraBounds;
  412.  
  413.                         Matrix34 worldTM = m_pVehicle->GetEntity()->GetWorldTM();
  414.  
  415.                         cameraBounds.SetOBBfromAABB(Matrix33(worldTM), localBounds);
  416.  
  417.                         // Try to find point on edge of camera bounds to begin swept sphere intersection test.
  418.                         Vec3 rayBoxIntersect;
  419.  
  420.                         if (Intersect::Ray_OBB(Ray(m_position, -direction), worldTM.GetTranslation(), cameraBounds, rayBoxIntersect) > 0)
  421.                         {
  422.                                 Vec3 temp = m_position - rayBoxIntersect;
  423.  
  424.                                 if (direction.Dot(temp) > 0.0f)
  425.                                 {
  426.                                         sphere.center = rayBoxIntersect;
  427.                                         direction = temp;
  428.                                 }
  429.                         }
  430.  
  431.                         // Perform swept sphere intersection test against world.
  432.                         geom_contact* pContact = NULL;
  433.  
  434.                         IPhysicalEntity* pSkipEntities[10];
  435.  
  436.                         float distance = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, direction, ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid,
  437.                                 &pContact, 0, (geom_colltype_player << rwi_colltype_bit) | rwi_stop_at_pierceable, 0, 0, 0,
  438.                                 pSkipEntities, m_pVehicle->GetSkipEntities(pSkipEntities, 10));
  439.  
  440.                         if (distance > 0.0f)
  441.                         {
  442.                                 // Sweep intersects world so calculate new offset.
  443.                                 offset = (sphere.center + (direction.GetNormalizedSafe() * distance)) - m_lookAt;
  444.                         }
  445.                 }
  446.  
  447.                 Interpolate(m_lastOffset, offset, 10.f, dt);
  448.  
  449.                 m_position = m_lookAt + m_lastOffset;
  450.         }
  451.         else
  452.         {
  453.                 CRY_ASSERT_MESSAGE(0, "camera will fail because lookat position is invalid");
  454.         }
  455.  
  456.         m_rotatingAction.zero();
  457. }
  458.  
  459. //------------------------------------------------------------------------
  460. void CVehicleViewSteer::UpdateView(SViewParams& viewParams, EntityId playerId)
  461. {
  462.         static bool doUpdate = true;
  463.  
  464.         if (!doUpdate) return;
  465.  
  466.         if (m_position.IsValid())
  467.         {
  468.                 viewParams.position = m_position;
  469.         }
  470.         else
  471.         {
  472.                 CRY_ASSERT_MESSAGE(0, "camera position invalid");
  473.         }
  474.  
  475.         Vec3 dir = (m_lookAt - m_position).GetNormalizedSafe();
  476.         if (dir.IsValid() && dir.GetLengthSquared() > 0.01f)
  477.         {
  478.                 viewParams.rotation = Quat::CreateRotationVDir(dir);
  479.         }
  480.         else
  481.         {
  482.                 CRY_ASSERT_MESSAGE(0, "camera rotation invalid");
  483.         }
  484.  
  485.         // set view direction on actor
  486.         IActor* pActor = m_pSeat->GetPassengerActor(true);
  487.         if (pActor && pActor->IsClient())
  488.         {
  489.                 pActor->SetViewInVehicle(viewParams.rotation);
  490.         }
  491. }
  492.  
  493. //------------------------------------------------------------------------
  494. void CVehicleViewSteer::Serialize(TSerialize serialize, EEntityAspects aspects)
  495. {
  496.         CVehicleViewBase::Serialize(serialize, aspects);
  497.  
  498.         if (serialize.GetSerializationTarget() != eST_Network)
  499.         {
  500.                 serialize.Value("position", m_position);
  501.         }
  502. }
  503.  
  504. void CVehicleViewSteer::OffsetPosition(const Vec3& delta)
  505. {
  506. #ifdef SEG_WORLD
  507.         m_position += delta;
  508. #endif
  509. }
  510.  
  511. DEFINE_VEHICLEOBJECT(CVehicleViewSteer);
  512.  
downloadVehicleViewSteer.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top