Unity 布料仿真笔记2 欧拉积分 Verlet积分分析

前言

An object at rest remains at rest, unless acted upon by an exterior force. An object in motion remains in motion, at a constant speed, and in the same direction, unless acted upon by an exterior force

欧拉积分

欧拉积分其实分为隐式欧拉隐式欧拉,为了简单开发,这里使用显式欧拉方法进行积分。当然这里说的简单开发,可不是简单了一点,实际隐式欧拉的求解相比显示欧拉的求解更加复杂,而且对于游戏来说也无必要。欧式积分,其实可以看成我们假定在一个规定的时间,物体的速度是一致的。那么在这个一致速度的时间范围内,我们就能很好去求解质点下一刻的状态。

在显式欧拉积分中,下一时刻的位置与当前的速度和当前的位置有关。
不过欧拉方法中,有一些是我们不希望的。由于我们并不是完全按照物理模型去仿真,因此在每一步计算的时候总会有一些误差。在欧拉积分中,每一步会逐步的累计误差。

积分公式

V t + 1 = V t + a Δ t V_{t+1}=V_{t} + a \Delta t Vt+1=Vt+aΔt
X t + 1 = X t + V t Δ t X_{t+1}=X_{t} + V_{t} \Delta t Xt+1=Xt+VtΔt
公式中, X X X是位置, V V V是速度

C#代码分析

    // Euler
    // Most integral mathod have convergance feature
    // So In Explicit Euler Mathod , 
    // I give a air resistance to speed up the aconvergance
    public void ExplicitEulerMathod(float deltaTime)
    {
        foreach (var item in Springs)
        {
            // euler
            // spring force

            Vector3 spingforce = Springk * item.GetCurentLength().normalized * (item.GetCurentLength().magnitude - item.RestLength);
            item.Mass1.Force += spingforce;
            item.Mass2.Force -= spingforce;
            Debug.DrawLine(item.Mass1.Position, item.Mass2.Position);
        }

        foreach (var item in Masses)
        {
            if (!item.isPined)
            {
                item.Force += Gravity;
                item.Force -= item.Velocity * AirResistanceFactor;

                item.Velocity += (item.Force / item.MassValue) * deltaTime;
                item.Position += item.Velocity * deltaTime;
            }
            item.Force = Vector3.zero;
        }
    }

Verlet积分

Verlet积分参考
Verlet积分会使用上一个时刻的状态来推下一个时刻的状态。Verlet是一种基于位置的积分,在计算时,上一时刻和当前时刻的位置很重要,然而速度在这里却不那么重要,但是我们可以计算速度,以方便用来计算其他的参数,例如空气阻力。
当我们计算得到下一个时刻的位置,我们需要根据弹簧质点的特性对当前位置进行约束。约束方法就是,假设我们的弹簧是一个弹性系数无限大,不可拉伸的弹簧。当我们计算得到下一个时刻的位置的时候,就需要进行位置修正。

积分公式

X t + 1 = X t + ( X t − X t − 1 ) + a t ∗ Δ t ∗ Δ t X_{t+1}=X_{t} + (X_{t}-X_{t -1})+a_{t} *\Delta t*\Delta t Xt+1=Xt+(XtXt1)+atΔtΔt

C#代码分析

// Verlet mathod
    // 
    public void VerletMathod(float deltaTime)
    {
        // first , get the final position of mass
        // second , constraint the positon to the rest length

        foreach (var item in Masses)
        {
            if (!item.isPined)
            {
                Vector3 tempPosition = item.Position;

                item.Force = Gravity;
                // Verlet integration
                item.Position += (1f - AirResistanceFactor) * (item.Position - item.LastPosition) + (item.Force / item.MassValue) * deltaTime * deltaTime;

                item.LastPosition = tempPosition;
            }
        }
        foreach (var item in Springs)
        {
            Vector3 subtract = item.Mass1.Position - item.Mass2.Position;
            subtract = subtract.normalized * (subtract.magnitude - item.RestLength);

            if (item.Mass1.isPined)
            {
                item.Mass2.Position += subtract;
            }
            else if (item.Mass2.isPined)
            {
                item.Mass1.Position -= subtract;
            }
            else
            {
                item.Mass1.Position -= subtract/2.0f;
                item.Mass2.Position += subtract/2.0f;
            }
            // Draing line on scene view
            Debug.DrawLine(item.Mass1.Position, item.Mass2.Position);
        }
    }

总结

从仿真效果来看,不同的算法效果都还不错。。但是仿真内容下一篇笔记将会记录使用龙格库塔积分进行计算的方法。

参考

[1]Verlet Integration : http://datagenetics.com/blog/july22018/index.html
[2]Git Repository:https://github.com/HanochZhu/PhysicSimulation
先留个坑,有空来写。
创作不易,如果你觉得帮到了你,点赞、收藏、关注三连哦

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值