diff --git a/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.cpp b/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.cpp index 576a49cb17..7381cd8056 100644 --- a/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.cpp +++ b/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.cpp @@ -230,6 +230,9 @@ void Instance::Initialize(Instance* parent, float spawnDeltaFrame, int32_t insta m_randObject.SetSeed(instanceGlobal->GetRandObject().GetRandInt()); prevPosition_ = SIMD::Vec3f(0, 0, 0); + prevLocalVelocity_ = SIMD::Vec3f(0, 0, 0); + location_modify_global_ = SIMD::Vec3f(0, 0, 0); + velocity_modify_global_ = SIMD::Vec3f(0, 0, 0); } void Instance::FirstUpdate() @@ -375,6 +378,7 @@ void Instance::FirstUpdate() } prevGlobalPosition_ = SIMD::Vec3f::Transform(prevPosition_, m_ParentMatrix); + prevLocalVelocity_ = SIMD::Vec3f(0, 0, 0); m_pEffectNode->InitializeRenderedInstance(*this, *ownGroup_, m_pManager); } @@ -637,8 +641,17 @@ void Instance::UpdateTransform(float deltaFrame) UpdateParentMatrix(deltaFrame); } + float accerarationDelta = deltaFrame; + if (deltaFrame > 1) + { + // trapezoid interporation + accerarationDelta = ((1.0f + 1.0f / deltaFrame) / 2.0f) * deltaFrame; + } + SIMD::Vec3f localPosition = prevPosition_; - SIMD::Vec3f localVelocity; + SIMD::Vec3f localVelocity = prevLocalVelocity_; + + SIMD::Vec3f localAcc = SIMD::Vec3f(0, 0, 0); if (m_pEffectNode->CommonValues.TranslationBindType == TranslationParentBindType::NotBind_FollowParent || m_pEffectNode->CommonValues.TranslationBindType == TranslationParentBindType::WhenCreating_FollowParent) @@ -652,6 +665,7 @@ void Instance::UpdateTransform(float deltaFrame) toTarget *= followParentParam.maxFollowSpeed; } + auto prevSteering = steeringVec_; SIMD::Vec3f vSteering = toTarget - steeringVec_; vSteering *= followParentParam.steeringSpeed; @@ -663,34 +677,42 @@ void Instance::UpdateTransform(float deltaFrame) steeringVec_ *= followParentParam.maxFollowSpeed; } - localVelocity = steeringVec_ * deltaFrame * m_pEffectNode->m_effect->GetMaginification(); + localAcc = (steeringVec_ - prevSteering) * m_pEffectNode->m_effect->GetMaginification(); } else { - localVelocity = m_pEffectNode->TranslationParam.CalculateTranslationState(translation_values, m_randObject, m_pEffectNode->GetEffect(), m_pContainer->GetRootInstance(), m_LivingTime, m_LivedTime, m_pParent, coordinateSystem, m_pEffectNode->DynamicFactor); + localAcc = m_pEffectNode->TranslationParam.CalculateTranslationState(translation_values, m_randObject, m_pEffectNode->GetEffect(), m_pContainer->GetRootInstance(), m_LivingTime, m_LivedTime, deltaFrame, m_pParent, coordinateSystem, m_pEffectNode->DynamicFactor); if (m_pEffectNode->GenerationLocation.EffectsRotation) { // TODO : check rotation(It seems has bugs and it can optimize it) - localVelocity = SIMD::Vec3f::Transform(localVelocity, m_GenerationLocation.Get3x3SubMatrix()); + localAcc = SIMD::Vec3f::Transform(localAcc, m_GenerationLocation.Get3x3SubMatrix()); } } - localPosition += localVelocity; - auto matRot = RotationFunctions::CalculateRotation(rotation_values, m_pEffectNode->RotationParam, m_randObject, m_pEffectNode->GetEffect(), m_pContainer->GetRootInstance(), m_LivingTime, m_LivedTime, m_pParent, m_pEffectNode->DynamicFactor, m_pManager->GetLayerParameter(GetInstanceGlobal()->GetLayer()).ViewerPosition); auto scaling = ScalingFunctions::UpdateScaling(scaling_values, m_pEffectNode->ScalingParam, m_randObject, m_pEffectNode->GetEffect(), m_pContainer->GetRootInstance(), m_LivingTime, m_LivedTime, m_pParent, m_pEffectNode->DynamicFactor); // update local fields if (m_pEffectNode->LocalForceField.HasValue) { - forceField_.ExternalVelocity = localVelocity; - localPosition += forceField_.Update(m_pEffectNode->LocalForceField, localPosition, m_pEffectNode->GetEffect()->GetMaginification(), deltaFrame, m_pEffectNode->GetEffect()->GetSetting()->GetCoordinateSystem()); + // for compatibiliy + auto new_local_position = localPosition + (localVelocity * deltaFrame + localAcc * accerarationDelta); + + localAcc += forceField_.Update( + m_pEffectNode->LocalForceField, + new_local_position, + localVelocity, + m_pEffectNode->GetEffect()->GetMaginification(), + deltaFrame, + m_pEffectNode->GetEffect()->GetSetting()->GetCoordinateSystem()); } + localPosition += localVelocity * deltaFrame + localAcc * accerarationDelta; + localVelocity += localAcc; prevPosition_ = localPosition; + prevLocalVelocity_ = localVelocity; - /* 描画部分の更新 */ m_pEffectNode->UpdateRenderedInstance(*this, *ownGroup_, m_pManager); // Update matrix @@ -716,9 +738,11 @@ void Instance::UpdateTransform(float deltaFrame) if (m_pEffectNode->LocalForceField.IsGlobalEnabled) { InstanceGlobal* instanceGlobal = m_pContainer->GetRootInstance(); - forceField_.UpdateGlobal(m_pEffectNode->LocalForceField, prevGlobalPosition_, m_pEffectNode->GetEffect()->GetMaginification(), instanceGlobal->GetTargetLocation(), deltaFrame, m_pEffectNode->GetEffect()->GetSetting()->GetCoordinateSystem()); - SIMD::Mat43f MatTraGlobal = SIMD::Mat43f::Translation(forceField_.GlobalModifyLocation); - calcMat *= MatTraGlobal; + const auto acc_global = forceField_.UpdateGlobal(m_pEffectNode->LocalForceField, prevGlobalPosition_, m_pEffectNode->GetEffect()->GetMaginification(), instanceGlobal->GetTargetLocation(), deltaFrame, m_pEffectNode->GetEffect()->GetSetting()->GetCoordinateSystem()); + location_modify_global_ += velocity_modify_global_ * deltaFrame + acc_global * accerarationDelta; + velocity_modify_global_ += acc_global; + SIMD::Mat43f mat_location_global = SIMD::Mat43f::Translation(location_modify_global_); + calcMat *= mat_location_global; } globalMatrix_.Step(calcMat, m_LivingTime); diff --git a/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.h b/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.h index 5d20c313ed..484b84f541 100644 --- a/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.h +++ b/Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.h @@ -71,9 +71,15 @@ class alignas(16) Instance : public IntrusiveList::Node SIMD::Vec3f prevPosition_; SIMD::Vec3f prevGlobalPosition_; + SIMD::Vec3f prevLocalVelocity_; + SIMD::Vec3f parentPosition_; + SIMD::Vec3f steeringVec_; + SIMD::Vec3f location_modify_global_; + SIMD::Vec3f velocity_modify_global_; + public: static const int32_t ChildrenMax = 16; diff --git a/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.cpp b/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.cpp index 5cbc02a75d..837c7c7687 100644 --- a/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.cpp +++ b/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.cpp @@ -355,13 +355,16 @@ void LocalForceFieldParameter::MaintainAttractiveForceCompatibility(const float LocalForceFields[3].IsGlobal = true; } -SIMD::Vec3f LocalForceFieldInstance::Update(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, float magnification, float deltaFrame, CoordinateSystem coordinateSystem) +SIMD::Vec3f LocalForceFieldInstance::Update(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, const SIMD::Vec3f& local_velocity_per_update, float magnification, float deltaFrame, CoordinateSystem coordinateSystem) { if (deltaFrame == 0.0f) { return SIMD::Vec3f{0, 0, 0}; } + std::array accs; + accs.fill(SIMD::Vec3f(0, 0, 0)); + for (size_t i = 0; i < parameter.LocalForceFields.size(); i++) { auto& field = parameter.LocalForceFields[i]; @@ -376,7 +379,7 @@ SIMD::Vec3f LocalForceFieldInstance::Update(const LocalForceFieldParameter& para ForceFieldCommonParameter ffcp; ffcp.FieldCenter = parameter.LocalForceFields[i].Position; ffcp.Position = location / magnification; - ffcp.PreviousSumVelocity = (VelocitySum + ExternalVelocity / deltaFrame) / magnification; + ffcp.PreviousSumVelocity = local_velocity_per_update / magnification; ffcp.PreviousVelocity = Velocities[i] / magnification; ffcp.DeltaFrame = deltaFrame; ffcp.IsFieldRotated = field.IsRotated; @@ -455,26 +458,37 @@ SIMD::Vec3f LocalForceFieldInstance::Update(const LocalForceFieldParameter& para } Velocities[i] += acc; + accs[i] = acc; } - VelocitySum = SIMD::Vec3f(0, 0, 0); + SIMD::Vec3f acc_sum = SIMD::Vec3f(0, 0, 0); for (size_t i = 0; i < parameter.LocalForceFields.size(); i++) { if (parameter.LocalForceFields[i].IsGlobal) continue; - - VelocitySum += Velocities[i]; + acc_sum += accs[i]; } - return VelocitySum * deltaFrame; + return acc_sum; } -void LocalForceFieldInstance::UpdateGlobal(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, float magnification, const SIMD::Vec3f& targetPosition, float deltaFrame, CoordinateSystem coordinateSystem) +SIMD::Vec3f LocalForceFieldInstance::UpdateGlobal(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, float magnification, const SIMD::Vec3f& targetPosition, float deltaFrame, CoordinateSystem coordinateSystem) { if (deltaFrame == 0.0f) { - return; + return SIMD::Vec3f(0, 0, 0); + } + + std::array accs; + accs.fill(SIMD::Vec3f(0, 0, 0)); + + SIMD::Vec3f velocity_sum_prev = SIMD::Vec3f(0, 0, 0); + for (size_t i = 0; i < parameter.LocalForceFields.size(); i++) + { + if (!parameter.LocalForceFields[i].IsGlobal) + continue; + velocity_sum_prev += Velocities[i]; } for (size_t i = 0; i < parameter.LocalForceFields.size(); i++) @@ -491,7 +505,7 @@ void LocalForceFieldInstance::UpdateGlobal(const LocalForceFieldParameter& param ForceFieldCommonParameter ffcp; ffcp.FieldCenter = parameter.LocalForceFields[i].Position; ffcp.Position = location / magnification; - ffcp.PreviousSumVelocity = GlobalVelocitySum / magnification; + ffcp.PreviousSumVelocity = velocity_sum_prev / magnification; ffcp.PreviousVelocity = Velocities[i] / magnification; ffcp.TargetPosition = targetPosition / magnification; ffcp.DeltaFrame = deltaFrame; @@ -558,28 +572,23 @@ void LocalForceFieldInstance::UpdateGlobal(const LocalForceFieldParameter& param } Velocities[i] += acc; + accs[i] = acc; } - GlobalVelocitySum = SIMD::Vec3f(0, 0, 0); - + SIMD::Vec3f acc_sum = SIMD::Vec3f(0, 0, 0); for (size_t i = 0; i < parameter.LocalForceFields.size(); i++) { if (!parameter.LocalForceFields[i].IsGlobal) continue; - - GlobalVelocitySum += Velocities[i]; + acc_sum += accs[i]; } - GlobalModifyLocation += GlobalVelocitySum * deltaFrame; + return acc_sum; } void LocalForceFieldInstance::Reset() { Velocities.fill(SIMD::Vec3f(0, 0, 0)); - VelocitySum = SIMD::Vec3f(0, 0, 0); - GlobalVelocitySum = SIMD::Vec3f(0, 0, 0); - GlobalModifyLocation = SIMD::Vec3f(0, 0, 0); - ExternalVelocity = SIMD::Vec3f(0, 0, 0); } } // namespace Effekseer \ No newline at end of file diff --git a/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.h b/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.h index 5c0129b3b2..87ed7ceffd 100644 --- a/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.h +++ b/Dev/Cpp/Effekseer/Effekseer/ForceField/ForceFields.h @@ -241,7 +241,7 @@ class ForceField if (ffp.Gravitation) { - return dir * ffp.Power / distance; + return dir * ffp.Power / distance * ffc.DeltaFrame; } return dir * ffp.Power * ffc.DeltaFrame; @@ -289,7 +289,7 @@ class ForceField auto xlen = power / distance * (power / 2.0f); auto flen = sqrt(power * power - xlen * xlen); - return ((front * flen - localPos * xlen) * direction - ffc.PreviousVelocity) * ffc.DeltaFrame; + return ((front * flen - localPos * xlen) * direction * ffc.DeltaFrame - ffc.PreviousVelocity); } /** @@ -353,13 +353,21 @@ class ForceField if (ffc.DeltaFrame > 0) { float eps = 0.0001f; - auto ret = SIMD::Vec3f(0.0f, 0.0f, 0.0f); auto vel = ffc.PreviousVelocity; - vel += targetDirection * force * ffc.DeltaFrame; - float currentVelocity = vel.GetLength() + eps; - SIMD::Vec3f currentDirection = vel / currentVelocity; + auto deltaFrame = ffc.DeltaFrame; + + while (deltaFrame > eps) + { + auto tempDeltaFrame = std::min(1.0f, deltaFrame); + vel += targetDirection * force * tempDeltaFrame; + float currentVelocity = vel.GetLength() + eps; + SIMD::Vec3f currentDirection = vel / currentVelocity; + + vel = (targetDirection * ffp.Control + currentDirection * (1.0f - ffp.Control)) * currentVelocity; + + deltaFrame -= tempDeltaFrame; + } - vel = (targetDirection * ffp.Control + currentDirection * (1.0f - ffp.Control)) * currentVelocity; return vel - ffc.PreviousVelocity; } } @@ -433,15 +441,9 @@ struct LocalForceFieldInstance { std::array Velocities; - SIMD::Vec3f ExternalVelocity; - SIMD::Vec3f VelocitySum; - - SIMD::Vec3f GlobalVelocitySum; - SIMD::Vec3f GlobalModifyLocation; - - SIMD::Vec3f Update(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, float magnification, float deltaFrame, CoordinateSystem coordinateSystem); + SIMD::Vec3f Update(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, const SIMD::Vec3f& local_velocity_per_update, float magnification, float deltaFrame, CoordinateSystem coordinateSystem); - void UpdateGlobal(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, float magnification, const SIMD::Vec3f& targetPosition, float deltaTime, CoordinateSystem coordinateSystem); + SIMD::Vec3f UpdateGlobal(const LocalForceFieldParameter& parameter, const SIMD::Vec3f& location, float magnification, const SIMD::Vec3f& targetPosition, float deltaTime, CoordinateSystem coordinateSystem); void Reset(); }; diff --git a/Dev/Cpp/Effekseer/Effekseer/Parameter/Translation.h b/Dev/Cpp/Effekseer/Effekseer/Parameter/Translation.h index 5079cde415..fafe276be4 100644 --- a/Dev/Cpp/Effekseer/Effekseer/Parameter/Translation.h +++ b/Dev/Cpp/Effekseer/Effekseer/Parameter/Translation.h @@ -95,6 +95,7 @@ struct InstanceTranslationState }; SIMD::Vec3f prevLocation; + SIMD::Vec3f prevVelocity; }; class TranslationParameter @@ -383,6 +384,7 @@ class TranslationParameter } instanceState.prevLocation = position; + instanceState.prevVelocity = SIMD::Vec3f(0, 0, 0); } SIMD::Vec3f CalculateTranslationState( @@ -392,10 +394,16 @@ class TranslationParameter const InstanceGlobal* instanceGlobal, float livingTime, float livedTime, + float deltaFrame, const Instance* m_pParent, CoordinateSystem coordinateSystem, const DynamicFactorParameter& dynamicFactor) { + if (deltaFrame == 0.0f) + { + return SIMD::Vec3f(0, 0, 0); + } + SIMD::Vec3f localPosition; if (TranslationType == ParameterTranslationType_None) @@ -469,9 +477,11 @@ class TranslationParameter return {0, 0, 0}; } - const auto vel = localPosition - instanceState.prevLocation; + const auto vel = (localPosition - instanceState.prevLocation) / deltaFrame; + const auto acc = vel - instanceState.prevVelocity; instanceState.prevLocation = localPosition; - return vel; + instanceState.prevVelocity = vel; + return acc; } }; diff --git a/TestData b/TestData index 4bd1c4c552..ae2503b85e 160000 --- a/TestData +++ b/TestData @@ -1 +1 @@ -Subproject commit 4bd1c4c55263ba9e5894ab7fe6450483e25a163e +Subproject commit ae2503b85e4ff8824e9f194afec58a19f8ebe872