// 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 override bool ParseBytesAndExecute(byte[] data) { if (data.Length < 4) { return false; } int len = Utilities.BytesToInt(Utilities.BytesPartial(data, 0, 4)); if (data.Length != 4 + 24 * 2 * len) { return false; } AABB[] boxes = new AABB[len]; for (int i = 0; i < len; i++) { boxes[i] = new AABB(); boxes[i].Min = Location.FromDoubleBytes(data, 4 + i * 24 * 2); boxes[i].Max = Location.FromDoubleBytes(data, 4 + i * 24 * 2 + 24); } TheClient.TheRegion.Highlights = boxes; return true; }
// TODO: EFficiency needed so much! public override void Execute(PlayerCommandEntry entry) { if (entry.InputArguments.Count < 1) { entry.Player.SendMessage(TextChannel.COMMAND_RESPONSE, "/blockship <convex/perfect> [scale]"); return; } BGETraceMode tm = BGETraceMode.CONVEX; if (entry.InputArguments[0].ToLowerFast() == "perfect") { tm = BGETraceMode.PERFECT; } double maxRad = 20; // TODO: Config! Location start = (entry.Player.GetPosition() + new Location(0, 0, -0.1)).GetBlockLocation(); List<KeyValuePair<Location, BlockInternal>> blocks = new List<KeyValuePair<Location, BlockInternal>>(); AABB extent = new AABB() { Min = start, Max = start }; if (!FloodFrom(entry.Player.TheRegion, start, blocks, maxRad, extent) || blocks.Count == 0) { entry.Player.SendMessage(TextChannel.COMMAND_RESPONSE, "Invalid flood-search!"); return; } Location size = extent.Max - extent.Min; int xwidth = (int)size.X + 1; int ywidth = (int)size.Y + 1; int zwidth = (int)size.Z + 1; int xsub = (int)extent.Min.X; int ysub = (int)extent.Min.Y; int zsub = (int)extent.Min.Z; BlockInternal[] blocksin = new BlockInternal[xwidth * ywidth * zwidth]; foreach (KeyValuePair<Location, BlockInternal> block in blocks) { entry.Player.TheRegion.SetBlockMaterial(block.Key, Material.AIR, 0, 0, 1, 0, true, true, true); blocksin[(int)(block.Key.Z - zsub) * ywidth * xwidth + (int)(block.Key.Y - ysub) * xwidth + (int)(block.Key.X - xsub)] = block.Value; } BlockGroupEntity bge = new BlockGroupEntity(extent.Min, tm, entry.Player.TheRegion, blocksin, xwidth, ywidth, zwidth); bge.scale = entry.InputArguments.Count < 2 ? Location.One : Location.FromString(entry.InputArguments[1]); entry.Player.TheRegion.SpawnEntity(bge); }
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 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; }
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; } }
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; } }