BVB Source Codes

CRYENGINE Show OwnerAngularInterpolatorNode.cpp Source code

Return Download CRYENGINE: download OwnerAngularInterpolatorNode.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4.  
  5. #include <CryMath/Cry_Math.h>
  6. #include <CryFlowGraph/IFlowBaseNode.h>
  7.  
  8. //////////////////////////////////////////////////////////////////////////
  9.  
  10. class CRotateEntityToExNode : public CFlowBaseNode<eNCT_Instanced>
  11. {
  12.         enum EValueType
  13.         {
  14.                 VT_SPEED = 0,
  15.                 VT_TIME
  16.         };
  17.         enum ECoordSys
  18.         {
  19.                 CS_PARENT = 0,
  20.                 CS_WORLD,
  21.                 CS_LOCAL
  22.         };
  23.  
  24.         CTimeValue m_startTime;
  25.         CTimeValue m_endTime;
  26.         CTimeValue m_localStartTime;   // updated every time that the target rotation is dynamically updated in middle of the movement. When there is no update, is equivalent to m_startTime
  27.         Quat       m_targetQuat;
  28.         Quat       m_sourceQuat;
  29.         ECoordSys  m_coorSys;
  30.         EValueType m_valueType;
  31.         bool       m_bIsMoving;
  32.  
  33. public:
  34.         CRotateEntityToExNode(SActivationInfo* pActInfo)
  35.                 : m_coorSys(CS_WORLD),
  36.                 m_valueType(VT_SPEED),
  37.                 m_bIsMoving(false)
  38.         {
  39.                 m_targetQuat.SetIdentity();
  40.                 m_sourceQuat.SetIdentity();
  41.         };
  42.  
  43.         IFlowNodePtr Clone(SActivationInfo* pActInfo)
  44.         {
  45.                 return new CRotateEntityToExNode(pActInfo);
  46.         }
  47.  
  48.         void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  49.         {
  50.                 ser.BeginGroup("Local");
  51.                 ser.Value("isMoving", m_bIsMoving);
  52.                 if (m_bIsMoving)
  53.                 {
  54.                         ser.Value("startTime", m_startTime);
  55.                         ser.Value("endTime", m_endTime);
  56.                         ser.Value("localStartTime", m_localStartTime);
  57.                         ser.Value("sourceQuat", m_sourceQuat);
  58.                         ser.Value("targetQuat", m_targetQuat);
  59.                 }
  60.                 ser.EndGroup();
  61.  
  62.                 if (ser.IsReading())
  63.                 {
  64.                         m_coorSys = (ECoordSys)GetPortInt(pActInfo, IN_COORDSYS);
  65.                         m_valueType = (EValueType)GetPortInt(pActInfo, IN_VALUETYPE);
  66.                 }
  67.         }
  68.  
  69.         enum EInPorts
  70.         {
  71.                 IN_DEST = 0,
  72.                 IN_DYN_DEST,
  73.                 IN_VALUETYPE,
  74.                 IN_VALUE,
  75.                 IN_COORDSYS,
  76.                 IN_START,
  77.                 IN_STOP
  78.         };
  79.         enum EOutPorts
  80.         {
  81.                 OUT_CURRENT = 0,
  82.                 OUT_CURRENT_RAD,
  83.                 OUT_START,
  84.                 OUT_STOP,
  85.                 OUT_FINISH,
  86.                 OUT_DONE
  87.         };
  88.  
  89.         virtual void GetConfiguration(SFlowNodeConfig& config)
  90.         {
  91.                 static const SInputPortConfig in_config[] = {
  92.                         InputPortConfig<Vec3>("Destination",   _HELP("Destination (degrees on each axis)")),
  93.                         InputPortConfig<bool>("DynamicUpdate", true,                                        _HELP("If dynamic update of Destination [follow-during-rotation] is allowed or not"),       _HELP("DynamicUpdate")),
  94.                         InputPortConfig<int>("ValueType",      0,                                           _HELP("Defines if the 'Value' input will be interpreted as speed or as time (duration)."),  _HELP("ValueType"),     _UICONFIG("enum_int:speed=0,time=1")),
  95.                         InputPortConfig<float>("Value",        0.f,                                         _HELP("Speed (Degrees/sec) or Time (duration in secs), depending on 'ValueType' input.")),
  96.                         InputPortConfig<int>("CoordSys",       0,                                           _HELP("Destination in Parent relative, World (absolute) or Local relative angles"),         _HELP("CoordSys"),      _UICONFIG("enum_int:Parent=0,World=1,Local=2")),
  97.                         InputPortConfig_Void("Start",          _HELP("Trigger this to start the movement")),
  98.                         InputPortConfig_Void("Stop",           _HELP("Trigger this to stop the movement")),
  99.                         { 0 }
  100.                 };
  101.                 static const SOutputPortConfig out_config[] = {
  102.                         OutputPortConfig<Vec3>("Current",    _HELP("Current Rotation in Degrees")),
  103.                         OutputPortConfig<Vec3>("CurrentRad", _HELP("Current Rotation in Radian")),
  104.                         OutputPortConfig_Void("Start",       _HELP("Triggered when start or reset inputs are triggered")),
  105.                         OutputPortConfig_Void("Stop",        _HELP("Triggered when stop input is triggered")),
  106.                         OutputPortConfig_Void("Finish",      _HELP("Triggered when destination is reached")),
  107.                         OutputPortConfig_Void("Done",        _HELP("Triggered when destination rotation is reached or rotation stopped")),
  108.                         { 0 }
  109.                 };
  110.                 config.sDescription = _HELP("Rotate an entity during a defined period of time or with a defined speed");
  111.                 config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_SUPPORTED;
  112.                 config.pInputPorts = in_config;
  113.                 config.pOutputPorts = out_config;
  114.                 config.SetCategory(EFLN_APPROVED);
  115.         }
  116.  
  117.         void DegToQuat(const Vec3& rotation, Quat& destQuat)
  118.         {
  119.                 Ang3 temp;
  120.  
  121.                 temp.x = Snap_s360(rotation.x);
  122.                 temp.y = Snap_s360(rotation.y);
  123.                 temp.z = Snap_s360(rotation.z);
  124.                 const Ang3 angRad = DEG2RAD(temp);
  125.                 destQuat.SetRotationXYZ(angRad);
  126.         }
  127.  
  128.         void SetRawEntityRot(IEntity* pEntity, const Quat& quat)
  129.         {
  130.                 if (m_coorSys == CS_WORLD && pEntity->GetParent())
  131.                 {
  132.                         Matrix34 tm(quat);
  133.                         tm.SetTranslation(pEntity->GetWorldPos());
  134.                         pEntity->SetWorldTM(tm);
  135.                 }
  136.                 else
  137.                         pEntity->SetRotation(quat);
  138.         }
  139.  
  140.         void UpdateCurrentRotOutputs(SActivationInfo* pActInfo, const Quat& quat)
  141.         {
  142.                 Ang3 angles(quat);
  143.                 Ang3 anglesDeg = RAD2DEG(angles);
  144.                 ActivateOutput(pActInfo, OUT_CURRENT_RAD, Vec3(angles));
  145.                 ActivateOutput(pActInfo, OUT_CURRENT, Vec3(anglesDeg));
  146.         }
  147.  
  148.         void PhysicStop(IEntity* pEntity, const Quat* forcedOrientation = NULL)
  149.         {
  150.                 if (pEntity->GetPhysics())
  151.                 {
  152.                         pe_action_set_velocity asv;
  153.                         asv.w.zero();
  154.                         asv.bRotationAroundPivot = 1;
  155.                         pEntity->GetPhysics()->Action(&asv);
  156.  
  157.                         pe_params_pos pos;
  158.                         pos.pos = pEntity->GetWorldPos();
  159.                         if (forcedOrientation == NULL)
  160.                         {
  161.                                 // This might be one frame behind?
  162.                                 pos.q = pEntity->GetWorldRotation();
  163.                         }
  164.                         else
  165.                         {
  166.                                 pos.q = *forcedOrientation;
  167.                         }
  168.                         pEntity->GetPhysics()->SetParams(&pos);
  169.                 }
  170.         }
  171.  
  172.         void PhysicSetApropiateSpeed(IEntity* pEntity)
  173.         {
  174.                 if (pEntity->GetPhysics())
  175.                 {
  176.                         Quat targetQuat = (m_sourceQuat | m_targetQuat) < 0 ? -m_targetQuat : m_targetQuat;
  177.                         Vec3 rotVel = Quat::log(targetQuat * !m_sourceQuat) * (2.0f / max(0.01f, (m_endTime - m_localStartTime).GetSeconds()));
  178.  
  179.                         pe_action_set_velocity asv;
  180.                         asv.w = rotVel;
  181.                         asv.bRotationAroundPivot = 1;
  182.                         pEntity->GetPhysics()->Action(&asv);
  183.                 }
  184.         }
  185.  
  186.         //////////////////////////////////////////////////////////////////////////
  187.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  188.         {
  189.                 switch (event)
  190.                 {
  191.                 case eFE_Initialize:
  192.                         {
  193.                                 m_coorSys = (ECoordSys)GetPortInt(pActInfo, IN_COORDSYS);
  194.                                 m_valueType = (EValueType)GetPortInt(pActInfo, IN_VALUETYPE);
  195.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  196.                                 m_bIsMoving = false;
  197.                                 break;
  198.                         }
  199.  
  200.                 case eFE_Activate:
  201.                         {
  202.                                 if (!pActInfo->pEntity)
  203.                                         break;
  204.  
  205.                                 if (IsPortActive(pActInfo, IN_STOP))
  206.                                 {
  207.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  208.                                         ActivateOutput(pActInfo, OUT_DONE, true);
  209.                                         ActivateOutput(pActInfo, OUT_STOP, true);
  210.                                         PhysicStop(pActInfo->pEntity);
  211.                                         m_bIsMoving = false;
  212.                                 }
  213.                                 // when the target is updated in middle of the movement, we can not just continue the interpolation only changing the target because that would cause some snaps.
  214.                                 // so we do sort of a new start but keeping the initial time into account, so we can still finish at the right time.
  215.                                 if (IsPortActive(pActInfo, IN_DEST) && GetPortBool(pActInfo, IN_DYN_DEST) == true && m_bIsMoving)
  216.                                 {
  217.                                         ReadSourceAndTargetQuats(pActInfo);
  218.                                         m_localStartTime = gEnv->pTimer->GetFrameStartTime();
  219.                                         CalcEndTime(pActInfo);
  220.                                         if (m_valueType == VT_TIME)
  221.                                         {
  222.                                                 PhysicSetApropiateSpeed(pActInfo->pEntity);
  223.                                         }
  224.                                 }
  225.                                 if (IsPortActive(pActInfo, IN_START))
  226.                                 {
  227.                                         bool triggerStartOutput = true;
  228.                                         Start(pActInfo, triggerStartOutput);
  229.                                 }
  230.                                 if (IsPortActive(pActInfo, IN_VALUE))
  231.                                 {
  232.                                         if (m_bIsMoving)
  233.                                         {
  234.                                                 bool triggerStartOutput = false;
  235.                                                 Start(pActInfo, triggerStartOutput);
  236.                                         }
  237.                                 }
  238.  
  239.                                 // we dont support dynamic change of those inputs
  240.                                 assert(!IsPortActive(pActInfo, IN_COORDSYS));
  241.                                 assert(!IsPortActive(pActInfo, IN_VALUETYPE));
  242.  
  243.                                 break;
  244.                         }
  245.  
  246.                 case eFE_Update:
  247.                         {
  248.                                 if (!pActInfo->pEntity)
  249.                                 {
  250.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  251.                                         m_bIsMoving = false;
  252.                                         break;
  253.                                 }
  254.  
  255.                                 CTimeValue curTime = gEnv->pTimer->GetFrameStartTime();
  256.                                 const float fDuration = (m_endTime - m_localStartTime).GetSeconds();
  257.                                 float fPosition;
  258.                                 if (fDuration <= 0.0)
  259.                                         fPosition = 1.0;
  260.                                 else
  261.                                 {
  262.                                         fPosition = (curTime - m_localStartTime).GetSeconds() / fDuration;
  263.                                         fPosition = clamp_tpl(fPosition, 0.0f, 1.0f);
  264.                                 }
  265.                                 if (curTime >= m_endTime)
  266.                                 {
  267.                                         if (m_bIsMoving)
  268.                                         {
  269.                                                 m_bIsMoving = false;
  270.                                                 ActivateOutput(pActInfo, OUT_DONE, true);
  271.                                                 ActivateOutput(pActInfo, OUT_FINISH, true);
  272.                                         }
  273.  
  274.                                         // By delaying the shutdown of regular updates, we generate
  275.                                         // the physics/entity stop + snap request multiple times. This seems
  276.                                         // to fix a weird glitch in Jailbreak whereby doors sometimes seem to
  277.                                         // overshoot their end orientation (physics proxies seem to be correct
  278.                                         // but the render proxies are off).
  279.                                         static const float s_Crysis3HacDeactivateDelay = 1.0f;
  280.                                         if (curTime >= (m_endTime + s_Crysis3HacDeactivateDelay))
  281.                                         {
  282.                                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  283.                                         }
  284.                                         SetRawEntityRot(pActInfo->pEntity, m_targetQuat);
  285.                                         PhysicStop(pActInfo->pEntity, &m_targetQuat);
  286.                                         UpdateCurrentRotOutputs(pActInfo, m_targetQuat);
  287.                                 }
  288.                                 else
  289.                                 {
  290.                                         Quat quat;
  291.                                         quat.SetSlerp(m_sourceQuat, m_targetQuat, fPosition);
  292.                                         SetRawEntityRot(pActInfo->pEntity, quat);
  293.                                         UpdateCurrentRotOutputs(pActInfo, quat);
  294.                                 }
  295.                                 break;
  296.                         }
  297.                 }
  298.         }
  299.  
  300.         void Start(SActivationInfo* pActInfo, bool triggerStartOutput)
  301.         {
  302.                 m_bIsMoving = true;
  303.  
  304.                 ReadSourceAndTargetQuats(pActInfo);
  305.  
  306.                 m_startTime = gEnv->pTimer->GetFrameStartTime();
  307.                 m_localStartTime = m_startTime;
  308.                 CalcEndTime(pActInfo);
  309.  
  310.                 PhysicSetApropiateSpeed(pActInfo->pEntity);
  311.  
  312.                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  313.                 if (triggerStartOutput)
  314.                         ActivateOutput(pActInfo, OUT_START, true);
  315.         }
  316.  
  317.         void ReadSourceAndTargetQuats(SActivationInfo* pActInfo)
  318.         {
  319.                 m_sourceQuat = m_coorSys == CS_WORLD ? pActInfo->pEntity->GetWorldRotation() : pActInfo->pEntity->GetRotation();
  320.                 m_sourceQuat.Normalize();
  321.  
  322.                 const Vec3& destRotDeg = GetPortVec3(pActInfo, IN_DEST);
  323.                 if (m_coorSys == CS_LOCAL)
  324.                 {
  325.                         Quat rotQuat;
  326.                         DegToQuat(destRotDeg, rotQuat);
  327.  
  328.                         m_targetQuat = m_sourceQuat * rotQuat;
  329.                 }
  330.                 else
  331.                 {
  332.                         DegToQuat(destRotDeg, m_targetQuat);
  333.                 }
  334.         }
  335.  
  336.         void CalcEndTime(SActivationInfo* pActInfo)
  337.         {
  338.                 if (m_valueType == VT_TIME)
  339.                 {
  340.                         CTimeValue timePast = m_localStartTime - m_startTime;
  341.                         float duration = GetPortFloat(pActInfo, IN_VALUE) - timePast.GetSeconds();
  342.                         m_endTime = m_startTime + duration;
  343.                 }
  344.                 else // when is speed-driven, we just calculate the apropiate endTime and from that on, everything else is the same
  345.                 {
  346.                         Quat qOriInv = m_sourceQuat.GetInverted();
  347.                         Quat qDist = qOriInv * m_targetQuat;
  348.                         qDist.NormalizeSafe();
  349.  
  350.                         float angDiff = RAD2DEG(2 * acosf(qDist.w));
  351.                         if (angDiff > 180.f)
  352.                         {
  353.                                 angDiff = 360.0f - angDiff;
  354.                         }
  355.  
  356.                         float desiredSpeed = fabsf(GetPortFloat(pActInfo, IN_VALUE));
  357.                         if (desiredSpeed < 0.0001f)
  358.                                 desiredSpeed = 0.0001f;
  359.                         m_endTime = m_localStartTime + angDiff / desiredSpeed;
  360.                 }
  361.         }
  362.  
  363.         virtual void GetMemoryUsage(ICrySizer* s) const
  364.         {
  365.                 s->Add(*this);
  366.         }
  367.  
  368. };
  369.  
  370. REGISTER_FLOW_NODE("Movement:RotateEntityToEx", CRotateEntityToExNode);
  371.  
downloadOwnerAngularInterpolatorNode.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