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; }
bool FloodFrom(Region tregion, Location start, List<KeyValuePair<Location, BlockInternal>> blocks, double maxRad, AABB extent) { Queue<Location> locsToGo = new Queue<Location>(); locsToGo.Enqueue(start); while (locsToGo.Count > 0) { Location c = locsToGo.Dequeue(); if ((c - start).LengthSquared() > maxRad * maxRad) { SysConsole.Output(OutputType.INFO, "Escaped radius!"); return false; } BlockInternal bi = tregion.GetBlockInternal(c); if ((Material)bi.BlockMaterial == Material.AIR) { continue; } if (!((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.EDITED)) { SysConsole.Output(OutputType.INFO, "Found natural block!"); return false; } if (((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.PROTECTED)) { continue; } blocks.Add(new KeyValuePair<Location, BlockInternal>(c, bi)); tregion.SetBlockMaterial(c, (Material)bi.BlockMaterial, bi.BlockData, bi.BlockPaint, (byte)(bi.BlockLocalData | (byte)BlockFlags.PROTECTED), bi.Damage, false, false); extent.Include(c); foreach (Location dir in FloodDirs) { locsToGo.Enqueue(c + dir); } } return true; }
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; }
public void renderGame() { Stopwatch totalt = new Stopwatch(); totalt.Start(); try { MainWorldView.ForwardVec = Player.ForwardVector(); // Frustum cf1 = null; if (CVars.g_firstperson.ValueB) { MainWorldView.CameraPos = PlayerEyePosition; } else { CollisionResult cr = TheRegion.Collision.RayTrace(PlayerEyePosition, PlayerEyePosition - MainWorldView.CalcForward() * Player.ViewBackMod(), IgnorePlayer); if (cr.Hit) { MainWorldView.CameraPos = cr.Position + cr.Normal * 0.05; } else { MainWorldView.CameraPos = cr.Position; } } if (CVars.u_showmap.ValueB && mapLastRendered + 1.0 < TheRegion.GlobalTickTimeLocal) // TODO: 1.0 -> custom { mapLastRendered = TheRegion.GlobalTickTimeLocal; AABB box = new AABB() { Min = Player.GetPosition(), Max = Player.GetPosition() }; foreach (Chunk ch in TheRegion.LoadedChunks.Values) { box.Include(ch.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE); box.Include(ch.WorldPosition.ToLocation() * Chunk.CHUNK_SIZE + new Location(Chunk.CHUNK_SIZE)); } Matrix4 ortho = Matrix4.CreateOrthographicOffCenter((float)box.Min.X, (float)box.Max.X, (float)box.Min.Y, (float)box.Max.Y, (float)box.Min.Z, (float)box.Max.Z); // Matrix4 oident = Matrix4.Identity; s_mapvox = s_mapvox.Bind(); GL.UniformMatrix4(View3D.MAT_LOC_VIEW, false, ref ortho); GL.Viewport(0, 0, 256, 256); // TODO: Customizable! GL.BindFramebuffer(FramebufferTarget.Framebuffer, map_fbo_main); GL.DrawBuffer(DrawBufferMode.ColorAttachment0); GL.ClearBuffer(ClearBuffer.Color, 0, new float[] { 0.0f, 1.0f, 0.0f, 1.0f }); GL.ClearBuffer(ClearBuffer.Depth, 0, new float[] { 1.0f }); GL.BindTexture(TextureTarget.Texture2DArray, TBlock.TextureID); foreach (Chunk chunk in TheRegion.LoadedChunks.Values) { chunk.Render(); } GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); GL.BindTexture(TextureTarget.Texture2DArray, 0); GL.DrawBuffer(DrawBufferMode.Back); } sortEntities(); Particles.Sort(); MainWorldView.Headmat = TheRegion.GetBlockMaterial(PlayerEyePosition); MainWorldView.SunLoc = GetSunLocation(); MainWorldView.Render(); ReverseEntitiesOrder(); } catch (Exception ex) { SysConsole.Output("Rendering (2D)", ex); } totalt.Stop(); TotalTime = (double)totalt.ElapsedMilliseconds / 1000f; if (TotalTime > TotalSpikeTime) { TotalSpikeTime = TotalTime; } }
// TODO: Optimize tracing! public Structure(Region tregion, Location startOfTrace, int maxrad) { startOfTrace = startOfTrace.GetBlockLocation(); Queue<Location> locs = new Queue<Location>(); HashSet<Location> found = new HashSet<Location>(); List<Location> resultLocs = new List<Location>(); locs.Enqueue(startOfTrace); int maxradsq = maxrad * maxrad; AABB box = new AABB() { Max = startOfTrace, Min = startOfTrace }; while (locs.Count > 0) { Location loc = locs.Dequeue(); if (found.Contains(loc)) { continue; } if (loc.DistanceSquared(startOfTrace) > maxradsq) { throw new Exception("Escaped radius!"); } BlockInternal bi = tregion.GetBlockInternal(loc); if ((Material)bi.BlockMaterial == Material.AIR) { continue; } if (!((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.EDITED)) { throw new Exception("Found natural block!"); } if (((BlockFlags)bi.BlockLocalData).HasFlag(BlockFlags.PROTECTED)) { throw new Exception("Found protected block!"); } found.Add(loc); resultLocs.Add(loc); box.Include(loc); foreach (Location dir in FloodDirs) { locs.Enqueue(loc + dir); } } Location ext = box.Max - box.Min; Size = new Vector3i((int)ext.X + 1, (int)ext.Y + 1, (int)ext.Z + 1); Origin = new Vector3i((int)Math.Floor(startOfTrace.X - box.Min.X), (int)Math.Floor(startOfTrace.Y - box.Min.Y), (int)Math.Floor(startOfTrace.Z - box.Min.Z)); Blocks = new BlockInternal[Size.X * Size.Y * Size.Z]; foreach (Location loc in resultLocs) { Blocks[BlockIndex((int)(loc.X - box.Min.X), (int)(loc.Y - box.Min.Y), (int)(loc.Z - box.Min.Z))] = tregion.GetBlockInternal(loc); } }
public void PreHandleSpawn() { model = TheClient.Models.GetModel(mod); model.LoadSkin(TheClient.Textures); int ignoreme; if (mode == ModelCollisionMode.PRECISE) { Shape = TheClient.Models.Handler.MeshToBepu(model.Original, out ignoreme); } else if (mode == ModelCollisionMode.CONVEXHULL) { Shape = TheClient.Models.Handler.MeshToBepuConvex(model.Original, out ignoreme); } else if (mode == ModelCollisionMode.AABB) { List<BEPUutilities.Vector3> vecs = TheClient.Models.Handler.GetCollisionVertices(model.Original); Location zero = new Location(vecs[0]); AABB abox = new AABB() { Min = zero, Max = zero }; for (int v = 1; v < vecs.Count; v++) { abox.Include(new Location(vecs[v])); } Location size = abox.Max - abox.Min; Location center = abox.Max - size / 2; Shape = new BoxShape((float)size.X * (float)scale.X, (float)size.Y * (float)scale.Y, (float)size.Z * (float)scale.Z); Offset = -center; } else { List<BEPUutilities.Vector3> vecs = TheClient.Models.Handler.GetCollisionVertices(model.Original); // Location zero = new Location(vecs[0].X, vecs[0].Y, vecs[0].Z); double distSq = 0; for (int v = 1; v < vecs.Count; v++) { if (vecs[v].LengthSquared() > distSq) { distSq = vecs[v].LengthSquared(); } } double size = Math.Sqrt(distSq); Offset = Location.Zero; Shape = new SphereShape((float)size * (float)scale.X); } }
public override void Spawn() { List<BEPUutilities.Vector3> vecs = TheClient.Models.Handler.GetCollisionVertices(model.Original); Location zero = new Location(vecs[0]); AABB abox = new AABB() { Min = zero, Max = zero }; for (int v = 1; v < vecs.Count; v++) { abox.Include(new Location(vecs[v])); } ModelMin = abox.Min.ToBVector(); ModelMax = abox.Max.ToBVector(); }
public override void SpawnBody() { Model smod = TheServer.Models.GetModel(model); if (smod == null) // TODO: smod should return a cube when all else fails? { // TODO: Make it safe to -> TheRegion.DespawnEntity(this); return; } Model3D smodel = smod.Original; if (smodel == null) // TODO: smodel should return a cube when all else fails? { // TODO: Make it safe to -> TheRegion.DespawnEntity(this); return; } if (mode == ModelCollisionMode.PRECISE) { Shape = TheServer.Models.handler.MeshToBepu(smodel, out modelVerts); // TODO: Scale! } if (mode == ModelCollisionMode.CONVEXHULL) { Shape = TheServer.Models.handler.MeshToBepuConvex(smodel, out modelVerts); // TODO: Scale! } else if (mode == ModelCollisionMode.AABB) { List<BEPUutilities.Vector3> vecs = TheServer.Models.handler.GetCollisionVertices(smodel); Location zero = new Location(vecs[0]); AABB abox = new AABB() { Min = zero, Max = zero }; for (int v = 1; v < vecs.Count; v++) { abox.Include(new Location(vecs[v])); } Location size = abox.Max - abox.Min; Location center = abox.Max - size / 2; offset = -center; Shape = new BoxShape((double)size.X * (double)scale.X, (double)size.Y * (double)scale.Y, (double)size.Z * (double)scale.Z); } else { List<BEPUutilities.Vector3> vecs = TheServer.Models.handler.GetCollisionVertices(smodel); double distSq = 0; for (int v = 1; v < vecs.Count; v++) { if (vecs[v].LengthSquared() > distSq) { distSq = vecs[v].LengthSquared(); } } double size = Math.Sqrt(distSq); offset = Location.Zero; Shape = new SphereShape((double)size * (double)scale.X); } base.SpawnBody(); if (mode == ModelCollisionMode.PRECISE) { offset = InternalOffset; } }