示例#1
0
        /// <summary>
        /// A convex-shaped ray-trace method for the special case of needing to handle Voxel collision types.
        /// </summary>
        /// <param name="shape">The shape of the convex ray source object.</param>
        /// <param name="start">The start of the ray.</param>
        /// <param name="dir">The normalized vector of the direction of the ray.</param>
        /// <param name="len">The length of the ray.</param>
        /// <param name="considerSolid">What materials are 'solid'.</param>
        /// <param name="filter">A function to identify what entities should be filtered out.</param>
        /// <param name="rayHit">Outputs the result of the ray trace.</param>
        /// <returns>Whether there was a collision.</returns>
        public bool SpecialCaseConvexTrace(ConvexShape shape, Location start, Location dir, double len, MaterialSolidity considerSolid, Func <BroadPhaseEntry, bool> filter, out RayCastResult rayHit)
        {
            RigidTransform rt = new RigidTransform(start.ToBVector(), BEPUutilities.Quaternion.Identity);

            BEPUutilities.Vector3 sweep = (dir * len).ToBVector();
            RayCastResult         best  = new RayCastResult(new RayHit()
            {
                T = len
            }, null);
            bool hA = false;

            if (considerSolid.HasFlag(MaterialSolidity.FULLSOLID))
            {
                if (PhysicsWorld.ConvexCast(shape, ref rt, ref sweep, filter, out RayCastResult rcr))
                {
                    best = rcr;
                    hA   = true;
                }
            }
            if (considerSolid == MaterialSolidity.FULLSOLID)
            {
                rayHit = best;
                return(hA);
            }
            sweep = dir.ToBVector();
            AABB box = new AABB()
            {
                Min = start,
                Max = start
            };

            box.Include(start + dir * len);
            foreach (KeyValuePair <Vector3i, Chunk> chunk in LoadedChunks)
            {
                if (chunk.Value == null || chunk.Value.FCO == null)
                {
                    continue;
                }
                if (!box.Intersects(new AABB()
                {
                    Min = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE,
                    Max = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE)
                }))
                {
                    continue;
                }
                if (chunk.Value.FCO.ConvexCast(shape, ref rt, ref sweep, len, considerSolid, out RayHit temp))
                {
                    hA = true;
                    if (temp.T < best.HitData.T)
                    {
                        best.HitData   = temp;
                        best.HitObject = chunk.Value.FCO;
                    }
                }
            }
            rayHit = best;
            return(hA);
        }
示例#2
0
        /// <summary>
        /// A ray-trace method for the special case of needing to handle Voxel collision types.
        /// </summary>
        /// <param name="start">The start of the ray.</param>
        /// <param name="dir">The normalized vector of the direction of the ray.</param>
        /// <param name="len">The length of the ray.</param>
        /// <param name="considerSolid">What materials are 'solid'.</param>
        /// <param name="filter">A function to identify what entities should be filtered out.</param>
        /// <param name="rayHit">Outputs the result of the ray trace.</param>
        /// <returns>Whether there was a collision.</returns>
        public bool SpecialCaseRayTrace(Location start, Location dir, double len, MaterialSolidity considerSolid, Func <BroadPhaseEntry, bool> filter, out RayCastResult rayHit)
        {
            Ray           ray  = new Ray(start.ToBVector(), dir.ToBVector());
            RayCastResult best = new RayCastResult(new RayHit()
            {
                T = len
            }, null);
            bool hA = false;

            if (considerSolid.HasFlag(MaterialSolidity.FULLSOLID))
            {
                if (PhysicsWorld.RayCast(ray, len, filter, out RayCastResult rcr))
                {
                    best = rcr;
                    hA   = true;
                }
            }
            if (considerSolid == MaterialSolidity.FULLSOLID)
            {
                rayHit = best;
                return(hA);
            }
            AABB box = new AABB()
            {
                Min = start,
                Max = start
            };

            box.Include(start + dir * len);
            foreach (Dictionary <Vector3i, Chunk> chkmap in LoadedChunks)
            {
                foreach (Chunk chunk in chkmap.Values)
                {
                    if (chunk == null || chunk.FCO == null)
                    {
                        continue;
                    }
                    if (!box.Intersects(new AABB()
                    {
                        Min = chunk.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE,
                        Max = chunk.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE, Chunk.CHUNK_SIZE)
                    }))
                    {
                        continue;
                    }
                    if (chunk.FCO.RayCast(ray, len, null, considerSolid, out RayHit temp))
                    {
                        hA = true;
                        if (temp.T < best.HitData.T)
                        {
                            best.HitData   = temp;
                            best.HitObject = chunk.FCO;
                        }
                    }
                }
            }
            rayHit = best;
            return(hA);
        }
示例#3
0
 public bool SpecialCaseRayTrace(Location start, Location dir, float len, MaterialSolidity considerSolid, Func<BroadPhaseEntry, bool> filter, out RayCastResult rayHit)
 {
     Ray ray = new Ray(start.ToBVector(), dir.ToBVector());
     RayCastResult best = new RayCastResult(new RayHit() { T = len }, null);
     bool hA = false;
     if (considerSolid.HasFlag(MaterialSolidity.FULLSOLID))
     {
         RayCastResult rcr;
         if (PhysicsWorld.RayCast(ray, len, filter, out rcr))
         {
             best = rcr;
             hA = true;
         }
     }
     AABB box = new AABB();
     box.Min = start;
     box.Max = start;
     box.Include(start + dir * len);
     foreach (KeyValuePair<Vector3i, Chunk> chunk in LoadedChunks)
     {
         if (chunk.Value == null || chunk.Value.FCO == null)
         {
             continue;
         }
         if (!box.Intersects(new AABB() { Min = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE, Max = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE) }))
         {
             continue;
         }
         RayHit temp;
         if (chunk.Value.FCO.RayCast(ray, len, null, considerSolid, out temp))
         {
             hA = true;
             //temp.T *= len;
             if (temp.T < best.HitData.T)
             {
                 best.HitData = temp;
                 best.HitObject = chunk.Value.FCO;
             }
         }
     }
     rayHit = best;
     return hA;
 }
示例#4
0
 public bool SpecialCaseConvexTrace(ConvexShape shape, Location start, Location dir, float len, MaterialSolidity considerSolid, Func<BroadPhaseEntry, bool> filter, out RayCastResult rayHit)
 {
     RigidTransform rt = new RigidTransform(start.ToBVector(), BEPUutilities.Quaternion.Identity);
     BEPUutilities.Vector3 sweep = (dir * len).ToBVector();
     RayCastResult best = new RayCastResult(new RayHit() { T = len }, null);
     bool hA = false;
     if (considerSolid.HasFlag(MaterialSolidity.FULLSOLID))
     {
         RayCastResult rcr;
         if (PhysicsWorld.ConvexCast(shape, ref rt, ref sweep, filter, out rcr))
         {
             best = rcr;
             hA = true;
         }
     }
     sweep = dir.ToBVector();
     AABB box = new AABB();
     box.Min = start;
     box.Max = start;
     box.Include(start + dir * len);
     foreach (KeyValuePair<Vector3i, Chunk> chunk in LoadedChunks)
     {
         if (chunk.Value == null || chunk.Value.FCO == null)
         {
             continue;
         }
         if (!box.Intersects(new AABB() { Min = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE, Max = chunk.Value.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE) }))
         {
             continue;
         }
         RayHit temp;
         if (chunk.Value.FCO.ConvexCast(shape, ref rt, ref sweep, len, considerSolid, out temp))
         {
             hA = true;
             //temp.T *= len;
             if (temp.T < best.HitData.T)
             {
                 best.HitData = temp;
                 best.HitObject = chunk.Value.FCO;
             }
         }
     }
     rayHit = best;
     return hA;
 }
示例#5
0
        public bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweepnorm, double slen, MaterialSolidity solidness, out RayHit hit)
        {
            RigidTransform rot = new RigidTransform(Vector3.Zero, startingTransform.Orientation);

            castShape.GetBoundingBox(ref rot, out BoundingBox bb);
            double  adv    = 0.1f;
            double  max    = slen + adv;
            bool    gotOne = false;
            RayHit  BestRH = default(RayHit);
            Vector3 sweep  = sweepnorm * slen;

            for (double f = 0; f < max; f += adv)
            {
                Vector3 c  = startingTransform.Position + sweepnorm * f;
                int     mx = (int)Math.Ceiling(c.X + bb.Max.X);
                for (int x = (int)Math.Floor(c.X + bb.Min.X); x <= mx; x++)
                {
                    if (x < 0 || x >= ChunkSize.X)
                    {
                        continue;
                    }
                    int my = (int)Math.Ceiling(c.Y + bb.Max.Y);
                    for (int y = (int)Math.Floor(c.Y + bb.Min.Y); y <= my; y++)
                    {
                        if (y < 0 || y >= ChunkSize.Y)
                        {
                            continue;
                        }
                        int mz = (int)Math.Ceiling(c.Z + bb.Max.Z);
                        for (int z = (int)Math.Floor(c.Z + bb.Min.Z); z <= mz; z++)
                        {
                            if (z < 0 || z >= ChunkSize.Z)
                            {
                                continue;
                            }
                            BlockInternal bi = Blocks[BlockIndex(x, y, z)];
                            if (solidness.HasFlag(((Material)bi.BlockMaterial).GetSolidity()))
                            {
                                EntityShape es = BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out Location offs, false);
                                if (es == null)
                                {
                                    continue;
                                }
                                Vector3          adj  = new Vector3(x + (double)offs.X, y + (double)offs.Y, z + (double)offs.Z);
                                EntityCollidable coll = es.GetCollidableInstance();
                                //coll.LocalPosition = adj;
                                RigidTransform rt = new RigidTransform(Vector3.Zero, Quaternion.Identity);
                                coll.LocalPosition  = Vector3.Zero;
                                coll.WorldTransform = rt;
                                coll.UpdateBoundingBoxForTransform(ref rt);
                                RigidTransform adjusted = new RigidTransform(startingTransform.Position - adj, startingTransform.Orientation);
                                bool           b        = coll.ConvexCast(castShape, ref adjusted, ref sweep, out RayHit rhit);
                                if (b && (!gotOne || rhit.T * slen < BestRH.T) && rhit.T >= 0)
                                {
                                    gotOne           = true;
                                    BestRH           = rhit;
                                    BestRH.Location += adj;
                                    BestRH.T        *= slen;           // TODO: ???
                                    BestRH.Normal    = -BestRH.Normal; // TODO: WHY?!
                                }
                            }
                        }
                    }
                }
                if (gotOne)
                {
                    hit = BestRH;
                    return(true);
                }
            }
            hit = new RayHit()
            {
                Location = startingTransform.Position + sweep, Normal = new Vector3(0, 0, 0), T = slen
            };
            return(false);
        }
示例#6
0
 public bool ConvexCast(ConvexShape castShape, ref RigidTransform startingTransform, ref Vector3 sweepnorm, double slen, MaterialSolidity solidness, out RayHit hit)
 {
     BoundingBox bb;
     RigidTransform rot = new RigidTransform(Vector3.Zero, startingTransform.Orientation);
     castShape.GetBoundingBox(ref rot, out bb);
     double adv = 0.1f;
     double max = slen + adv;
     bool gotOne = false;
     RayHit BestRH = default(RayHit);
     Vector3 sweep = sweepnorm * slen;
     for (double f = 0; f < max; f += adv)
     {
         Vector3 c = startingTransform.Position + sweepnorm * f;
         int mx = (int)Math.Ceiling(c.X + bb.Max.X);
         for (int x = (int)Math.Floor(c.X + bb.Min.X); x <= mx; x++)
         {
             if (x < 0 || x >= ChunkSize.X)
             {
                 continue;
             }
             int my = (int)Math.Ceiling(c.Y + bb.Max.Y);
             for (int y = (int)Math.Floor(c.Y + bb.Min.Y); y <= my; y++)
             {
                 if (y < 0 || y >= ChunkSize.Y)
                 {
                     continue;
                 }
                 int mz = (int)Math.Ceiling(c.Z + bb.Max.Z);
                 for (int z = (int)Math.Floor(c.Z + bb.Min.Z); z <= mz; z++)
                 {
                     if (z < 0 || z >= ChunkSize.Z)
                     {
                         continue;
                     }
                     BlockInternal bi = Blocks[BlockIndex(x, y, z)];
                     if (solidness.HasFlag(((Material)bi.BlockMaterial).GetSolidity()))
                     {
                         Location offs;
                         EntityShape es = BlockShapeRegistry.BSD[bi.BlockData].GetShape(bi.Damage, out offs, false);
                         if (es == null)
                         {
                             continue;
                         }
                         Vector3 adj = new Vector3(x + (double)offs.X, y + (double)offs.Y, z + (double)offs.Z);
                         EntityCollidable coll = es.GetCollidableInstance();
                         //coll.LocalPosition = adj;
                         RigidTransform rt = new RigidTransform(Vector3.Zero, Quaternion.Identity);
                         coll.LocalPosition = Vector3.Zero;
                         coll.WorldTransform = rt;
                         coll.UpdateBoundingBoxForTransform(ref rt);
                         RayHit rhit;
                         RigidTransform adjusted = new RigidTransform(startingTransform.Position - adj, startingTransform.Orientation);
                         bool b = coll.ConvexCast(castShape, ref adjusted, ref sweep, out rhit);
                         if (b && (!gotOne || rhit.T * slen < BestRH.T) && rhit.T >= 0)
                         {
                             gotOne = true;
                             BestRH = rhit;
                             BestRH.Location += adj;
                             BestRH.T *= slen; // TODO: ???
                             BestRH.Normal = -BestRH.Normal; // TODO: WHY?!
                         }
                     }
                 }
             }
         }
         if (gotOne)
         {
             hit = BestRH;
             return true;
         }
     }
     hit = new RayHit() { Location = startingTransform.Position + sweep, Normal = new Vector3(0, 0, 0), T = slen };
     return false;
 }