Unreal Engine 4-インタラクティブロープの構築
ステルスドラゴンパス:トレース中のフック爪遊び方では、ロープはUE 4のケーブルComponentを使用して構築されています.当初はこの方面のソースコードとドキュメントを見て、Unreal Engine 4のブログコラムで対応情報を検索することができます:転送ゲート.
UE 4のこのケーブルComponentは世界のシーンとインタラクティブではないので、このブログでは、このケーブルComponentに基づいてロープと世界のインタラクティブを実現する方法について説明します.
UE 4の
UE 4のコードは以下の通りである.
ロープと球形物体の相互作用をどのように実現すればいいですか?相対的には簡単で、リラックス法に検出を加えるだけです.ケーブルパーティクルが対応する球形の中に落ちたら、球面に直接押すだけです.
では、
Particleと物体の衝突を制約するために
これによりロープと球形の衝突が交互に実現される.
ロープとカプセルの衝突拘束も簡単で、対応する点をカプセルの表面に押すだけでよい.ここではコードを放出するのが不便で、読者は自分で実現することができます.
UE 4のCable ComponentはVerlet Integrationを使用し,MeshはSceneProxyで構築する.ここでは球形&カプセル体との衝突が実現し、これで生地&ヘアピン&水面のシミュレーションが容易に実現できるのでしょうか…
UE 4のこのケーブルComponentは世界のシーンとインタラクティブではないので、このブログでは、このケーブルComponentに基づいてロープと世界のインタラクティブを実現する方法について説明します.
Verlet Integration
UCableComponent
のソースコードを表示すると、Tick関数に次のようなコードが表示されます.// Perform simulation substeps
TimeRemainder += DeltaTime;
while(TimeRemainder > UseSubstep)
{
PerformSubstep(UseSubstep, Gravity);
TimeRemainder -= UseSubstep;
}
PerformSubstep
関数の実装は次のとおりです.void UCableComponent::PerformSubstep(float InSubstepTime, const FVector& Gravity)
{
VerletIntegrate(InSubstepTime, Gravity);
SolveConstraints();
}
VerletIntegrate
関数を見て笑った.当初は専門的に研究していたので、対応する論文は以下の通りだ.Cable Particle
UE 4の
UCableComponent
では、ケーブルパーティクルを用いてロープをシミュレートし、Verlet Integrationと弛緩法を用いてロープ粒子のシミュレーションを行い、対応するSceneProxy
でMeshの構築を行う.UE 4のコードは以下の通りである.
void UCableComponent::SolveConstraints()
{
const float SegmentLength = CableLength/(float)NumSegments;
// For each iteration..
for(int32 IterationIdx=0; IterationIdx<SolverIterations; IterationIdx++)
{
// For each segment..
for(int32 SegIdx=0; SegIdx<NumSegments; SegIdx++)
{
FCableParticle& ParticleA = Particles[SegIdx];
FCableParticle& ParticleB = Particles[SegIdx+1];
// Solve for this pair of particles
SolveDistanceConstraint(ParticleA, ParticleB, SegmentLength);
}
}
}
球形物体とのインタラクション
ロープと球形物体の相互作用をどのように実現すればいいですか?相対的には簡単で、リラックス法に検出を加えるだけです.ケーブルパーティクルが対応する球形の中に落ちたら、球面に直接押すだけです.
では、
SolveConstraints
関数を次のように変更します.void UCableComponent::SolveConstraints()
{
const float SegmentLength = CableLength/(float)NumSegments;
// For each iteration..
for(int32 IterationIdx=0; IterationIdx<SolverIterations; IterationIdx++)
{
SolveCollides();
// For each segment..
for(int32 SegIdx=0; SegIdx<NumSegments; SegIdx++)
{
FCableParticle& ParticleA = Particles[SegIdx];
FCableParticle& ParticleB = Particles[SegIdx+1];
// Solve for this pair of particles
SolveDistanceConstraint(ParticleA, ParticleB, SegmentLength);
}
}
}
Particleと物体の衝突を制約するために
SolveCollides
関数が1つだけ追加されました.void UCableComponent::SolveCollides()
{
for (int32 SegIdx = 0; SegIdx < NumSegments SegIdx++)
{
for (int SphereIdx = 0; SphereIdx < CollideSphere.Num(); SphereIdx++)
{
SolveSphereCollide(Particles[SegIdx + 1], CollideSphere[SphereIdx]);
}
}
}
void UCableComponent::SolveSphereCollide(FStripParticle& Particle, FComponentReference Comp)
{
auto Component = Comp.GetComponent(GetOwner());
if (IsValid(Component))
{
if (Particle.bFree)
{
const float dist = FVector::Dist(Component->GetComponentLocation(), Particle.Position);
auto sphere = Cast<USphereComponent>(Component);
if (sphere && dist < (sphere->GetScaledSphereRadius()))
{
auto tmp1 = Particle.Position;
auto tmp2 = sphere->GetComponentLocation();
auto tmp3 = sphere->GetScaledSphereRadius();
auto delta = tmp3 * ((tmp1 - tmp2).GetSafeNormal());
Particle.Position = Component->GetComponentLocation() + delta;
}
}
}
}
これによりロープと球形の衝突が交互に実現される.
カプセルとの衝突
ロープとカプセルの衝突拘束も簡単で、対応する点をカプセルの表面に押すだけでよい.ここではコードを放出するのが不便で、読者は自分で実現することができます.
考える
UE 4のCable ComponentはVerlet Integrationを使用し,MeshはSceneProxyで構築する.ここでは球形&カプセル体との衝突が実現し、これで生地&ヘアピン&水面のシミュレーションが容易に実現できるのでしょうか…