Skip to content

Commit

Permalink
Implement Collisions module and rotate to velocity (#978)
Browse files Browse the repository at this point in the history
Implement Collisions module and rotate to velocity
  • Loading branch information
durswd authored Dec 11, 2023
1 parent 2a0a606 commit c970772
Show file tree
Hide file tree
Showing 34 changed files with 600 additions and 157 deletions.
1 change: 1 addition & 0 deletions Dev/Cpp/Effekseer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ set(effekseer_src
Effekseer/Material/Effekseer.CompiledMaterial.cpp
Effekseer/Material/Effekseer.MaterialCompiler.cpp
Effekseer/IO/Effekseer.EfkEfcFactory.cpp
Effekseer/Parameter/Collisions.cpp
Effekseer/Parameter/Easing.cpp
Effekseer/Parameter/Effekseer.Parameters.cpp
Effekseer/Parameter/KillRules.cpp
Expand Down
2 changes: 1 addition & 1 deletion Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectImplemented.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class EffectImplemented : public Effect, public ReferenceObject
friend class EffectFactory;
friend class Instance;

static const int32_t SupportBinaryVersion = Version17;
static const int32_t SupportBinaryVersion = Version18Alpha1;

protected:
SettingRef m_setting;
Expand Down
1 change: 1 addition & 0 deletions Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ void EffectNodeImplemented::LoadParameter(unsigned char*& pos, EffectNode* paren
GenerationLocation.load(pos, ef->GetVersion());
DepthValues.Load(pos, ef->GetVersion());
KillParam.Load(pos, ef->GetVersion());
Collisions.Load(pos, ef->GetVersion());

if (m_effect->GetVersion() >= 3)
{
Expand Down
3 changes: 3 additions & 0 deletions Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "Parameter/AllTypeColor.h"
#include "Parameter/AlphaCutoff.h"
#include "Parameter/BasicSettings.h"
#include "Parameter/Collisions.h"
#include "Parameter/CustomData.h"
#include "Parameter/DepthParameter.h"
#include "Parameter/DynamicParameter.h"
Expand Down Expand Up @@ -518,6 +519,8 @@ class EffectNodeImplemented : public EffectNode, public SIMD::AlignedAllocationP

DynamicFactorParameter DynamicFactor;

CollisionsParameter Collisions;

bool Traverse(const std::function<bool(EffectNodeImplemented*)>& visitor);

Effect* GetEffect() const override;
Expand Down
2 changes: 1 addition & 1 deletion Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNodeModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ void EffectNodeModel::Rendering(const Instance& instance, const Instance* next_i

if (nodeParam_.EnableViewOffset)
{
instanceParameter.ViewOffsetDistance = instance.translation_values.view_offset.distance;
instanceParameter.ViewOffsetDistance = instance.translation_state_.view_offset.distance;
}

CalcCustomData(&instance, instanceParameter.CustomData1, instanceParameter.CustomData2);
Expand Down
2 changes: 1 addition & 1 deletion Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNodeRibbon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ void EffectNodeRibbon::BeginRenderingGroup(InstanceGroup* group, Manager* manage

if (m_nodeParameter.EnableViewOffset)
{
m_instanceParameter.ViewOffsetDistance = groupFirst->translation_values.view_offset.distance;
m_instanceParameter.ViewOffsetDistance = groupFirst->translation_state_.view_offset.distance;
}

CalcCustomData(group->GetFirst(), m_instanceParameter.CustomData1, m_instanceParameter.CustomData2);
Expand Down
2 changes: 1 addition & 1 deletion Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNodeRing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ void EffectNodeRing::Rendering(const Instance& instance, const Instance* next_in

if (instance.m_pEffectNode->TranslationParam.TranslationType == ParameterTranslationType_ViewOffset)
{
instanceParameter.ViewOffsetDistance = instance.translation_values.view_offset.distance;
instanceParameter.ViewOffsetDistance = instance.translation_state_.view_offset.distance;
}

CalcCustomData(&instance, instanceParameter.CustomData1, instanceParameter.CustomData2);
Expand Down
2 changes: 1 addition & 1 deletion Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNodeSprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ void EffectNodeSprite::Rendering(const Instance& instance, const Instance* next_

if (nodeParam_.EnableViewOffset)
{
instanceParameter.ViewOffsetDistance = instance.translation_values.view_offset.distance;
instanceParameter.ViewOffsetDistance = instance.translation_state_.view_offset.distance;
}

CalcCustomData(&instance, instanceParameter.CustomData1, instanceParameter.CustomData2);
Expand Down
2 changes: 1 addition & 1 deletion Dev/Cpp/Effekseer/Effekseer/Effekseer.EffectNodeTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ void EffectNodeTrack::BeginRenderingGroup(InstanceGroup* group, Manager* manager

if (m_nodeParameter.EnableViewOffset)
{
m_instanceParameter.ViewOffsetDistance = groupFirst->translation_values.view_offset.distance;
m_instanceParameter.ViewOffsetDistance = groupFirst->translation_state_.view_offset.distance;
}

CalcCustomData(group->GetFirst(), m_instanceParameter.CustomData1, m_instanceParameter.CustomData2);
Expand Down
137 changes: 99 additions & 38 deletions Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ void Instance::FirstUpdate()
ColorParent = m_pParent->ColorInheritance;
}

steeringVec_ = SIMD::Vec3f(0, 0, 0);
steering_vec_ = SIMD::Vec3f(0, 0, 0);

if (m_pEffectNode->CommonValues.TranslationBindType == TranslationParentBindType::NotBind_FollowParent ||
m_pEffectNode->CommonValues.TranslationBindType == TranslationParentBindType::WhenCreating_FollowParent)
Expand All @@ -320,7 +320,7 @@ void Instance::FirstUpdate()
followParentParam.steeringSpeed = m_pEffectNode->SteeringBehaviorParam.SteeringSpeed.getValue(rand) / 100.0f;
}

m_pEffectNode->TranslationParam.InitializeTranslationState(translation_values, prevPosition_, steeringVec_, rand, effect, instanceGlobal, m_LivingTime, m_LivedTime, m_pParent, m_pEffectNode->DynamicFactor);
m_pEffectNode->TranslationParam.InitializeTranslationState(translation_state_, prevPosition_, steering_vec_, rand, effect, instanceGlobal, m_LivingTime, m_LivedTime, m_pParent, m_pEffectNode->DynamicFactor);

RotationFunctions::InitRotation(rotation_values, m_pEffectNode->RotationParam, rand, effect, instanceGlobal, m_LivingTime, m_LivedTime, m_pParent, m_pEffectNode->DynamicFactor);
ScalingFunctions::InitScaling(scaling_values, m_pEffectNode->ScalingParam, rand, effect, instanceGlobal, m_LivingTime, m_LivedTime, m_pParent, m_pEffectNode->DynamicFactor);
Expand Down Expand Up @@ -591,65 +591,87 @@ void Instance::UpdateTransform(float deltaFrame)
UpdateParentMatrix(deltaFrame);
}

float accerarationDelta = deltaFrame;
float acceraration_delta = deltaFrame;
if (deltaFrame > 1)
{
// trapezoid interporation
accerarationDelta = ((1.0f + 1.0f / deltaFrame) / 2.0f) * deltaFrame;
acceraration_delta = ((1.0f + 1.0f / deltaFrame) / 2.0f) * deltaFrame;
}

SIMD::Vec3f localPosition = prevPosition_;
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)
const auto calculate_acc = [&](SIMD::Vec3f& steeringVec, InstanceTranslationState& translation_state, RandObject& rand_obj, float living_time, float deltaFrame)
{
SIMD::Vec3f worldPos = SIMD::Vec3f::Transform(localPosition, m_ParentMatrix);
SIMD::Vec3f toTarget = parentPosition_ - worldPos;
SIMD::Vec3f acc = SIMD::Vec3f(0, 0, 0);

if (toTarget.GetLength() > followParentParam.maxFollowSpeed)
if (m_pEffectNode->CommonValues.TranslationBindType == TranslationParentBindType::NotBind_FollowParent ||
m_pEffectNode->CommonValues.TranslationBindType == TranslationParentBindType::WhenCreating_FollowParent)
{
toTarget = toTarget.GetNormal();
toTarget *= followParentParam.maxFollowSpeed;
}
SIMD::Vec3f worldPos = SIMD::Vec3f::Transform(localPosition, m_ParentMatrix);
SIMD::Vec3f toTarget = parentPosition_ - worldPos;

auto prevSteering = steeringVec_;
SIMD::Vec3f vSteering = toTarget - steeringVec_;
vSteering *= followParentParam.steeringSpeed;
if (toTarget.GetLength() > followParentParam.maxFollowSpeed)
{
toTarget = toTarget.GetNormal();
toTarget *= followParentParam.maxFollowSpeed;
}

steeringVec_ += vSteering * deltaFrame;
auto prevSteering = steeringVec;
SIMD::Vec3f vSteering = toTarget - steeringVec;
vSteering *= followParentParam.steeringSpeed;

if (steeringVec_.GetLength() > followParentParam.maxFollowSpeed)
{
steeringVec_ = steeringVec_.GetNormal();
steeringVec_ *= followParentParam.maxFollowSpeed;
}
steeringVec += vSteering * deltaFrame;

localAcc = (steeringVec_ - prevSteering) * m_pEffectNode->m_effect->GetMaginification();
}
else
{
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 (steeringVec.GetLength() > followParentParam.maxFollowSpeed)
{
steeringVec = steeringVec.GetNormal();
steeringVec *= followParentParam.maxFollowSpeed;
}

if (m_pEffectNode->GenerationLocation.EffectsRotation)
acc = (steeringVec - prevSteering) * m_pEffectNode->m_effect->GetMaginification();
}
else
{
// TODO : check rotation(It seems has bugs and it can optimize it)
localAcc = SIMD::Vec3f::Transform(localAcc, m_GenerationLocation.Get3x3SubMatrix());
acc = m_pEffectNode->TranslationParam.CalculateTranslationState(translation_state, rand_obj, m_pEffectNode->GetEffect(), m_pContainer->GetRootInstance(), living_time, 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)
acc = SIMD::Vec3f::Transform(acc, m_GenerationLocation.Get3x3SubMatrix());
}
}

return acc;
};

auto local_acc = calculate_acc(steering_vec_, translation_state_, m_randObject, m_LivingTime, deltaFrame);

// accelaration for rotation of velocity to avoid that a velocity is zero
SIMD::Vec3f local_acc_rot = SIMD::Vec3f(0, 0, 0);
if (RotationFunctions::CalculateInGlobal(m_pEffectNode->RotationParam))
{
const float delta_plus = 0.01f;
auto steering_vec_temp = steering_vec_;
auto translation_state_temp = translation_state_;
auto rand_obj_temp = m_randObject;
local_acc_rot = calculate_acc(steering_vec_temp, translation_state_temp, rand_obj_temp, m_LivingTime + delta_plus, delta_plus);
}

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);
SIMD::Mat43f matRot = SIMD::Mat43f::Identity;
if (!RotationFunctions::CalculateInGlobal(m_pEffectNode->RotationParam))
{
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)
{
// for compatibiliy
auto new_local_position = localPosition + (localVelocity * deltaFrame + localAcc * accerarationDelta);
auto new_local_position = localPosition + (localVelocity * deltaFrame + local_acc * acceraration_delta);

localAcc += forceField_.Update(
local_acc += forceField_.Update(
m_pEffectNode->LocalForceField,
new_local_position,
localVelocity,
Expand All @@ -658,8 +680,8 @@ void Instance::UpdateTransform(float deltaFrame)
m_pEffectNode->GetEffect()->GetSetting()->GetCoordinateSystem());
}

localPosition += localVelocity * deltaFrame + localAcc * accerarationDelta;
localVelocity += localAcc;
localPosition += localVelocity * deltaFrame + local_acc * acceraration_delta;
localVelocity += local_acc;
prevPosition_ = localPosition;
prevLocalVelocity_ = localVelocity;

Expand All @@ -685,12 +707,51 @@ void Instance::UpdateTransform(float deltaFrame)
assert(calcMat.IsValid());
}

bool recalculate_matrix = false;
SIMD::Vec3f acc_global_sum = SIMD::Vec3f(0, 0, 0);

if (m_pEffectNode->LocalForceField.IsGlobalEnabled)
{
recalculate_matrix = true;
InstanceGlobal* instanceGlobal = m_pContainer->GetRootInstance();
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;
acc_global_sum += acc_global;
}

if (m_pEffectNode->Collisions.IsEnabled)
{
recalculate_matrix = true;
SIMD::Vec3f s;
SIMD::Mat43f r;
SIMD::Vec3f t;
calcMat.GetSRT(s, r, t);

SIMD::Vec3f pos = calcMat.GetTranslation() + location_modify_global_ + (velocity_modify_global_ * deltaFrame + acc_global_sum * acceraration_delta);
SIMD::Vec3f vel = SIMD::Vec3f::Transform(prevLocalVelocity_, r) + (velocity_modify_global_ + acc_global_sum);

InstanceGlobal* instanceGlobal = m_pContainer->GetRootInstance();
const auto result = CollisionsFunctions::Update(collisionState_, m_pEffectNode->Collisions, pos, prevGlobalPosition_, vel, instanceGlobal->EffectGlobalMatrix.GetTranslation());
location_modify_global_ -= std::get<1>(result);
acc_global_sum += std::get<0>(result);
}

if (RotationFunctions::CalculateInGlobal(m_pEffectNode->RotationParam))
{
SIMD::Vec3f s;
SIMD::Mat43f r;
SIMD::Vec3f t;
calcMat.GetSRT(s, r, t);

const SIMD::Vec3f vel = SIMD::Vec3f::Transform(prevLocalVelocity_ + local_acc_rot, r) + (velocity_modify_global_ + acc_global_sum);
SIMD::Mat43f matRotGlobal = RotationFunctions::CalculateRotationGlobal(rotation_values, m_pEffectNode->RotationParam, vel);
calcMat = SIMD::Mat43f::SRT(s, matRotGlobal, t);
}

if (recalculate_matrix)
{
location_modify_global_ += velocity_modify_global_ * deltaFrame + acc_global_sum * acceraration_delta;
velocity_modify_global_ += acc_global_sum;

SIMD::Mat43f mat_location_global = SIMD::Mat43f::Translation(location_modify_global_);
calcMat *= mat_location_global;
}
Expand Down
7 changes: 5 additions & 2 deletions Dev/Cpp/Effekseer/Effekseer/Effekseer.Instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "ForceField/ForceFields.h"

#include "Parameter/AlphaCutoff.h"
#include "Parameter/Collisions.h"
#include "Parameter/CustomData.h"
#include "Parameter/Rotation.h"
#include "Parameter/Scaling.h"
Expand Down Expand Up @@ -75,7 +76,7 @@ class alignas(16) Instance : public IntrusiveList<Instance>::Node

SIMD::Vec3f parentPosition_;

SIMD::Vec3f steeringVec_;
SIMD::Vec3f steering_vec_;

SIMD::Vec3f location_modify_global_;
SIMD::Vec3f velocity_modify_global_;
Expand Down Expand Up @@ -116,7 +117,7 @@ class alignas(16) Instance : public IntrusiveList<Instance>::Node
float steeringSpeed;
} followParentParam;

InstanceTranslationState translation_values;
InstanceTranslationState translation_state_;

RotationState rotation_values;

Expand Down Expand Up @@ -178,6 +179,8 @@ class alignas(16) Instance : public IntrusiveList<Instance>::Node

float m_AlphaThreshold = 0.0f;

CollisionsState collisionState_;

Instance(ManagerImplemented* pManager, EffectNodeImplemented* pEffectNode, InstanceContainer* pContainer, InstanceGroup* pGroup);

virtual ~Instance();
Expand Down
64 changes: 64 additions & 0 deletions Dev/Cpp/Effekseer/Effekseer/Parameter/Collisions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "Collisions.h"
#include <string.h>

namespace Effekseer
{

void CollisionsParameter::Load(unsigned char*& pos, int version)
{
if (version >= Version18Alpha1)
{
int isEnabled = 0;
memcpy(&isEnabled, pos, sizeof(int));
pos += sizeof(int);

IsEnabled = isEnabled > 0;

memcpy(&Bounce, pos, sizeof(float));
pos += sizeof(float);

memcpy(&Height, pos, sizeof(float));
pos += sizeof(float);

memcpy(&WorldCoordinateSyatem, pos, sizeof(int));
pos += sizeof(int);
}
}

std::tuple<SIMD::Vec3f, SIMD::Vec3f> CollisionsFunctions::Update(
CollisionsState& state,
const CollisionsParameter& parameter,
const SIMD::Vec3f& next_position_global,
const SIMD::Vec3f& position_global,
const SIMD::Vec3f& velocity_global,
const SIMD::Vec3f& position_center_local)
{
if (!parameter.IsEnabled)
{
return {
SIMD::Vec3f(0, 0, 0), SIMD::Vec3f(0, 0, 0)};
}

auto next_position = next_position_global;
auto current_position = position_global;

if (parameter.WorldCoordinateSyatem == WorldCoordinateSyatemType::Local)
{
next_position -= position_center_local;
current_position -= position_center_local;
}

if (next_position.GetY() < parameter.Height && current_position.GetY() >= parameter.Height)
{
auto diff = next_position - current_position;
auto pos_diff = diff * (current_position.GetY() - parameter.Height) / diff.GetY();
return {SIMD::Vec3f(0, -velocity_global.GetY() * (1.0f + parameter.Bounce), 0), pos_diff};
}
else
{
return {
SIMD::Vec3f(0, 0, 0), SIMD::Vec3f(0, 0, 0)};
}
}

} // namespace Effekseer
Loading

0 comments on commit c970772

Please sign in to comment.