/// <summary> /// Directions of faces which are revealed due to ViewGrid /// </summary> Direction GetVoxelSliceDirections(IntVector3 p, ref IntGrid3 viewGrid) { Direction d = 0; // Note: we never draw the bottommost layer in the map, so we don't check for Z1 if (p.Z == viewGrid.Z2) { d |= Direction.Up; } if (p.X == viewGrid.X1) { d |= Direction.West; } if (p.X == viewGrid.X2) { d |= Direction.East; } if (p.Y == viewGrid.Y1) { d |= Direction.North; } if (p.Y == viewGrid.Y2) { d |= Direction.South; } return(d); }
/// <summary> /// Directions of faces which are revealed due to ViewGrid /// </summary> Direction GetGridSliceDirections(ref IntGrid3 grid, ref IntGrid3 viewGrid) { Direction d = 0; // Note: we never draw the bottommost layer in the map, so we don't check for Z1 if (grid.Z2 == viewGrid.Z2) { d |= Direction.Up; } if (grid.X1 == viewGrid.X1) { d |= Direction.West; } if (grid.X2 == viewGrid.X2) { d |= Direction.East; } if (grid.Y1 == viewGrid.Y1) { d |= Direction.North; } if (grid.Y2 == viewGrid.Y2) { d |= Direction.South; } return(d); }
public void AddArea(IntGrid3 area, DesignationType type) { int origCount = m_map.Count; var locations = area.Range().Where(this.Environment.Contains); foreach (var p in locations) { if (GetTileValid(p, type) == false) continue; DesignationData oldData; if (m_map.TryGetValue(p, out oldData)) { if (oldData.Type == type) continue; RemoveJob(p); } var data = new DesignationData(type); data.Reachable = GetTileReachable(p, type); m_map[p] = data; this.Environment.OnTileExtraChanged(p); } if (origCount == 0 && m_map.Count > 0) { this.Environment.MapTileTerrainChanged += OnEnvironmentMapTileTerrainChanged; this.Environment.World.TickStarting += OnTickStartEvent; } }
public static void Calculate3(IntVector3 viewerLocation, int visionRange, VisionMap visibilityMap, IntSize3 mapSize, Func<IntVector3, bool> blockerDelegate) { visibilityMap.Clear(); if (blockerDelegate(viewerLocation) == true) return; var g = new IntGrid3(new IntVector3(), mapSize); g = g.Offset(-viewerLocation.X, -viewerLocation.Y, -viewerLocation.Z); var vr = new IntVector3(visionRange, visionRange, visionRange); g = g.Intersect(new IntGrid3(vr, -vr)); int visionRangeSquared = (visionRange + 1) * (visionRange + 1); // +1 to get a bit bigger view area foreach (var dst in g.Range()) { if (dst.LengthSquared > visionRangeSquared) continue; bool vis = FindLos3(viewerLocation, dst, blockerDelegate); visibilityMap[dst] = vis; // XXX Cheat a bit so that the floor will be visible if (vis && dst.Z == 0 && viewerLocation.Z > 1) { visibilityMap[dst.SetZ(dst.Z - 1)] = true; } } }
void UpdateNearList() { m_nearList.Clear(); var eye = m_camera.Position; var frustum = m_camera.Frustum; var farCorner = GetFrustumFarthestCorner(ref frustum); float camRadius = (farCorner - eye).Length(); float chunkRadius = (float)Math.Sqrt(3) * Chunk.CHUNK_SIZE / 2; var viewGrid = m_viewGridProvider.ViewGrid; // XXX grid can be reduced to be inside camradius, but we need to somehow free the chunks that go outside near list //var grid = new IntGrid3(viewGrid.Corner1 / Chunk.CHUNK_SIZE, (viewGrid.Corner2 + Chunk.CHUNK_SIZE - 1) / Chunk.CHUNK_SIZE); var grid = this.Size; foreach (var cp in grid.Range()) { var chunk = GetChunk(cp); IntVector3 chunkOffset = cp * Chunk.CHUNK_SIZE; var chunkGrid = new IntGrid3(chunkOffset, Chunk.ChunkSize); var containment = viewGrid.ContainsExclusive(ref chunkGrid); if (containment == Containment.Disjoint) { // the chunk is outside the view area if (chunk != null) { FreeChunk(chunk); } continue; } var chunkCenter = chunkOffset.ToVector3() + new Vector3(Chunk.CHUNK_SIZE / 2); if (Vector3.Distance(eye, chunkCenter) - chunkRadius > camRadius) { if (chunk != null) { FreeChunk(chunk); } continue; } if (chunk == null) { chunk = CreateChunk(cp); } m_nearList.Add(chunk); } m_forceDrawListUpdate = true; }
static void SetArea(EnvironmentObject env, IntGrid3 area, TileData data) { foreach (var p in area.Range()) { env.SetTileData(p, data); } }
public FellTreeParallelJob(IEnvironmentObject env, IntGrid3 area) : base(null) { m_environment = env; m_area = area; AddNewJobs(); }
IEnumerable <IntVector3> GetVisibleLocationsSimpleFOV() { var g = new IntGrid3(this.Location - this.VisionRange, this.Location + this.VisionRange); g = g.Intersect(new IntGrid3(this.Environment.Size)); return(g.Range()); }
public void RemoveArea(IntGrid3 area) { var removes = m_map.Where(kvp => area.Contains(kvp.Key)).ToArray(); foreach (var kvp in removes) { RemoveDesignation(kvp.Key); } }
public Map(int width, int height, int depth) { this.Grid = new AStarMapTile[depth, height, width]; this.Bounds = new IntGrid3(0, 0, 0, width, height, depth); for (int y = 0; y < 350; ++y) { SetBlocked(new IntVector3(5, y, 0), true); } for (int y = 2; y < 22; ++y) { SetBlocked(new IntVector3(14, y, 0), true); } for (int y = 6; y < 11; ++y) { SetWeight(new IntVector3(10, y, 0), 40); } for (int y = 6; y < 18; ++y) { SetBlocked(new IntVector3(3, y, 1), true); } for (int y = 6; y < 11; ++y) { SetWeight(new IntVector3(5, y, 1), 40); } SetStairs(new IntVector3(10, 10, 0), Stairs.Up); SetStairs(new IntVector3(10, 10, 1), Stairs.Down); SetStairs(new IntVector3(15, 12, 0), Stairs.Up); SetStairs(new IntVector3(15, 12, 1), Stairs.Down); var r = new Random(4); var bounds = new IntGrid2Z(16, 0, 30, 30, 0); foreach (var p in bounds.Range()) { var v = r.Next(100); if (v < 30) { SetBlocked(p, true); } else if (v < 60) { SetWeight(p, v); } } }
void UpdateVertexBuffer() { if (m_env == null) { RemoveAndDispose(ref m_vertexBuffer); m_vertexList = null; return; } var envContents = m_env.Contents; if (m_vertexList != null && envContents.Count > m_vertexList.Count) { m_vertexList = null; } if (m_vertexList == null) { m_vertexList = new VertexList <SceneryVertex>(envContents.Count * 2); } IntGrid3 viewGrid = m_viewGridProvider.ViewGrid; m_vertexList.Clear(); foreach (var ob in envContents.OfType <ConcreteObject>()) { if (viewGrid.Contains(ob.Location) == false) { continue; } var c = ob.Color; if (c == GameColor.None) { c = ob.Material.Color; } m_vertexList.Add(new SceneryVertex(ob.Location.ToVector3(), ToColor(c), (uint)ob.SymbolID)); } if (m_vertexList.Count > 0) { if (m_vertexBuffer == null || m_vertexBuffer.ElementCount < m_vertexList.Count) { RemoveAndDispose(ref m_vertexBuffer); m_vertexBuffer = ToDispose(SharpDX.Toolkit.Graphics.Buffer.Vertex.New <SceneryVertex>(this.GraphicsDevice, m_vertexList.Count)); } m_vertexBuffer.SetData(m_vertexList.Data, 0, m_vertexList.Count); } }
public Rect MapCubeToRenderPointRect(IntGrid3 grid) { var p1 = MapLocationToScreenTile(grid.Corner1); var p2 = MapLocationToScreenTile(grid.Corner2); var r = new Rect(p1, p2); r.Inflate(0.5, 0.5); p1 = ScreenToRenderPoint(r.TopLeft); p2 = ScreenToRenderPoint(r.BottomRight); return new Rect(p1, p2); }
public MapSelection(IntGrid3 box) : this() { if (box.Columns == 0 || box.Rows == 0 || box.Depth == 0) { this.IsSelectionValid = false; } else { this.SelectionStart = box.Corner1; this.SelectionEnd = box.Corner2; this.IsSelectionValid = true; } }
public Rect MapCubeToRenderPointRect(IntGrid3 grid) { var p1 = MapLocationToScreenTile(grid.Corner1); var p2 = MapLocationToScreenTile(grid.Corner2); var r = new Rect(p1, p2); r.Inflate(0.5, 0.5); p1 = ScreenToRenderPoint(r.TopLeft); p2 = ScreenToRenderPoint(r.BottomRight); return(new Rect(p1, p2)); }
void SendMapTiles(IPlayer player) { var visionTracker = player.GetVisionTracker(this); int w = this.Width; int h = this.Height; int d = this.Depth; var size = new IntSize3(w, h, 1); var arr = new ulong[w * h]; for (int z = 0; z < d; ++z) { var bounds = new IntGrid3(new IntVector3(0, 0, z), size); Parallel.For(0, h, y => { for (int x = 0; x < w; ++x) { var p = new IntVector3(x, y, z); ulong v; if (!visionTracker.Sees(p)) { v = 0; } else { v = GetTileData(p).Raw; } arr[y * w + x] = v; } }); var msg = new Messages.MapDataTerrainsMessage() { Environment = this.ObjectID, Bounds = bounds, TerrainData = arr, }; player.Send(msg); //Trace.TraceError("Sent {0}", z); } }
public void SetTarget(EnvironmentObject env, IntGrid3 box) { if (env == m_environment && m_box == box) { return; } if (env != m_environment) { if (m_environment != null) { m_environment.MapTileTerrainChanged -= OnMapTerrainChanged; m_environment.MapTileObjectChanged -= OnMapObjectChanged; } m_environment = env; if (m_environment != null) { m_environment.MapTileTerrainChanged += OnMapTerrainChanged; m_environment.MapTileObjectChanged += OnMapObjectChanged; } Notify("Environment"); NotifyTileObjectChanges(); } if (box != m_box) { var old = m_box; m_box = box; if (m_box.IsNull || m_environment == null) { m_adjustedBox = m_box; } else { m_adjustedBox = m_box.Intersect(new IntGrid3(m_environment.Size)); } Notify("Box"); NotifyTileObjectChanges(old, m_box); } NotifyTileTerrainChanges(); Notify("IsNotEmpty"); }
public void SetTileDataRange(ulong[] tileData, IntGrid3 bounds) { int i = 0; for (int z = bounds.Z; z < bounds.Z + bounds.Depth; ++z) { for (int y = bounds.Y; y < bounds.Y + bounds.Rows; ++y) { for (int x = bounds.X; x < bounds.X + bounds.Columns; ++x) { ulong v = tileData[i++]; m_grid[z, y, x].Raw = v; } } } }
public void SetTerrains(IntGrid3 bounds, ulong[] tileData) { this.Version += 1; m_tileGrid.Grow(bounds.Corner2); //Trace.TraceError("Recv {0}", bounds.Z); m_tileGrid.SetTileDataRange(tileData, bounds); if (this.MapTileTerrainChanged != null) { foreach (var p in bounds.Range()) { MapTileTerrainChanged(p); } } }
static void CreateOreSphere(TerrainData terrain, Random random, IntVector3 center, int r, MaterialID oreMaterialID, double probIn, double probOut) { // adjust r, so that r == 1 gives sphere of one tile r -= 1; // XXX split the sphere into 8 parts, and mirror var bb = new IntGrid3(center.X - r, center.Y - r, center.Z - r, r * 2 + 1, r * 2 + 1, r * 2 + 1); var rs = MyMath.Square(r); foreach (var p in bb.Range()) { var y = p.Y; var x = p.X; var z = p.Z; var v = MyMath.Square(x - center.X) + MyMath.Square(y - center.Y) + MyMath.Square(z - center.Z); if (rs >= v) { var rr = Math.Sqrt(v); double rel; if (r == 0) { rel = 1; } else { rel = 1 - rr / r; } var prob = (probIn - probOut) * rel + probOut; if (random.NextDouble() <= prob) { CreateOre(terrain, p, oreMaterialID); } } } }
void HandleVoxel(IntVector3 p, ref Voxel vox, ref IntGrid3 viewGrid, Direction visibleChunkFaces, VertexList <TerrainVertex> vertexList) { // Faces that are visible due to viewgrid Direction sliceFaces = GetVoxelSliceDirections(p, ref viewGrid) & visibleChunkFaces; // Faces that are drawn (if there's something to draw) Direction visibleFaces = (vox.VisibleFaces | sliceFaces) & visibleChunkFaces; if (visibleFaces == 0) { return; } FaceTexture baseTexture, topTexture; GetTextures(p, ref vox, out baseTexture, out topTexture, sliceFaces); CreateCube(p, visibleFaces, ref baseTexture, ref topTexture, vertexList, sliceFaces); }
public void GenerateVertices(ref IntGrid3 viewGrid, IntVector3 cameraChunkPos, VertexList <TerrainVertex> terrainVertexList, VertexList <SceneryVertex> sceneryVertexList) { terrainVertexList.Clear(); sceneryVertexList.Clear(); var diff = cameraChunkPos - this.ChunkPosition; Direction visibleChunkFaces = 0; if (diff.X >= 0) { visibleChunkFaces |= Direction.PositiveX; } if (diff.X <= 0) { visibleChunkFaces |= Direction.NegativeX; } if (diff.Y >= 0) { visibleChunkFaces |= Direction.PositiveY; } if (diff.Y <= 0) { visibleChunkFaces |= Direction.NegativeY; } if (diff.Z >= 0) { visibleChunkFaces |= Direction.PositiveZ; } if (diff.Z <= 0) { visibleChunkFaces |= Direction.NegativeZ; } GenerateVertices(ref viewGrid, visibleChunkFaces, terrainVertexList, sceneryVertexList); this.VertexCount = terrainVertexList.Count; this.SceneryVertexCount = sceneryVertexList.Count; }
public void AddArea(IntGrid3 area, DesignationType type) { int origCount = m_map.Count; var locations = area.Range().Where(this.Environment.Contains); foreach (var p in locations) { if (GetTileValid(p, type) == false) { continue; } DesignationData oldData; if (m_map.TryGetValue(p, out oldData)) { if (oldData.Type == type) { continue; } RemoveJob(p); } var data = new DesignationData(type); data.ReachableSimple = GetTileReachableSimple(p, type); m_map[p] = data; this.Environment.OnTileExtraChanged(p); } if (origCount == 0 && m_map.Count > 0) { this.Environment.MapTileTerrainChanged += OnEnvironmentMapTileTerrainChanged; this.Environment.World.TickStarted += OnTickStartEvent; } }
void NotifyTileObjectChanges(IntGrid3 oldGrid, IntGrid3 newGrid) { if (m_environment == null) { m_objects.Clear(); return; } var rm = oldGrid.Range().Except(newGrid.Range()) .SelectMany(p => m_environment.GetContents(p)); foreach (var ob in rm) { m_objects.Remove(ob); } var add = newGrid.Range().Except(oldGrid.Range()) .SelectMany(p => m_environment.GetContents(p)); foreach (var ob in add) { m_objects.Add(ob); } }
public static bool PickVoxel(EnvironmentObject env, GameSurfaceView view, IntVector2 screenPos, IntGrid3 cropGrid, MapControlPickMode pickMode, out IntVector3 pos, out Direction face) { var camera = view.Camera; var ray = Ray.GetPickRay(screenPos.X, screenPos.Y, view.ViewPort, view.Camera.View * view.Camera.Projection); IntVector3 outpos = new IntVector3(); Direction outdir = Direction.None; var corner = cropGrid.Corner2; var size = new IntSize3(corner.X + 1, corner.Y + 1, corner.Z + 1); IntVector3 prevoutpos = new IntVector3(); Direction prevoutdir = Direction.None; VoxelRayCast.RunRayCast(size, ray.Position, ray.Direction, view.Camera.FarZ, (x, y, z, dir) => { var p = new IntVector3(x, y, z); if (cropGrid.Contains(p) == false) { return(false); } var td = env.GetTileData(p); switch (pickMode) { case MapControlPickMode.Underground: if (!td.IsUndefined && !td.IsWall) { return(false); } outpos = p; outdir = dir; return(true); case MapControlPickMode.AboveGround: if (!td.IsUndefined && !td.IsWall) { prevoutpos = p; prevoutdir = dir; return(false); } if (prevoutpos.IsNull) { outpos = p; outdir = dir; } else { outpos = prevoutpos; outdir = prevoutdir; } return(true); case MapControlPickMode.Constant: if (p.Z > cropGrid.Z2) { return(false); } outpos = p; outdir = dir; return(true); default: throw new NotImplementedException(); } }); pos = outpos; face = outdir; return(face != Direction.None); }
void GenerateVertices(ref IntGrid3 viewGrid, Direction visibleChunkFaces, VertexList<TerrainVertex> terrainVertexList, VertexList<SceneryVertex> sceneryVertexList) { IntGrid3 chunkGrid = viewGrid.Intersect(new IntGrid3(this.ChunkOffset, Chunk.ChunkSize)); // is the chunk inside frustum, but outside the viewgrid? if (chunkGrid.IsNull) return; if (m_scanned == false) ScanForAllEmptyOrUndefined(); if (this.IsAllEmpty) return; if (this.IsAllUndefined) { CreateUndefinedChunk(ref viewGrid, ref chunkGrid, terrainVertexList, visibleChunkFaces); return; } if (m_voxelMap == null) FillVoxelMap(); // Draw from up to down to avoid overdraw for (int z = chunkGrid.Z2; z >= chunkGrid.Z1; --z) { for (int y = chunkGrid.Y1; y <= chunkGrid.Y2; ++y) { for (int x = chunkGrid.X1; x <= chunkGrid.X2; ++x) { var p = new IntVector3(x, y, z); var td = m_map.GetTileData(p); if (td.WaterLevel == 0) { if (td.IsEmpty) continue; } var pos = p - this.ChunkOffset; if (td.HasTree) { // Add tree as scenery vertex HandleTree(sceneryVertexList, td, ref pos); continue; } if (td.IsGreen) // XXX continue; var vox = m_voxelMap.Grid[pos.Z, pos.Y, pos.X]; HandleVoxel(p, ref vox, ref viewGrid, visibleChunkFaces, terrainVertexList); } } } }
public void RemoveArea(IntGrid3 area) { var removes = m_map.Where(kvp => area.Contains(kvp.Key)).ToArray(); foreach (var kvp in removes) RemoveDesignation(kvp.Key); }
public void SetContext(EnvironmentObject env, IntGrid3 area) { this.Environment = env; this.Area = area; }
void ProcessRebuildList(IntVector3 cameraChunkPos) { if (m_rebuildList.Count == 0) { return; } var task = Task.Run(() => { IntGrid3 viewGrid = m_viewGridProvider.ViewGrid; Parallel.ForEach(m_rebuildList, chunk => { var cacheItem = m_vertexCacheStack.Take(); chunk.GenerateVertices(ref viewGrid, cameraChunkPos, cacheItem.TerrainVertexList, cacheItem.SceneryVertexList); if (chunk.VertexCount == 0 && chunk.SceneryVertexCount == 0) { // nothing more to do, mark as valid and add back to stack chunk.IsValid = true; m_vertexCacheStack.Return(cacheItem); } else { cacheItem.Chunk = chunk; m_vertexCacheQueue.Add(cacheItem); } }); m_vertexCacheQueue.Add(null); }); while (true) { var cacheItem = m_vertexCacheQueue.Take(); if (cacheItem == null) { break; } var chunk = cacheItem.Chunk; chunk.UpdateVertexBuffer(m_scene.GraphicsDevice, cacheItem.TerrainVertexList); chunk.UpdateSceneryVertexBuffer(m_scene.GraphicsDevice, cacheItem.SceneryVertexList); chunk.IsValid = true; cacheItem.Chunk = null; m_vertexCacheStack.Return(cacheItem); } task.Wait(); task.Dispose(); System.Diagnostics.Trace.Assert(m_vertexCacheStack.Count == VERTEX_CACHE_COUNT); System.Diagnostics.Trace.Assert(m_vertexCacheQueue.Count == 0); this.ChunkRecalcs = m_rebuildList.Count; m_rebuildList.Clear(); }
public HaulToAreaAssignment(IJobObserver parent, IEnvironmentObject environment, IntGrid3 destination, DirectionSet positioning, IItemObject hauledItem) : base(parent, environment, positioning, hauledItem) { m_dest = destination; }
IEnumerable<IntVector3> GetVisibleLocationsSimpleFOV() { var g = new IntGrid3(this.Location - this.VisionRange, this.Location + this.VisionRange); g = g.Intersect(new IntGrid3(this.Environment.Size)); return g.Range(); }
void CreateUndefinedChunk(ref IntGrid3 viewGrid, ref IntGrid3 chunkGrid, VertexList <TerrainVertex> vertexList, Direction visibleChunkFaces) { // Faces that are visible due to viewgrid Direction sliceFaces = GetGridSliceDirections(ref chunkGrid, ref viewGrid) & visibleChunkFaces; // Only faces revealed by viewgrid are visible Direction visibleFaces = sliceFaces; if (visibleFaces == 0) { return; } int sides = (int)visibleFaces; FaceTexture tex = Chunk.UndefinedFaceTexture; const int occlusion = 0; var offset = chunkGrid.Corner1 - this.ChunkOffset; var size = new IntVector3(chunkGrid.Size.Width, chunkGrid.Size.Height, chunkGrid.Size.Depth); // All faces are revealed by viewgrid byte sliceHack = (byte)1; if (Chunk.UseBigUnknownChunk) { /* Note: Using chunk sized quads causes t-junction problems */ for (int side = 0; side < 6 && sides != 0; ++side, sides >>= 1) { if ((sides & 1) == 0) { continue; } var vertices = s_cubeFaceInfo[side].Vertices; IntVector3 v0 = vertices[0] * size + offset; IntVector3 v1 = vertices[1] * size + offset; IntVector3 v2 = vertices[2] * size + offset; IntVector3 v3 = vertices[3] * size + offset; var vd = new TerrainVertex(v0, v1, v2, v3, occlusion, occlusion, occlusion, occlusion, tex, sliceHack); vertexList.Add(vd); } } else { for (int side = 0; side < 6 && sides != 0; ++side, sides >>= 1) { if ((sides & 1) == 0) { continue; } int d0 = side / 2; int d1 = (d0 + 1) % 3; int d2 = (d0 + 2) % 3; bool posFace = (side & 1) == 1; var vertices = s_cubeFaceInfo[side].Vertices; IntVector3 v0 = vertices[0] + offset; IntVector3 v1 = vertices[1] + offset; IntVector3 v2 = vertices[2] + offset; IntVector3 v3 = vertices[3] + offset; var vec1 = new IntVector3(); vec1[d1] = 1; var vec2 = new IntVector3(); vec2[d2] = 1; for (int v = 0; v < size[d1]; ++v) { for (int u = 0; u < size[d2]; ++u) { var off = vec1 * v + vec2 * u; if (posFace) { off[d0] = size[d0] - 1; } var vd = new TerrainVertex(v0 + off, v1 + off, v2 + off, v3 + off, occlusion, occlusion, occlusion, occlusion, tex, sliceHack); vertexList.Add(vd); } } } } }
public MoveToAreaAssignment(IJobObserver parent, IEnvironmentObject environment, IntGrid3 destination, DirectionSet positioning) : base(parent, environment, positioning) { m_dest = destination; }
void HandleVoxel(IntVector3 p, ref Voxel vox, ref IntGrid3 viewGrid, Direction visibleChunkFaces, VertexList<TerrainVertex> vertexList) { // Faces that are visible due to viewgrid Direction sliceFaces = GetVoxelSliceDirections(p, ref viewGrid) & visibleChunkFaces; // Faces that are drawn (if there's something to draw) Direction visibleFaces = (vox.VisibleFaces | sliceFaces) & visibleChunkFaces; if (visibleFaces == 0) return; FaceTexture baseTexture, topTexture; GetTextures(p, ref vox, out baseTexture, out topTexture, sliceFaces); CreateCube(p, visibleFaces, ref baseTexture, ref topTexture, vertexList, sliceFaces); }
void UpdateNearList() { m_nearList.Clear(); var eye = m_camera.Position; var frustum = m_camera.Frustum; var farCorner = GetFrustumFarthestCorner(ref frustum); float camRadius = (farCorner - eye).Length(); float chunkRadius = (float)Math.Sqrt(3) * Chunk.CHUNK_SIZE / 2; var viewGrid = m_viewGridProvider.ViewGrid; // XXX grid can be reduced to be inside camradius, but we need to somehow free the chunks that go outside near list //var grid = new IntGrid3(viewGrid.Corner1 / Chunk.CHUNK_SIZE, (viewGrid.Corner2 + Chunk.CHUNK_SIZE - 1) / Chunk.CHUNK_SIZE); var grid = this.Size; foreach (var cp in grid.Range()) { var chunk = GetChunk(cp); IntVector3 chunkOffset = cp * Chunk.CHUNK_SIZE; var chunkGrid = new IntGrid3(chunkOffset, Chunk.ChunkSize); var containment = viewGrid.ContainsExclusive(ref chunkGrid); if (containment == Containment.Disjoint) { // the chunk is outside the view area if (chunk != null) FreeChunk(chunk); continue; } var chunkCenter = chunkOffset.ToVector3() + new Vector3(Chunk.CHUNK_SIZE / 2); if (Vector3.Distance(eye, chunkCenter) - chunkRadius > camRadius) { if (chunk != null) FreeChunk(chunk); continue; } if (chunk == null) chunk = CreateChunk(cp); m_nearList.Add(chunk); } m_forceDrawListUpdate = true; }
public static bool PickVoxel(EnvironmentObject env, GameSurfaceView view, IntVector2 screenPos, IntGrid3 cropGrid, MapControlPickMode pickMode, out IntVector3 pos, out Direction face) { var camera = view.Camera; var ray = Ray.GetPickRay(screenPos.X, screenPos.Y, view.ViewPort, view.Camera.View * view.Camera.Projection); IntVector3 outpos = new IntVector3(); Direction outdir = Direction.None; var corner = cropGrid.Corner2; var size = new IntSize3(corner.X + 1, corner.Y + 1, corner.Z + 1); IntVector3 prevoutpos = new IntVector3(); Direction prevoutdir = Direction.None; VoxelRayCast.RunRayCast(size, ray.Position, ray.Direction, view.Camera.FarZ, (x, y, z, dir) => { var p = new IntVector3(x, y, z); if (cropGrid.Contains(p) == false) return false; var td = env.GetTileData(p); switch (pickMode) { case MapControlPickMode.Underground: if (!td.IsUndefined && !td.IsWall) return false; outpos = p; outdir = dir; return true; case MapControlPickMode.AboveGround: if (!td.IsUndefined && !td.IsWall) { prevoutpos = p; prevoutdir = dir; return false; } if (prevoutpos.IsNull) { outpos = p; outdir = dir; } else { outpos = prevoutpos; outdir = prevoutdir; } return true; case MapControlPickMode.Constant: if (p.Z > cropGrid.Z2) return false; outpos = p; outdir = dir; return true; default: throw new NotImplementedException(); } }); pos = outpos; face = outdir; return face != Direction.None; }
public AStarAreaTarget(IEnvironmentObject env, IntGrid3 destination) : base(env) { m_destination = destination; }
/// <summary> /// Directions of faces which are revealed due to ViewGrid /// </summary> Direction GetGridSliceDirections(ref IntGrid3 grid, ref IntGrid3 viewGrid) { Direction d = 0; // Note: we never draw the bottommost layer in the map, so we don't check for Z1 if (grid.Z2 == viewGrid.Z2) d |= Direction.Up; if (grid.X1 == viewGrid.X1) d |= Direction.West; if (grid.X2 == viewGrid.X2) d |= Direction.East; if (grid.Y1 == viewGrid.Y1) d |= Direction.North; if (grid.Y2 == viewGrid.Y2) d |= Direction.South; return d; }
public void Add(IntGrid3 box) { m_boxs.Add(box); }
/// <summary> /// Directions of faces which are revealed due to ViewGrid /// </summary> Direction GetVoxelSliceDirections(IntVector3 p, ref IntGrid3 viewGrid) { Direction d = 0; // Note: we never draw the bottommost layer in the map, so we don't check for Z1 if (p.Z == viewGrid.Z2) d |= Direction.Up; if (p.X == viewGrid.X1) d |= Direction.West; if (p.X == viewGrid.X2) d |= Direction.East; if (p.Y == viewGrid.Y1) d |= Direction.North; if (p.Y == viewGrid.Y2) d |= Direction.South; return d; }
void GenerateVertices(ref IntGrid3 viewGrid, Direction visibleChunkFaces, VertexList <TerrainVertex> terrainVertexList, VertexList <SceneryVertex> sceneryVertexList) { IntGrid3 chunkGrid = viewGrid.Intersect(new IntGrid3(this.ChunkOffset, Chunk.ChunkSize)); // is the chunk inside frustum, but outside the viewgrid? if (chunkGrid.IsNull) { return; } if (m_scanned == false) { ScanForAllEmptyOrUndefined(); } if (this.IsAllEmpty) { return; } if (this.IsAllUndefined) { CreateUndefinedChunk(ref viewGrid, ref chunkGrid, terrainVertexList, visibleChunkFaces); return; } if (m_voxelMap == null) { FillVoxelMap(); } // Draw from up to down to avoid overdraw for (int z = chunkGrid.Z2; z >= chunkGrid.Z1; --z) { for (int y = chunkGrid.Y1; y <= chunkGrid.Y2; ++y) { for (int x = chunkGrid.X1; x <= chunkGrid.X2; ++x) { var p = new IntVector3(x, y, z); var td = m_map.GetTileData(p); if (td.WaterLevel == 0) { if (td.IsEmpty) { continue; } } var pos = p - this.ChunkOffset; if (td.HasTree) { // Add tree as scenery vertex HandleTree(sceneryVertexList, td, ref pos); continue; } if (td.IsGreen) // XXX { continue; } var vox = m_voxelMap.Grid[pos.Z, pos.Y, pos.X]; HandleVoxel(p, ref vox, ref viewGrid, visibleChunkFaces, terrainVertexList); } } } }
void NotifyTileObjectChanges(IntGrid3 oldGrid, IntGrid3 newGrid) { if (this.Environment == null) { m_objects.Clear(); return; } var rm = oldGrid.Range().Except(newGrid.Range()) .SelectMany(p => this.Environment.GetContents(p)); foreach (var ob in rm) m_objects.Remove(ob); var add = newGrid.Range().Except(oldGrid.Range()) .SelectMany(p => this.Environment.GetContents(p)); foreach (var ob in add) m_objects.Add(ob); }
/// <summary> /// Find route from src to destination area /// </summary> public static AStarResult FindArea(IEnvironmentObject env, IntVector3 src, DirectionSet srcPositioning, IntGrid3 dstArea, int maxNodeCount = 200000, CancellationToken? cancellationToken = null) { var initLocs = env.GetPositioningLocations(src, srcPositioning); var target = new AStarAreaTarget(env, dstArea); return Find(initLocs, target, maxNodeCount, cancellationToken); }
void ReadAndSetTileData(Stream stream, IntGrid3 bounds) { using (var reader = new BinaryReader(stream)) { TileData td = new TileData(); foreach (IntPoint3 p in bounds.Range()) { td.Raw = reader.ReadUInt64(); m_tileGrid.SetTileData(p, td); if (MapTileTerrainChanged != null) MapTileTerrainChanged(p); } } }
public void Remove(IntGrid3 box) { m_boxs.Remove(box); }
public void SetTileDataRange(ulong[] tileData, IntGrid3 bounds) { int i = 0; for (int z = bounds.Z; z < bounds.Z + bounds.Depth; ++z) for (int y = bounds.Y; y < bounds.Y + bounds.Rows; ++y) for (int x = bounds.X; x < bounds.X + bounds.Columns; ++x) { ulong v = tileData[i++]; m_grid[z, y, x].Raw = v; } }
public static void SendSetTerrains(SetTerrainDialog dialog, EnvironmentObject env, IntGrid3 cube) { var data = dialog.Data; var args = new Dictionary<string, object>() { { "envID", env.ObjectID }, { "cube", cube }, { "terrainID", data.TerrainID }, { "terrainMaterialID", data.TerrainMaterialID }, { "interiorID", data.InteriorID }, { "interiorMaterialID", data.InteriorMaterialID }, { "waterLevel", data.Water.HasValue ? (data.Water == true ? (byte?)TileData.MaxWaterLevel : (byte?)0) : null }, }; var script = @"env = world.GetObject(envID) for p in cube.Range(): td = env.GetTileData(p) if terrainID != None: Dwarrowdelf.TileData.TerrainID.SetValue(td, terrainID) if terrainMaterialID != None: Dwarrowdelf.TileData.TerrainMaterialID.SetValue(td, terrainMaterialID) if interiorID != None: Dwarrowdelf.TileData.InteriorID.SetValue(td, interiorID) if interiorMaterialID != None: Dwarrowdelf.TileData.InteriorMaterialID.SetValue(td, interiorMaterialID) if waterLevel != None: Dwarrowdelf.TileData.WaterLevel.SetValue(td, waterLevel) env.SetTileData(p, td) env.ScanWaterTiles() "; var msg = new Dwarrowdelf.Messages.IPScriptMessage(script, args); GameData.Data.User.Send(msg); }
static void SetArea(EnvironmentObject env, IntGrid3 area, TileData data) { foreach (var p in area.Range()) env.SetTileData(p, data); }
public void SetTerrains(IntGrid3 bounds, byte[] tileDataList, bool isCompressed) { this.Version += 1; m_tileGrid.Grow(bounds.Corner2); //Trace.TraceError("Recv {0}", bounds.Z); #if !parallel using (var memStream = new MemoryStream(tileDataList)) { if (isCompressed == false) { ReadAndSetTileData(memStream, bounds); } else { using (var decompressStream = new DeflateStream(memStream, CompressionMode.Decompress)) ReadAndSetTileData(decompressStream, bounds); } } #else Task.Factory.StartNew(() => { var dstStream = new MemoryStream(); using (var memStream = new MemoryStream(tileDataList)) using (var decompressStream = new DeflateStream(memStream, CompressionMode.Decompress)) decompressStream.CopyTo(dstStream); dstStream.Position = 0; return dstStream; }).ContinueWith(t => { using (var stream = t.Result) ReadAndSetTileData(stream, bounds); //Trace.TraceError("done {0}", bounds.Z); }, TaskScheduler.FromCurrentSynchronizationContext()); #endif }
public void SetTerrains(IntGrid3 bounds, ulong[] tileData) { this.Version += 1; m_tileGrid.Grow(bounds.Corner2); //Trace.TraceError("Recv {0}", bounds.Z); m_tileGrid.SetTileDataRange(tileData, bounds); if (this.MapTileTerrainChanged != null) { foreach (var p in bounds.Range()) MapTileTerrainChanged(p); } }
void CreateUndefinedChunk(ref IntGrid3 viewGrid, ref IntGrid3 chunkGrid, VertexList<TerrainVertex> vertexList, Direction visibleChunkFaces) { // Faces that are visible due to viewgrid Direction sliceFaces = GetGridSliceDirections(ref chunkGrid, ref viewGrid) & visibleChunkFaces; // Only faces revealed by viewgrid are visible Direction visibleFaces = sliceFaces; if (visibleFaces == 0) return; int sides = (int)visibleFaces; FaceTexture tex = Chunk.UndefinedFaceTexture; const int occlusion = 0; var offset = chunkGrid.Corner1 - this.ChunkOffset; var size = new IntVector3(chunkGrid.Size.Width, chunkGrid.Size.Height, chunkGrid.Size.Depth); // All faces are revealed by viewgrid byte sliceHack = (byte)1; if (Chunk.UseBigUnknownChunk) { /* Note: Using chunk sized quads causes t-junction problems */ for (int side = 0; side < 6 && sides != 0; ++side, sides >>= 1) { if ((sides & 1) == 0) continue; var vertices = s_cubeFaceInfo[side].Vertices; IntVector3 v0 = vertices[0] * size + offset; IntVector3 v1 = vertices[1] * size + offset; IntVector3 v2 = vertices[2] * size + offset; IntVector3 v3 = vertices[3] * size + offset; var vd = new TerrainVertex(v0, v1, v2, v3, occlusion, occlusion, occlusion, occlusion, tex, sliceHack); vertexList.Add(vd); } } else { for (int side = 0; side < 6 && sides != 0; ++side, sides >>= 1) { if ((sides & 1) == 0) continue; int d0 = side / 2; int d1 = (d0 + 1) % 3; int d2 = (d0 + 2) % 3; bool posFace = (side & 1) == 1; var vertices = s_cubeFaceInfo[side].Vertices; IntVector3 v0 = vertices[0] + offset; IntVector3 v1 = vertices[1] + offset; IntVector3 v2 = vertices[2] + offset; IntVector3 v3 = vertices[3] + offset; var vec1 = new IntVector3(); vec1[d1] = 1; var vec2 = new IntVector3(); vec2[d2] = 1; for (int v = 0; v < size[d1]; ++v) for (int u = 0; u < size[d2]; ++u) { var off = vec1 * v + vec2 * u; if (posFace) off[d0] = size[d0] - 1; var vd = new TerrainVertex(v0 + off, v1 + off, v2 + off, v3 + off, occlusion, occlusion, occlusion, occlusion, tex, sliceHack); vertexList.Add(vd); } } } }
public static void SendSetTerrains(SetTerrainDialog dialog, EnvironmentObject env, IntGrid3 cube) { var data = dialog.Data; var args = new Dictionary <string, object>() { { "envID", env.ObjectID }, { "cube", cube }, { "tileID", data.TileID }, { "materialID", data.MaterialID }, { "waterLevel", data.Water.HasValue ? (data.Water == true ? (byte?)TileData.MaxWaterLevel : (byte?)0) : null }, }; var script = @"env = world.GetObject(envID) for p in cube.Range(): td = env.GetTileData(p) if tileID != None: Dwarrowdelf.TileData.ID.SetValue(td, tileID) if materialID != None: Dwarrowdelf.TileData.MaterialID.SetValue(td, materialID) if waterLevel != None: Dwarrowdelf.TileData.WaterLevel.SetValue(td, waterLevel) env.SetTileData(p, td) env.ScanWaterTiles() "; var msg = new Dwarrowdelf.Messages.IPScriptMessage(script, args); GameData.Data.User.Send(msg); }
public void GenerateVertices(ref IntGrid3 viewGrid, IntVector3 cameraChunkPos, VertexList<TerrainVertex> terrainVertexList, VertexList<SceneryVertex> sceneryVertexList) { terrainVertexList.Clear(); sceneryVertexList.Clear(); var diff = cameraChunkPos - this.ChunkPosition; Direction visibleChunkFaces = 0; if (diff.X >= 0) visibleChunkFaces |= Direction.PositiveX; if (diff.X <= 0) visibleChunkFaces |= Direction.NegativeX; if (diff.Y >= 0) visibleChunkFaces |= Direction.PositiveY; if (diff.Y <= 0) visibleChunkFaces |= Direction.NegativeY; if (diff.Z >= 0) visibleChunkFaces |= Direction.PositiveZ; if (diff.Z <= 0) visibleChunkFaces |= Direction.NegativeZ; GenerateVertices(ref viewGrid, visibleChunkFaces, terrainVertexList, sceneryVertexList); this.VertexCount = terrainVertexList.Count; this.SceneryVertexCount = sceneryVertexList.Count; }
void CreateOreSphere(IntPoint3 center, int r, MaterialID oreMaterialID, double probIn, double probOut) { // adjust r, so that r == 1 gives sphere of one tile r -= 1; // XXX split the sphere into 8 parts, and mirror var bb = new IntGrid3(center.X - r, center.Y - r, center.Z - r, r * 2 + 1, r * 2 + 1, r * 2 + 1); var rs = MyMath.Square(r); foreach (var p in bb.Range()) { var y = p.Y; var x = p.X; var z = p.Z; var v = MyMath.Square(x - center.X) + MyMath.Square(y - center.Y) + MyMath.Square(z - center.Z); if (rs >= v) { var rr = Math.Sqrt(v); double rel; if (r == 0) rel = 1; else rel = 1 - rr / r; var prob = (probIn - probOut) * rel + probOut; if (GetRandomDouble() <= prob) CreateOre(p, oreMaterialID); } } }