예제 #1
0
        public static unsafe bool ColliderCastAllTargets(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider, ref NativeList <Entity> allHitEntities)
        {
            ColliderCastInput input = new ColliderCastInput()
            {
                Collider    = (Collider *)collider.Value.GetUnsafePtr(),
                Orientation = rotation,
                Start       = rayFrom,
                End         = rayTo
            };

            NativeList <ColliderCastHit> colliderCastHits = new NativeList <ColliderCastHit>(Allocator.Temp);

            if (collisionWorld.CastCollider(input, ref colliderCastHits))
            {
                //Extract entities
                for (int i = 0; i < colliderCastHits.Length; ++i)
                {
                    allHitEntities.Add(colliderCastHits[i].Entity);
                }

                return(true);
            }

            return(false);
        }
            public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                var chunkTranslations = chunk.GetNativeArray(TranslationType);
                var chunkFighterSearchInputBuffers       = chunk.GetBufferAccessor(FighterSearchInputBufferType);
                var chunkFighterSearchHitDistanceBuffers = chunk.GetBufferAccessor(FighterSearchHitDistanceBufferType);

                for (var i = 0; i < chunk.Count; ++i)
                {
                    DynamicBuffer <FighterSearchInputBuffer>       input_buf = chunkFighterSearchInputBuffers[i];
                    DynamicBuffer <FighterSearchHitDistanceBuffer> hit_buf   = chunkFighterSearchHitDistanceBuffers[i];
                    for (var j = 0; j < input_buf.Length; ++j)
                    {
                        ColliderCastHit hit;
                        bool            hitted = world.CastCollider(input_buf[j].Value, out hit);
                        if (hitted)
                        {
                            hit_buf[j] = new FighterSearchHitDistanceBuffer {
                                Value = math.length(hit.Position - chunkTranslations[i].Value),
                            };
                        }
                        else
                        {
                            hit_buf[j] = new FighterSearchHitDistanceBuffer {
                                Value = float.MaxValue,
                            };
                        }
                    }
                    ;
                }
            }
예제 #3
0
        public static unsafe bool ColliderCast(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider)
        {
            ColliderCastInput input = new ColliderCastInput()
            {
                Collider    = (Collider *)collider.Value.GetUnsafePtr(),
                Orientation = rotation,
                Start       = rayFrom,
                End         = rayTo
            };

            return(collisionWorld.CastCollider(input));
        }
예제 #4
0
        public static unsafe bool BoxCast(float3 rayFrom, float3 rayTo, CollisionWorld collisionWorld, BoxGeometry boxGeometry, CollisionFilter collisionFilter)
        {
            BlobAssetReference <Collider> boxCollider = BoxCollider.Create(boxGeometry, collisionFilter);

            ColliderCastInput input = new ColliderCastInput()
            {
                Collider    = (Collider *)boxCollider.GetUnsafePtr(),
                Orientation = quaternion.identity,
                Start       = rayFrom,
                End         = rayTo
            };

            return(collisionWorld.CastCollider(input));
        }
예제 #5
0
    public unsafe static void SphereCastAll(CollisionWorld world, float radius, uint mask, float3 origin, float3 direction, NativeList <ColliderCastHit> results)
    {
        var sphereCollider = Unity.Physics.SphereCollider.Create(float3.zero, radius,
                                                                 new CollisionFilter()
        {
            CategoryBits = mask, MaskBits = mask, GroupIndex = (int)mask
        });
        ColliderCastInput input = new ColliderCastInput()
        {
            Position    = origin,
            Orientation = quaternion.identity,
            Direction   = direction,
            Collider    = (Collider *)sphereCollider.GetUnsafePtr()
        };

        world.CastCollider(input, ref results);
    }
예제 #6
0
    /// <summary>
    /// Performs a collider cast along the specified ray and returns all resulting <see cref="ColliderCastHit"/>s.<para/>
    ///
    /// The caller must dispose of the returned list.
    /// </summary>
    /// <param name="collider"></param>
    /// <param name="from"></param>
    /// <param name="to"></param>
    /// <param name="collisionWorld"></param>
    /// <param name="ignore">Will ignore this entity if it was hit. Useful to prevent returning hits from the caster.</param>
    /// <returns></returns>
    public unsafe static NativeList <ColliderCastHit> ColliderCastAll(PhysicsCollider collider, float3 from, float3 to, ref CollisionWorld collisionWorld, Entity ignore, Allocator allocator = Allocator.TempJob)
    {
        ColliderCastInput input = new ColliderCastInput()
        {
            Collider = collider.ColliderPtr,
            Start    = from,
            End      = to
        };

        NativeList <ColliderCastHit> allHits = new NativeList <ColliderCastHit>(allocator);

        if (collisionWorld.CastCollider(input, ref allHits))
        {
            TrimByEntity(ref allHits, ignore);
        }

        return(allHits);
    }
예제 #7
0
    public unsafe static NativeArray <Entity> GetNearbyObjects(Entity e, float3 translation, quaternion rotation, PhysicsCollider physicsCollider, BuildPhysicsWorld physicsWorldSystem)
    {
        CollisionWorld       world = physicsWorldSystem.PhysicsWorld.CollisionWorld;;
        NativeArray <Entity> context;
        var filter = new CollisionFilter()
        {
            BelongsTo    = ~0u,
            CollidesWith = ~0u, // all 1s, so all layers, collide with everything
            GroupIndex   = 0
        };

        SphereGeometry sphereGeometry = new SphereGeometry()
        {
            Center = float3.zero, Radius = 3f
        };
        BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(sphereGeometry, filter);
        NativeList <ColliderCastHit>  colliderHit    = new NativeList <ColliderCastHit>();
        ColliderCastInput             input          = new ColliderCastInput()
        {
            Collider    = (Collider *)sphereCollider.GetUnsafePtr(),
            Orientation = quaternion.identity,
            Start       = translation,
            End         = translation
        };

        if (world.CastCollider(input, ref colliderHit))
        {
            int compteur = 0;
            context = new NativeArray <Entity>(colliderHit.Length, Allocator.Temp);
            foreach (var collider in colliderHit)
            {
                context[compteur] = collider.Entity;
                compteur++;
            }
            Debug.Log(context.Length);
        }
        else
        {
            context = new NativeArray <Entity>(0, Allocator.Temp);
            Debug.Log("inhere");
        }
        return(context);
    }
예제 #8
0
        public static unsafe Entity ColliderCast(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider, PhysicsWorld physicsWorld)
        {
            ColliderCastInput input = new ColliderCastInput()
            {
                Collider    = (Collider *)collider.Value.GetUnsafePtr(),
                Orientation = rotation,
                Start       = rayFrom,
                End         = rayTo
            };

            ColliderCastHit hit = new ColliderCastHit();

            if (collisionWorld.CastCollider(input, out hit))
            {
                return(physicsWorld.Bodies[hit.RigidBodyIndex].Entity);
            }

            return(Entity.Null);
        }
        unsafe public void Execute(int index)
        {
            var center = math.lerp(upperRightPosition, lowerLeftPosition, 0.5f);
            var size   = new float3(startPosition.x - endPosition.x,
                                    startPosition.y - endPosition.y,
                                    1);
            var filter = new CollisionFilter()
            {
                BelongsTo    = ~0u,
                CollidesWith = ~0u, // all 1s, so all layers, collide with everything
                GroupIndex   = 0
            };

            BoxGeometry boxGeometry = new BoxGeometry()
            {
                Center = new float3(0, 0, 0) - new float3(startPosition.x - endPosition.x,
                                                          startPosition.y - endPosition.y,
                                                          1) / 2,
                Size        = (size * math.sign(size)) + new float3(1, 1, 1),
                Orientation = quaternion.identity,
                BevelRadius = 0,
            };
            BlobAssetReference <Unity.Physics.Collider> boxColliser = Unity.Physics.BoxCollider.Create(boxGeometry, filter);
            ColliderCastInput input = new ColliderCastInput()
            {
                Collider    = (Unity.Physics.Collider *)boxColliser.GetUnsafePtr(),
                Orientation = quaternion.identity,
                Start       = startPosition,
                End         = startPosition
            };
            NativeList <ColliderCastHit> allHits = new NativeList <ColliderCastHit> (500, Allocator.Temp);
            bool haveHit = collisionWorld.CastCollider(input, ref allHits);

            if (haveHit)
            {
                for (int i = 0; i < allHits.Length; i++)
                {
                    var    hit = allHits[i];
                    Entity e   = physicsWorld.Bodies[hit.RigidBodyIndex].Entity;
                    entityCommandBuffer.AddComponent(index, e, new SelectedTag());
                }
            }
        }
예제 #10
0
        public unsafe void  Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            BufferAccessor <ContactInfos> chunkContactInfosBuffers = chunk.GetBufferAccessor(ContactInfos);

            var colliders             = chunk.GetNativeArray(Collider);
            var colliderLocalToWorlds = chunk.GetNativeArray(LocalToWorld);

            for (var i = 0; i < chunk.Count; i++)
            {
                DynamicBuffer <ContactInfos> contactInfosBuffer = chunkContactInfosBuffers[i];

                contactInfosBuffer.Clear();

                float3 position = colliderLocalToWorlds[i].Position;

                ColliderCastInput colliderCastInput = new ColliderCastInput()
                {
                    Start    = position,
                    End      = position,
                    Collider = colliders[i].ColliderPtr
                };

                NativeList <ColliderCastHit> hits = new NativeList <ColliderCastHit>(Allocator.Temp);
                if (CollisionWorld.CastCollider(colliderCastInput, ref hits))
                {
                    foreach (var hit in hits)
                    {
                        if (Bodies[hit.RigidBodyIndex].Collider.GetUnsafePtr() == colliderCastInput.Collider)
                        {
                            continue;
                        }

                        contactInfosBuffer.Add(new ContactInfos()
                        {
                            Entity  = Bodies[hit.RigidBodyIndex].Entity,
                            Contact = hit
                        });
                    }
                }
                hits.Dispose();
            }
        }
예제 #11
0
    protected unsafe override void OnUpdate()
    {
        float          time       = Time.DeltaTime;
        float          dirForward = Input.GetAxis("Vertical");
        float          dirAngle   = Input.GetAxis("Horizontal");
        CollisionWorld world      = physicsWorldSystem.PhysicsWorld.CollisionWorld;

        Entities.ForEach((Entity e, ref PhysicsVelocity physicsVelocity, ref Rotation rotation, ref Translation translation, ref PhysicsCollider physicsCollider) =>
        {
            var filter = new CollisionFilter()
            {
                BelongsTo    = ~0u,
                CollidesWith = ~0u, // all 1s, so all layers, collide with everything
                GroupIndex   = 0
            };

            SphereGeometry sphereGeometry = new SphereGeometry()
            {
                Center = translation.Value, Radius = 10f
            };
            BlobAssetReference <Collider> sphereCollider = SphereCollider.Create(sphereGeometry, filter);
            NativeList <ColliderCastHit> colliderHit     = new NativeList <ColliderCastHit>(Allocator.Temp);
            ColliderCastInput input = new ColliderCastInput()
            {
                Collider    = (Collider *)sphereCollider.GetUnsafePtr(),
                Orientation = quaternion.identity,
                Start       = translation.Value,
                End         = translation.Value
            };
            world.CastCollider(input, ref colliderHit);
            //for (int i = 0; i < colliderHit.Length; i++)
            //{
            //Debug.Log(colliderHit[i].Entity + " / " + e.Index);
            //}
            //Debug.Log(colliderHit.Length);
            colliderHit.Dispose();
            //NativeArray<Entity> context = GetNearbyObjects(e, translation.Value, rotation.Value, physicsCollider, test);
            //context.Dispose();
        }).ScheduleParallel();
    }
예제 #12
0
    public unsafe static ColliderCastHit SphereCast(CollisionWorld world, float radius, uint mask, float3 origin, float3 direction)
    {
        var sphereCollider = Unity.Physics.SphereCollider.Create(float3.zero, radius,
                                                                 new CollisionFilter()
        {
            CategoryBits = mask, MaskBits = mask, GroupIndex = (int)mask
        });
        ColliderCastInput input = new ColliderCastInput()
        {
            Position    = origin,
            Orientation = quaternion.identity,
            Direction   = direction,
            Collider    = (Collider *)sphereCollider.GetUnsafePtr()
        };
        ColliderCastHit hit = new ColliderCastHit()
        {
            RigidBodyIndex = -1
        };

        world.CastCollider(input, out hit);
        return(hit);
    }
            public unsafe void Execute(int index)
            {
                Results.BeginForEachIndex(index);
                int numRows = (Request.ImageResolution + Results.ForEachCount - 1) / Results.ForEachCount;

                const float sphereRadius = 0.005f;
                BlobAssetReference <Collider> sphere;

                if (Request.CastSphere)
                {
                    sphere = SphereCollider.Create(float3.zero, sphereRadius, Request.CollisionFilter);
                }

                for (int yCoord = index * numRows; yCoord < math.min(Request.ImageResolution, (index + 1) * numRows); yCoord++)
                {
                    for (int xCoord = 0; xCoord < Request.ImageResolution; xCoord++)
                    {
                        float xFrac = 2.0f * ((xCoord / (float)Request.ImageResolution) - 0.5f);
                        float yFrac = 2.0f * ((yCoord / (float)Request.ImageResolution) - 0.5f);

                        float3 targetImagePlane = Request.ImageCenter + Request.Up * Request.PlaneHalfExtents * yFrac + Request.Right * Request.PlaneHalfExtents * xFrac;
                        float3 rayDir           = Request.RayLength * (Request.PinHole - targetImagePlane);

                        RaycastHit hit;
                        bool       hasHit;
                        if (Request.CastSphere)
                        {
                            var input = new ColliderCastInput
                            {
                                Collider    = (Collider *)sphere.GetUnsafePtr(),
                                Orientation = quaternion.identity,
                                Start       = Request.PinHole,
                                End         = Request.PinHole + rayDir
                            };
                            hasHit = World.CastCollider(input, out ColliderCastHit colliderHit);
                            hit    = new RaycastHit
                            {
                                Fraction       = colliderHit.Fraction,
                                Position       = colliderHit.Position,
                                SurfaceNormal  = colliderHit.SurfaceNormal,
                                RigidBodyIndex = colliderHit.RigidBodyIndex,
                                ColliderKey    = colliderHit.ColliderKey
                            };
                        }
                        else
                        {
                            var rayCastInput = new RaycastInput
                            {
                                Start  = Request.PinHole,
                                End    = Request.PinHole + rayDir,
                                Filter = Request.CollisionFilter
                            };
                            hasHit = World.CastRay(rayCastInput, out hit);
                        }

                        Color hitColor = Color.black;
                        if (hasHit)
                        {
                            if (hit.RigidBodyIndex < NumDynamicBodies)
                            {
                                hitColor = Color.yellow;
                            }
                            else
                            {
                                hitColor = Color.grey;
                            }

                            // Lighten alternate keys
                            if (Request.AlternateKeys && !hit.ColliderKey.Equals(ColliderKey.Empty))
                            {
                                Collider *collider = World.Bodies[hit.RigidBodyIndex].Collider;
                                hit.ColliderKey.PopSubKey(collider->NumColliderKeyBits, out uint key);
                                if (key % 2 == 0)
                                {
                                    Color.RGBToHSV(hitColor, out float h, out float s, out float v);
                                    hitColor = Color.HSVToRGB(h, s, v + 0.25f);
                                }
                            }

                            if (Request.Shadows)
                            {
                                float3 hitPos    = Request.PinHole + rayDir * hit.Fraction + hit.SurfaceNormal * 0.001f;
                                bool   shadowHit = false;

                                if (Request.CastSphere)
                                {
                                    var start = hitPos + hit.SurfaceNormal * sphereRadius;
                                    var input = new ColliderCastInput
                                    {
                                        Collider    = (Collider *)sphere.GetUnsafePtr(),
                                        Orientation = quaternion.identity,
                                        Start       = start,
                                        End         = start + (Request.LightDir * Request.RayLength),
                                    };
                                    ColliderCastHit colliderHit;
                                    shadowHit = World.CastCollider(input, out colliderHit);
                                }
                                else
                                {
                                    var rayCastInput = new RaycastInput
                                    {
                                        Start  = hitPos,
                                        End    = hitPos + (Request.LightDir * Request.RayLength),
                                        Filter = Request.CollisionFilter
                                    };
                                    RaycastHit shadowOutput;
                                    shadowHit = World.CastRay(rayCastInput, out shadowOutput);
                                }

                                if (shadowHit)
                                {
                                    hitColor *= 0.4f;
                                }
                            }
                        }

                        float lighting = math.min(1.0f, math.max(Request.AmbientLight, Vector3.Dot(hit.SurfaceNormal, Request.LightDir)));

                        Results.Write(xCoord);
                        Results.Write(yCoord);
                        Results.Write(hitColor * lighting);
                    }
                }

                Results.EndForEachIndex();
            }
예제 #14
0
        /// <summary>
        /// Gets the final position of a character attempting to move from a starting
        /// location with a given movement. The goal of this is to move the character
        /// but have the character 'bounce' off of objects at angles that are
        /// are along the plane perpendicular to the normal of the surface hit.
        /// This will cancel motion through the object and instead deflect it
        /// into another direction giving the effect of sliding along objects
        /// while the character's momentum is absorbed into the wall.
        /// </summary>
        /// <param name="commandBuffer">Command buffer for adding push events to objects</param>
        /// <param name="jobIndex">Index of this job for command buffer use</param>
        /// <param name="collisionWorld">World for checking collisions and other colliable objects</param>
        /// <param name="start">Starting location</param>
        /// <param name="movement">Intended direction of movement</param>
        /// <param name="collider">Collider controlling the character</param>
        /// <param name="entityIndex">Index of this entity</param>
        /// <param name="rotation">Current character rotation</param>
        /// <param name="physicsMassAccessor">Accessor to physics mass components</param>
        /// <param name="anglePower">Power to raise decay of movement due to
        /// changes in angle between intended movement and angle of surface.
        /// Will be angleFactor= 1 / (1 + normAngle) where normAngle is a normalized value
        /// between 0-1 where 1 is max angle (90 deg) and 0 is min angle (0 degrees).
        /// AnglePower is the power to which the angle factor is raised
        /// for a sharper decline. Value of zero negates this property.
        /// <param name="maxBounces">Maximum number of bounces when moving.
        /// After this has been exceeded the bouncing will stop. By default
        /// this is one assuming that each move is fairly small this should approximate
        /// normal movement.</param>
        /// <param name="pushPower">Multiplier for power when pushing on an object.
        /// Larger values mean more pushing.</param>
        /// <param name="pushDecay">How much does the current push decay the remaining
        /// movement by. Values between [0, 1]. A zero would mean all energy is lost
        /// when pushing, 1 means no momentum is lost by pushing. A value of 0.5
        /// would mean half of the energy is lost</param>
        /// <param name="epsilon">Epsilon parameter for pushing away from objects to avoid colliding
        /// with static objects. Should be some small float value that can be
        /// tuned for how much to push away while not allowing being shoved into objects.</param>
        /// <returns>The final location of the character.</returns>
        public static unsafe float3 ProjectValidMovement(
            EntityCommandBuffer.ParallelWriter commandBuffer,
            int jobIndex,
            CollisionWorld collisionWorld,
            float3 start,
            float3 movement,
            PhysicsCollider collider,
            int entityIndex,
            quaternion rotation,
            ComponentDataFromEntity <PhysicsMass> physicsMassGetter,
            float anglePower = 2,
            int maxBounces   = 1,
            float pushPower  = 25,
            float pushDecay  = 0,
            float epsilon    = 0.001f)
        {
            float3 from      = start;    // Starting location of movement
            float3 remaining = movement; // Remaining momentum
            int    bounces   = 0;        // current number of bounces

            // Continue computing while there is momentum and bounces remaining
            while (math.length(remaining) > epsilon && bounces <= maxBounces)
            {
                // Get the target location given the momentum
                float3 target = from + remaining;

                // Do a cast of the collider to see if an object is hit during this
                // movement action
                var input = new ColliderCastInput()
                {
                    Start       = from,
                    End         = target,
                    Collider    = collider.ColliderPtr,
                    Orientation = rotation
                };

                SelfFilteringClosestHitCollector <ColliderCastHit> hitCollector =
                    new SelfFilteringClosestHitCollector <ColliderCastHit>(entityIndex, 1.0f, collisionWorld);

                bool collisionOcurred = collisionWorld.CastCollider(input, ref hitCollector);

                if (!collisionOcurred && hitCollector.NumHits == 0)
                {
                    // If there is no hit, target can be returned as final position
                    return(target);
                }

                Unity.Physics.ColliderCastHit hit = hitCollector.ClosestHit;

                // Set the fraction of remaining movement (minus some small value)
                from = from + remaining * hit.Fraction;
                // Push slightly along normal to stop from getting caught in walls
                from = from + hit.SurfaceNormal * epsilon;

                // Apply some force to the object hit if it is moveable, Apply force on entity hit
                bool isKinematic = physicsMassGetter.HasComponent(hit.Entity) && IsKinematic(physicsMassGetter[hit.Entity]);
                if (hit.RigidBodyIndex < collisionWorld.NumDynamicBodies && !isKinematic)
                {
                    commandBuffer.AddBuffer <PushForce>(jobIndex, hit.Entity);
                    commandBuffer.AppendToBuffer(jobIndex, hit.Entity, new PushForce()
                    {
                        force = movement * pushPower, point = hit.Position
                    });
                    // If pushing something, reduce remaining force significantly
                    remaining *= pushDecay;
                }

                // Get angle between surface normal and remaining movement
                float angleBetween = math.length(math.dot(hit.SurfaceNormal, remaining)) / math.length(remaining);
                // Normalize angle between to be between 0 and 1
                angleBetween = math.min(KCCUtils.MaxAngleShoveRadians, math.abs(angleBetween));
                float normalizedAngle = angleBetween / KCCUtils.MaxAngleShoveRadians;
                // Create angle factor using 1 / (1 + normalizedAngle)
                float angleFactor = 1.0f / (1.0f + normalizedAngle);
                // If the character hit something
                // Reduce the momentum by the remaining movement that ocurred
                remaining *= (1 - hit.Fraction) * math.pow(angleFactor, anglePower);
                // Rotate the remaining remaining movement to be projected along the plane
                // of the surface hit (emulate pushing against the object)
                // A is our vector and B is normal of plane
                // A || B = B × (A×B / |B|) / |B|
                // From http://www.euclideanspace.com/maths/geometry/elements/plane/lineOnPlane/index.htm
                float3 planeNormal  = hit.SurfaceNormal;
                float  momentumLeft = math.length(remaining);
                remaining = math.cross(planeNormal, math.cross(remaining, planeNormal) / math.length(planeNormal)) / math.length(planeNormal);
                remaining = math.normalizesafe(remaining) * momentumLeft;
                // Track number of times the character has bounced
                bounces++;
            }
            return(from);
        }
예제 #15
0
 public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
 {
     _collisionWorld.CastCollider(_colliderInput, ref _allHits);
 }
예제 #16
0
 public unsafe void Execute(int index)
 {
     World.CastCollider(Inputs[index], out var hit);
     Results[index] = hit;
 }