bool CTransformationPinning::Execute(const SAnimationPoseModifierParams& params) { if (m_factor == 0.0f) return false; CRY_ASSERT(m_source && (m_jointID > 0.0f)); if (!m_jointsInitialised) { Init(params); } ISkeletonPose* pSkeletonPose = params.pCharacterInstance->GetISkeletonPose(); int sourceJoints = m_source->GetJointCount(); CRY_ASSERT(sourceJoints == pSkeletonPose->GetJointCount()); for (int i=0; i<sourceJoints; i++) { const QuatT &sourceJoint = m_source->GetAbsJointByID(i); const QuatT &relSourceJoint = m_source->GetRelJointByID(i); CRY_ASSERT(params.pPoseData->GetJointAbsolute(i).IsValid()); CRY_ASSERT(sourceJoint.IsValid()); switch (m_jointTypes[i]) { case TransformationPinJoint::Copy: if (m_factor < 1.0f) { QuatT diff = params.pPoseData->GetJointAbsolute(i).GetInverted() * sourceJoint; params.pPoseData->SetJointAbsolute(i, params.pPoseData->GetJointAbsolute(i) * diff.GetScaled(m_factor)); diff = params.pPoseData->GetJointRelative(i).GetInverted() * relSourceJoint; params.pPoseData->SetJointRelative(i, params.pPoseData->GetJointRelative(i) * diff.GetScaled(m_factor)); } else { params.pPoseData->SetJointAbsolute(i, sourceJoint); params.pPoseData->SetJointRelative(i, relSourceJoint); } break; case TransformationPinJoint::Feather: { int16 parent = m_source->GetParentIDByID(i); QuatT invParent = params.pPoseData->GetJointAbsolute(parent).GetInverted(); params.pPoseData->SetJointRelative(i, invParent * params.pPoseData->GetJointAbsolute(i)); QuatT thisJnt = params.pPoseData->GetJointAbsolute(parent) * params.pPoseData->GetJointRelative(i); CRY_ASSERT(params.pPoseData->GetJointRelative(i).IsValid()); CRY_ASSERT(thisJnt.IsValid()); } break; case TransformationPinJoint::Inherit: break; } } return true; }
QuatT GetWorldOffset(const QuatT& origin, const QuatT& destination) { CRY_ASSERT(origin.IsValid()); CRY_ASSERT(destination.IsValid()); QuatT offset(destination.t - origin.t, origin.q.GetInverted() * destination.q); offset.q.Normalize(); CRY_ASSERT(offset.IsValid()); return offset; }
QuatT ApplyWorldOffset(const QuatT& origin, const QuatT& offset) { CRY_ASSERT(origin.IsValid()); CRY_ASSERT(offset.IsValid()); QuatT destination(origin.q * offset.q, origin.t + offset.t); destination.q.Normalize(); CRY_ASSERT(destination.IsValid()); return destination; }
QuatT CombineHVComponents2D(const QuatT& cmpH, const QuatT& cmpV) { ANIMCHAR_PROFILE_DETAILED; // NOTE: This function assumes there is no pitch/bank and totally ignores XY rotations. CRY_ASSERT(cmpH.IsValid()); CRY_ASSERT(cmpV.IsValid()); QuatT cmb; cmb.t.x = cmpH.t.x; cmb.t.y = cmpH.t.y; cmb.t.z = cmpV.t.z; cmb.q.SetRotationZ(cmpH.q.GetRotZ()); CRY_ASSERT(cmb.IsValid()); return cmb; }
void CLocalPlayerComponent::GetFPTotalTorsoOffset(QuatT &offset, IItem * pCurrentItem) const { CItem *pItem = (CItem *)pCurrentItem; if (pItem) { pItem->GetFPOffset(offset); } else { offset.SetIdentity(); } }
QuatT /*CAnimatedCharacter::*/ExtractVComponent(const QuatT& m) /*const*/ { ANIMCHAR_PROFILE_DETAILED; // NOTE: This function assumes there is no pitch/bank and totally ignores XY rotations. CRY_ASSERT(m.IsValid()); QuatT ext;//(IDENTITY); ext.t.z = m.t.z; ext.t.x = 0.0f; ext.t.y = 0.0f; /* Ang3 a(m.q); a.z = 0.0f; ext.q.SetRotationXYZ(a); */ ext.q.SetIdentity(); CRY_ASSERT(ext.IsValid()); return ext; }
QuatT CombineHVComponents3D(const QuatT& cmpH, const QuatT& cmpV) { ANIMCHAR_PROFILE_DETAILED; //return CombineHVComponents2D(cmpH, cmpV); CRY_ASSERT(cmpH.IsValid()); CRY_ASSERT(cmpV.IsValid()); QuatT cmb; cmb.t.x = cmpH.t.x; cmb.t.y = cmpH.t.y; cmb.t.z = cmpV.t.z; // TODO: This should be optimized! Ang3 ah(cmpH.q); Ang3 av(cmpV.q); Ang3 a(av.x, av.y, ah.z); cmb.q.SetRotationXYZ(a); CRY_ASSERT(cmb.IsValid()); return cmb; }
void CAnimatedCharacter::SetDesiredLocalLocation( ISkeletonAnim* pSkeletonAnim, const QuatT& desiredLocalLocation, float fDeltaTime) { CRY_ASSERT(desiredLocalLocation.IsValid()); { uint32 NumAnimsInQueue = pSkeletonAnim->GetNumAnimsInFIFO(0); uint32 nMaxActiveInQueue=MAX_EXEC_QUEUE; if (nMaxActiveInQueue>NumAnimsInQueue) nMaxActiveInQueue=NumAnimsInQueue; if (NumAnimsInQueue>nMaxActiveInQueue) NumAnimsInQueue=nMaxActiveInQueue; uint32 active=0; for (uint32 a=0; a<NumAnimsInQueue; a++) { const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a); active += anim.IsActivated() ? 1 : 0; } if (active>nMaxActiveInQueue) active=nMaxActiveInQueue; nMaxActiveInQueue=active; const SParametricSampler *pLMG = NULL; for (int32 a=nMaxActiveInQueue-1; (a >= 0) && !pLMG; --a) { const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a); pLMG = anim.GetParametricSampler(); } } const Vec3 dir = desiredLocalLocation.GetColumn1(); float turnAngle = atan2f(-dir.x, dir.y); float turnSpeed = turnAngle / fDeltaTime; const Vec2 deltaVector(desiredLocalLocation.t.x, desiredLocalLocation.t.y); const float travelDist = deltaVector.GetLength(); const Vec2 deltaDir = (travelDist > 0.0f) ? (deltaVector / travelDist) : Vec2(0,0); float travelAngle = (deltaDir.x == 0.0f && deltaDir.y == 0.0f ? 0.0f : atan2f(-deltaDir.x, deltaDir.y)); float travelSpeed; if (gEnv->bMultiplayer) { travelSpeed = travelDist / fDeltaTime; } else { const float cosGroundSlope = fabsf(cosf(m_fGroundSlopeMoveDirSmooth)); travelSpeed = (cosGroundSlope > FLT_EPSILON) ? (travelDist / (fDeltaTime * cosGroundSlope)) : (travelDist / fDeltaTime); } // TravelAngle smoothing { const Vec2 newStrafe = Vec2(-sin_tpl(travelAngle), cos_tpl(travelAngle)); if (CAnimationGraphCVars::Get().m_enableTurnAngleSmoothing) { SmoothCD(m_fDesiredStrafeSmoothQTX, m_fDesiredStrafeSmoothRateQTX, fDeltaTime, newStrafe, 0.10f); } else { m_fDesiredStrafeSmoothQTX=newStrafe; m_fDesiredStrafeSmoothRateQTX.zero(); } travelAngle = Ang3::CreateRadZ(Vec2(0,1),m_fDesiredStrafeSmoothQTX); } const bool modulateTurnSpeedByTravelAngle = true; if (modulateTurnSpeedByTravelAngle) { static float minimum = DEG2RAD(10.0f); // do not change turnSpeed when travelAngle is below this static float maximum = DEG2RAD(40.0f); // force turnspeed to zero when travelAngle is above this const float turnSpeedScale = 1.0f - clamp_tpl( fabsf(travelAngle) - minimum, 0.0f, maximum - minimum ) / ( maximum - minimum ); turnSpeed *= turnSpeedScale; } // TurnSpeed smoothing { if (CAnimationGraphCVars::Get().m_enableTurnSpeedSmoothing) { SmoothCD(m_fDesiredTurnSpeedSmoothQTX, m_fDesiredTurnSpeedSmoothRateQTX, fDeltaTime, turnSpeed, 0.40f); } else { m_fDesiredTurnSpeedSmoothQTX = turnSpeed; m_fDesiredTurnSpeedSmoothRateQTX = 0.0f; } } // TravelSpeed smoothing { if (CAnimationGraphCVars::Get().m_enableTravelSpeedSmoothing) { SmoothCD(m_fDesiredMoveSpeedSmoothQTX, m_fDesiredMoveSpeedSmoothRateQTX, fDeltaTime, travelSpeed, 0.04f); } else { m_fDesiredMoveSpeedSmoothQTX = travelSpeed; m_fDesiredMoveSpeedSmoothRateQTX = 0.0f; } } SetMotionParam(pSkeletonAnim, eMotionParamID_TravelSpeed, m_fDesiredMoveSpeedSmoothQTX); SetMotionParam(pSkeletonAnim, eMotionParamID_TurnSpeed, m_fDesiredTurnSpeedSmoothQTX * CAnimationGraphCVars::Get().m_turnSpeedParamScale); SetMotionParam(pSkeletonAnim, eMotionParamID_TravelAngle, travelAngle); // eMotionParamID_TravelSlope SetMotionParam(pSkeletonAnim, eMotionParamID_TurnAngle, turnAngle); // eMotionParamID_TravelDist SetMotionParam(pSkeletonAnim, eMotionParamID_StopLeg, 0); }
//------------------------------------------------------------------------ EntityEffects::TAttachedEffectId CItem::AttachEffect(int slot, bool attachToAccessory, const char *effectName, const char *helper, const Vec3 &offset, const Vec3 &dir, float scale, bool prime) { if(!g_pGameCVars->i_particleeffects) { return 0; } Vec3 finalOffset(offset); string helperName(helper); if(attachToAccessory) { SEntitySlotInfo slotInfo; QuatT accessoryOffset; accessoryOffset.SetIdentity(); const char* accessoryHelper = ""; const char* accessoryName = NULL; const int numAccessories = m_accessories.size(); for (int curIndex = 0; curIndex < numAccessories; curIndex++) { IEntity* pAccessory = gEnv->pEntitySystem->GetEntity(m_accessories[curIndex].accessoryId); if(pAccessory && pAccessory->GetSlotInfo(slot, slotInfo)) { if(slotInfo.pStatObj) { accessoryOffset.t = slotInfo.pStatObj->GetHelperPos(helper); if(!accessoryOffset.t.IsZero()) { accessoryOffset.q = pAccessory->GetRotation(); accessoryOffset.t += pAccessory->GetPos(); accessoryName = m_accessories[curIndex].pClass->GetName(); break; } } if(slotInfo.pCharacter) { IAttachmentManager *pAttachmentManager = slotInfo.pCharacter->GetIAttachmentManager(); IAttachment *pAttachment = pAttachmentManager->GetInterfaceByName(helper); if(pAttachment) { accessoryHelper = GetAccessoryParams(m_accessories[curIndex].pClass)->attach_helper.c_str(); accessoryName = m_accessories[curIndex].pClass->GetName(); accessoryOffset = pAttachment->GetAttAbsoluteDefault(); break; } } } } if(accessoryName) { bool validSlot = GetEntity()->GetSlotInfo(slot, slotInfo) && (slotInfo.pCharacter || slotInfo.pStatObj); if (!validSlot || slotInfo.pStatObj) { if (validSlot) { Matrix34 mtx = GetEntity()->GetSlotLocalTM(slot, false) * Matrix34(accessoryOffset); finalOffset += mtx.GetTranslation(); } EntityEffects::SEffectAttachParams attachParams(finalOffset, dir, scale, prime, eIGS_Last); return m_effectsController.AttachParticleEffect(effectName, attachParams); } else if (slotInfo.pCharacter) // bone attachment { ICharacterInstance *pCharacter = slotInfo.pCharacter; IAttachmentManager *pAttachmentManager = pCharacter->GetIAttachmentManager(); IAttachment *pAttachment = NULL; helperName = string().Format("%s_%s", helper, accessoryName); pAttachment = pAttachmentManager->GetInterfaceByName(helperName.c_str()); if(!pAttachment) { IAttachment* pAccessoryAttachment = pAttachmentManager->GetInterfaceByName(accessoryHelper); if(pAccessoryAttachment) { const char* bone = pCharacter->GetIDefaultSkeleton().GetJointNameByID(pAccessoryAttachment->GetJointID()); pAttachment = pAttachmentManager->CreateAttachment(helperName.c_str(), CA_BONE, bone); if (pAttachment) { QuatT relative = pAccessoryAttachment->GetAttRelativeDefault(); relative = relative * accessoryOffset; relative.t = relative * finalOffset; finalOffset.zero(); pAttachment->SetAttRelativeDefault(relative); } } } } } } EntityEffects::SEffectAttachParams attachParams(finalOffset, dir, scale, prime, eIGS_Last); return m_effectsController.AttachParticleEffect(effectName, slot, helperName, attachParams); }
bool CStickyProjectile::StickToEntity( const SStickParams& stickParams, IEntity* pTargetEntity ) { IEntity* pProjectileEntity = stickParams.m_pProjectile->GetEntity(); ICharacterInstance* pCharInstance = pTargetEntity->GetCharacter(0); if( pCharInstance) { IActor* pActor = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pTargetEntity->GetId()); if (!pActor || (stickParams.m_bStickToFriendlies || !pActor->IsFriendlyEntity(stickParams.m_ownerId)) && (gEnv->bMultiplayer || !pActor->IsDead())) { m_stuckJoint = GetJointIdFromPartId(*pTargetEntity, stickParams.m_targetPartId); m_stuckNormal = stickParams.m_stickNormal; m_stuckPartId = stickParams.m_targetPartId; ICharacterModelSkeleton* pICharacterModelSkeleton = pCharInstance->GetICharacterModel()->GetICharacterModelSkeleton(); ISkeletonPose* pSkeleton = pCharInstance->GetISkeletonPose(); const char* boneName = pICharacterModelSkeleton->GetJointNameByID(m_stuckJoint); const QuatT jointWorld = QuatT(pTargetEntity->GetWorldTM()) * pSkeleton->GetAbsJointByID(m_stuckJoint); QuatT loc; CalculateLocationForStick( *pProjectileEntity, stickParams.m_stickPosition, stickParams.m_stickNormal, loc ); pProjectileEntity->SetWorldTM(Matrix34(loc)); // Get the local pos and rot. loc = jointWorld.GetInverted() * loc; m_stuckPos = loc.t; m_stuckRot = loc.q; // Attach. if(AttachToCharacter( stickParams.m_pProjectile, *pTargetEntity, *pCharInstance, boneName)) { m_flags |= eSF_IsStuck; m_flags |= pActor ? pActor->IsPlayer() ? eSF_StuckToPlayer : eSF_StuckToAI : 0; SetParentId(pTargetEntity->GetId()); m_childId = pProjectileEntity->GetId(); return true; } } } else { m_stuckNormal = stickParams.m_stickNormal; m_stuckPartId = stickParams.m_targetPartId; QuatT loc; CalculateLocationForStick( *pProjectileEntity, stickParams.m_stickPosition, stickParams.m_stickNormal, loc ); AttachTo(stickParams.m_pProjectile, pTargetEntity); pProjectileEntity->SetWorldTM(Matrix34(loc)); // Set as Stuck. SetParentId(pTargetEntity->GetId()); m_childId = pProjectileEntity->GetId(); m_flags |= eSF_IsStuck; //Store position and rotation relative to parent entity m_stuckPos = pProjectileEntity->GetPos(); m_stuckRot = pProjectileEntity->GetRotation(); return true; } return false; }
QuatT CAnimatedCharacter::MergeMCM(const QuatT& ent, const QuatT& anim, bool flat) const { ANIMCHAR_PROFILE_DETAILED; CRY_ASSERT(ent.IsValid()); CRY_ASSERT(anim.IsValid()); EMovementControlMethod mcmh = GetMCMH(); EMovementControlMethod mcmv = GetMCMV(); CRY_ASSERT(mcmh >= 0 && mcmh < eMCM_COUNT); CRY_ASSERT(mcmv >= 0 && mcmv < eMCM_COUNT); if (mcmh == mcmv) { switch (mcmh /*or mcmv*/) { case eMCM_Entity: case eMCM_ClampedEntity: case eMCM_SmoothedEntity: return ent; case eMCM_DecoupledCatchUp: case eMCM_Animation: case eMCM_AnimationHCollision: return anim; default: GameWarning("CAnimatedCharacter::MergeMCM() - Horizontal & Vertical MCM %s not implemented!", g_szMCMString[mcmh]); return ent; } } QuatT mergedH, mergedV; switch (mcmh) { case eMCM_Entity: case eMCM_ClampedEntity: case eMCM_SmoothedEntity: mergedH = ent; break; case eMCM_DecoupledCatchUp: case eMCM_Animation: case eMCM_AnimationHCollision: mergedH = anim; break; default: mergedH = ent; GameWarning("CAnimatedCharacter::MergeMCM() - Horizontal MCM %s not implemented!", g_szMCMString[mcmh]); break; } switch (mcmv) { case eMCM_Entity: case eMCM_ClampedEntity: case eMCM_SmoothedEntity: mergedV = ent; break; case eMCM_DecoupledCatchUp: case eMCM_Animation: mergedV = anim; break; default: mergedV = ent; GameWarning("CAnimatedCharacter::MergeMCM() - Vertical MCM %s not implemented!", g_szMCMString[mcmv]); break; } QuatT merged; if (flat) merged = CombineHVComponents2D(mergedH, mergedV); else merged = CombineHVComponents3D(mergedH, mergedV); CRY_ASSERT(merged.IsValid()); return merged; }