public RaycastChunkHit Raycast(Chunk chunk, Ray ray) { //World.GlobalToLocal(ray.Origin, out Vector2I minCPos, out Vector3I minBPos); //World.GlobalToLocal(ray.Origin + ray.Direction * ray.Length, out Vector2I maxCPos, out Vector3I maxBPos); Vector3I minRelDir = World.RelativePositionToChunk(ray.Origin, chunk.Coordinates); Vector3I maxRelDir = World.RelativePositionToChunk(ray.Origin + ray.Direction * ray.Length, chunk.Coordinates); int minX = Math.Min(minRelDir.X, maxRelDir.X); int maxX = Math.Max(minRelDir.X, maxRelDir.X); int minY = Math.Min(minRelDir.Y, maxRelDir.Y); int maxY = Math.Max(minRelDir.Y, maxRelDir.Y); int minZ = Math.Min(minRelDir.Z, maxRelDir.Z); int maxZ = Math.Max(minRelDir.Z, maxRelDir.Z); RayBoxCollisionProvider provider = new RayBoxCollisionProvider(); List <RaycastChunkHit> hits = new List <RaycastChunkHit>(); for (int z = minZ; z <= maxZ; z++) { if (z < 0 || z > Chunk.Depth - 1) { continue; } for (int y = minY; y <= maxY; y++) { if (y < 0 || y > Chunk.Height - 1) { continue; } for (int x = minX; x <= maxX; x++) { if (x < 0 || x > Chunk.Width - 1) { continue; } Block b = chunk[x, y, z]; if (b.Identifier != "winecrash:air") { Vector3D blockExtents = new Vector3D(0.5D); Vector3D blockCenter = new Vector3D(x + chunk.Coordinates.X * Chunk.Width, y, z + chunk.Coordinates.Y * Chunk.Depth) + blockExtents; FreeBoxCollider collider = new FreeBoxCollider() { Center = blockCenter, Extents = blockExtents }; Hit h = provider.Collide(ray, collider); collider.Delete(); if (h.HasHit) { hits.Add(new RaycastChunkHit(h.Position, h.Normal, h.Time * ray.Length, b, chunk, new Vector3I(x, y, z), true)); } } } } } if (hits.Count != 0) { return(hits.OrderBy(h => h.Distance).First()); } return(new RaycastChunkHit()); }
public Sweep SweepCollide(Chunk c, BoxCollider b) { //force = Vector3D.Zero; //translation = Vector3D.Zero; RigidBody rb = b.WObject.GetModule <RigidBody>(); Vector3D bc = b.Center; Vector3D be = b.Extents * 4; Vector3D cc = c.WObject.Position + Vector3D.Up * Chunk.Height / 2.0D + Vector3D.Right * Chunk.Width / 2.0D + Vector3D.Forward * Chunk.Depth / 2.0D; Vector3D ce = Vector3D.One * new Vector3D(Chunk.Width, Chunk.Height, Chunk.Depth) / 2.0D; // if outside of chunk, no collision. if ( //Y cc.Y - ce.Y > bc.Y + be.Y || // if too low cc.Y + ce.Y < bc.Y - be.Y || // if too high //X cc.X - ce.X > bc.X + be.X || // if too much left cc.X + ce.X < bc.X - be.X || // if too much right //Z cc.Z - ce.Z > bc.Z + be.Z || // if too much behind cc.Z + ce.Z < bc.Z - be.Z // if too much forward ) { return(new Sweep()); } else // the box collider is within the chunk { // max coords Vector3D max = bc + be; Vector3D min = bc - be; Vector3D cmax = new Vector3D( WMath.Clamp(max.X, c.Coordinates.X * Chunk.Width, c.Coordinates.X * Chunk.Width + (Chunk.Width - 1)), WMath.Clamp(max.Y, 0, 255), WMath.Clamp(max.Z, c.Coordinates.Y * Chunk.Depth, c.Coordinates.Y * Chunk.Depth + (Chunk.Depth - 1)) ); Vector3D cmin = new Vector3D( WMath.Clamp(min.X, c.Coordinates.X * Chunk.Width, c.Coordinates.X * Chunk.Width + (Chunk.Width - 1)), WMath.Clamp(min.Y, 0, 255), WMath.Clamp(min.Z, c.Coordinates.Y * Chunk.Depth, c.Coordinates.Y * Chunk.Depth + (Chunk.Depth - 1)) ); World.GlobalToLocal(cmax, out _, out Vector3I maxBpos); World.GlobalToLocal(cmin, out _, out Vector3I minBpos); List <AABBCollider> colliders = new List <AABBCollider>(); for (int z = minBpos.Z; z <= maxBpos.Z; z++) { for (int y = minBpos.Y; y <= maxBpos.Y; y++) { for (int x = minBpos.X; x <= maxBpos.X; x++) { if (c[x, y, z].Collides) { Vector3D blockExtents = new Vector3D(0.5D); Vector3D blockCenter = new Vector3D(x + c.Coordinates.X * Chunk.Width, y, z + c.Coordinates.Y * Chunk.Depth) + blockExtents; FreeBoxCollider collider = new FreeBoxCollider() { Center = blockCenter, Extents = blockExtents }; colliders.Add(collider); } } } } Sweep resultingSweep = new BoxBoxCollisionProvider().SweepCollideInto(b, rb.Velocity * Time.PhysicsDelta, colliders.ToArray()); for (int i = 0; i < colliders.Count; i++) { colliders[i].Delete(); } colliders.Clear(); colliders = null; return(resultingSweep); } }