public void Update(float deltaTime, EcsWorld world)
        {
            BroadphaseSAPComponent bpChunks =
                world.GetOrCreateSingleton <BroadphaseSAPComponent>();

            foreach (BroadphasePair pair in bpChunks.Pairs)
            {
                IEcsEntity entityA = pair.EntityA;
                IEcsEntity entityB = pair.EntityB;

                TransformComponent ta = entityA.GetComponent <TransformComponent>();
                TransformComponent tb = entityB.GetComponent <TransformComponent>();
                ColliderComponent  ca = entityA.GetComponent <ColliderComponent>();
                ColliderComponent  cb = entityB.GetComponent <ColliderComponent>();

                ContactInfo info;
                if (ca.ColliderType == ColliderType.Circle && cb.ColliderType == ColliderType.Circle)
                {
                    OnCircleCircleCollision(ca, ta, cb, tb, out info);
                }
                else if (ca.ColliderType == ColliderType.Circle && cb.ColliderType == ColliderType.Rect)
                {
                    OnCircleRectCollision(ca, ta, cb, tb, out info);
                }
                else if (ca.ColliderType == ColliderType.Rect && cb.ColliderType == ColliderType.Circle)
                {
                    OnCircleRectCollision(cb, tb, ca, ta, out info);
                    info.Normal = -info.Normal;
                }
                else
                {
                    throw new InvalidOperationException();
                }

                if (!info.Hit)
                {
                    continue;
                }

                RigBodyComponent ra = entityA.GetComponent <RigBodyComponent>();
                RigBodyComponent rb = entityB.GetComponent <RigBodyComponent>();

                float2 rv = rb.Velocity - ra.Velocity;

                float contactVel = math.dot(rv, info.Normal);
                float invMassSum = ra.InvMass + rb.InvMass;

                float  f       = -contactVel / invMassSum;
                float2 impulse = info.Normal * f * deltaTime;

                ra.Velocity -= ra.InvMass * impulse;
                rb.Velocity += rb.InvMass * impulse;

                float2 correction = info.Penetration / (ra.InvMass + rb.InvMass) * info.Normal * 0.5f;
                ta.Position -= correction * ra.InvMass;
                tb.Position += correction * rb.InvMass;
            }
        }
        public unsafe void Update(float deltaTime, EcsWorld world)
        {
            BroadphaseSAPComponent bpChunks = world.GetOrCreateSingleton <BroadphaseSAPComponent>();

            IEcsEntity[] entities = world.Filter(_entitiesFilter).ToEntityArray();

            for (int i = 0; i < entities.Length; i++)
            {
                IEcsEntity entity   = entities[i];
                uint       entityId = entity.Id;

                TransformComponent tr  = entity.GetComponent <TransformComponent>();
                ColliderComponent  col = entity.GetComponent <ColliderComponent>();
                RigBodyComponent   rig = entity.GetComponent <RigBodyComponent>();

                AABB aabb     = new AABB(col.Size, tr.Position, col.ColliderType == ColliderType.Rect ? tr.Rotation : 0f);
                bool isStatic = MathHelper.Equal(rig.InvMass, 0);
                int  layer    = col.Layer;

                List <SAPChunk> chunks = new List <SAPChunk>(4);
                foreach (int chunkId in BroadphaseHelper.GetChunks(aabb))
                {
                    chunks.Add(BroadphaseHelper.GetOrCreateChunk(chunkId, bpChunks));
                }

                BroadphaseRefComponent bpRef = new BroadphaseRefComponent
                {
                    Chunks     = chunks,
                    ChunksHash = BroadphaseHelper.CalculateChunksHash(aabb),
                    AABB       = aabb
                };
                entity.AddComponent(bpRef);

                foreach (SAPChunk chunk in chunks)
                {
                    if (chunk.Length >= chunk.Items.Length)
                    {
                        Array.Resize(ref chunk.Items, 2 * chunk.Length);

                        fixed(AABB *pAABB = &bpRef.AABB)
                        {
                            chunk.Items[chunk.Length++] = new BroadphaseAABB
                            {
                                AABB     = pAABB,
                                Id       = entityId,
                                IsStatic = isStatic,
                                Layer    = layer,
                                Entity   = entity
                            };
                        }

                        if (!isStatic)
                            chunk.DynamicCounter++; }
                }
            }
        }
예제 #3
0
        public unsafe void Update(float deltaTime, EcsWorld world)
        {
            BroadphaseSAPComponent bpChunks = world.GetOrCreateSingleton <BroadphaseSAPComponent>();

            world.Filter(_entitiesFilter).ForEach(
                (IEcsEntity entity, TransformComponent tr, ColliderComponent col, BroadphaseRefComponent bpRef) =>
            {
                AABB aabb = new AABB(col.Size, tr.Position,
                                     col.ColliderType == ColliderType.Rect ? tr.Rotation : 0f);

                fixed(AABB * pAABB = &bpRef.AABB)
                {
                    pAABB->Min = aabb.Min;
                    pAABB->Max = aabb.Max;
                }

                int chunksHash = BroadphaseHelper.CalculateChunksHash(aabb);
                if (bpRef.ChunksHash == chunksHash)
                {
                    return;
                }

                RigBodyComponent rig = entity.GetComponent <RigBodyComponent>();

                uint entityId = entity.Id;
                bool isStatic = MathHelper.Equal(rig.InvMass, 0);
                int layer     = col.Layer;

                List <SAPChunk> chunks    = bpRef.Chunks;
                List <SAPChunk> newChunks = new List <SAPChunk>(4);
                foreach (int chunkId in BroadphaseHelper.GetChunks(aabb))
                {
                    int index = -1;
                    for (int i = 0; i < chunks.Count; i++)
                    {
                        SAPChunk chunk = chunks[i];
                        if (chunk == null || chunk.Id != chunkId)
                        {
                            continue;
                        }

                        index = i;
                        break;
                    }

                    if (index >= 0)
                    {
                        SAPChunk chunk = chunks[index];
                        chunks[index]  = null;
                        newChunks.Add(chunk);
                    }
                    else
                    {
                        SAPChunk chunk = BroadphaseHelper.GetOrCreateChunk(chunkId, bpChunks);

                        if (chunk.Length >= chunk.Items.Length)
                        {
                            Array.Resize(ref chunk.Items, 2 * chunk.Length);
                        }

                        fixed(AABB * pAABB = &bpRef.AABB)
                        {
                            chunk.Items[chunk.Length++] = new BroadphaseAABB
                            {
                                AABB     = pAABB,
                                Id       = entityId,
                                IsStatic = isStatic,
                                Layer    = layer,
                                Entity   = entity
                            };
                        }

                        if (!isStatic)
                        {
                            chunk.DynamicCounter++;
                        }

                        newChunks.Add(chunk);
                    }
                }

                foreach (SAPChunk chunk in chunks)
                {
                    if (chunk == null)
                    {
                        continue;
                    }
                    BroadphaseHelper.RemoveFormChunk(chunk, entityId);
                }

                bpRef.Chunks     = newChunks;
                bpRef.ChunksHash = chunksHash;
            });
        }