Protfolio-Emanuel-Polsky / Assets / _Project / Code / VerletIntegration / Tear / System / CheckStretchesSystem.cs
CheckStretchesSystem.cs
Raw
using GarmentButton.VerletIntegration.Interaction;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;


namespace GarmentButton.VerletIntegration.Tear
{
    [UpdateInGroup(typeof(VerletIntegrationPhysicsGroupSystems))]
    [UpdateAfter(typeof(SimulateInteractionSystem))]
    [BurstCompile]
    public partial struct CheckStretchesSystem : ISystem
    {
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<EndSimulationEntityCommandBufferSystem.Singleton>();
            state.RequireForUpdate<Stick>();
            state.RequireForUpdate<Point>();
            state.RequireForUpdate<Tringle>();
            state.RequireForUpdate<TearLenght>();
        }

        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            var ecb = SystemAPI.GetSingleton<EndSimulationEntityCommandBufferSystem.Singleton>()
                .CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter();

            state.Dependency = new CheckStretchesJob
            {
                ECB = ecb,
            }.ScheduleParallel(state.Dependency);
        }

        [BurstCompile]
        [WithAll(typeof(TearLenght))]
        public partial struct CheckStretchesJob : IJobEntity
        {
            public EntityCommandBuffer.ParallelWriter ECB;

            public void Execute(
                Entity entity,
                [ChunkIndexInQuery] int sortKey,
                in TearLenght tearLenght,
                in DynamicBuffer<Point> points,
                ref DynamicBuffer<Stick> sticks,
                ref DynamicBuffer<Tringle> tringles)
            {
                if (sticks.Length == 0 || tringles.Length == 0)
                    return;

                var hasChanged = false;

                for (var i = 0; i < sticks.Length; i++)
                {
                    var stick = sticks[i];
                    if (!stick.Active)
                        continue;

                    var delta = points[stick.PointA].Position - points[stick.PointB].Position;
                    var maxLength = stick.Lenght * Stick.CONVERTION_RATE + tearLenght.Value;
                    if (math.lengthsq(delta) <= maxLength * maxLength)
                        continue;

                    stick.Active = false;
                    sticks[i] = stick;
                    RemoveConnectedTringles(stick.PointA, stick.PointB, ref tringles, ref hasChanged);
                }

                if (hasChanged)
                    ECB.AddComponent<UpdatedTringlesTag>(sortKey, entity);
            }

            private static void RemoveConnectedTringles(
                short pointA,
                short pointB,
                ref DynamicBuffer<Tringle> tringles,
                ref bool hasChanged)
            {
                for (var i = 0; i < tringles.Length; i += 3)
                {
                    var tringleEdge = tringles[i];
                    var tringleEdge2 = tringles[i + 1];
                    var tringleEdge3 = tringles[i + 2];

                    if (tringleEdge.Index == 0 && tringleEdge2.Index == 0 && tringleEdge3.Index == 0)
                        continue;

                    var hasPointA = IsOneOfThem(pointA, tringleEdge, tringleEdge2, tringleEdge3);
                    var hasPointB = IsOneOfThem(pointB, tringleEdge, tringleEdge2, tringleEdge3);
                    
                    if (!hasPointA || !hasPointB) continue;
                    
                    tringleEdge.Index = 0;

                    tringles[i] = tringleEdge;
                    tringles[i + 1] = tringleEdge;
                    tringles[i + 2] = tringleEdge;
                    hasChanged = true;
                }
            }

            private static bool IsOneOfThem(short point, Tringle tringleEdge, Tringle tringleEdge2, Tringle tringleEdge3)
            {
                return tringleEdge.Index == point || tringleEdge2.Index == point || tringleEdge3.Index == point;
            }
        }
    }

    public struct UpdatedTringlesTag : IComponentData
    {
    }
}