bool MergeIfMatchingCoords(WorldChunkComputed.WorldChunkZone chunkZone, Direction direction, WorldChunk sideChunk, WorldChunkComputed.WorldChunkZone sideChunkZone, WorldChunkSettings setting) { Direction inverseDirection = Coord.GetDirectionInverse(direction); List <int> matchingCoords = new List <int> (); for (int coord_idx = 0; coord_idx < chunkZone.directionChunkBorderCoords [direction].Count; coord_idx++) { // Get coord next to this one on the side Chunk /* Coord sideCoord = chunkZone.directionChunkBorderCoords [direction] [coord_idx].GetCoordOnChunkSide (direction, setting); * * if (sideChunkZone.directionChunkBorderCoords [inverseDirection].Contains (sideCoord)) { * matchingCoords.Add ((direction == Direction.Top || direction == Direction.Bottom) ? sideCoord.x : sideCoord.y); * } */ // Only X or Y int coord_value = chunkZone.directionChunkBorderCoords [direction] [coord_idx]; if (sideChunkZone.directionChunkBorderCoords [inverseDirection].Contains(coord_value)) { matchingCoords.Add(coord_value); } } // Have no matchink coords between both zones if (matchingCoords.Count > 0) { this.RemoveAndMergeIntoSideZone(chunkZone, direction, sideChunk, sideChunkZone, matchingCoords, setting); return(true); } return(false); }
// World Zone created on a chunk, and expended after public WorldZone(WorldChunk chunk, WorldChunkComputed.WorldChunkZone zone) { this.randomInt = (int)Random.Range(1f, 100f); this.randomColor = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f)); this.type = zone.type; this.isMainGround = false; this.isDeleted = false; if (zone.IsOnChunkBorder()) { this.state = WorldZoneStates.Created; this.requireZoneState = (chunk.requireState >= ChunkStates.Merged) ? WorldZoneStates.Merged : WorldZoneStates.Created; /* * for (int e = 0; e < Coord.directions.Length; e++) { * Direction direction = Coord.directions [e]; * Coord directionCoord = chunk.coord.GetDirection (direction); * if (zone.isDirectionChunkBorder [direction]) { * this.missingChunks.Add (directionCoord); * } * }*/ } else { this.state = WorldZoneStates.Merged; this.requireZoneState = WorldZoneStates.Merged; } // Have chunk border this.chunks.Add(chunk.coord); // ref to this zone this.chunkZones[chunk.coord] = new List <WorldChunkComputed.WorldChunkZone>(); this.chunkZones [chunk.coord].Add(zone); // Add a ref to it }
// Merge all zone from this chunk and all sideChunk // Will be called one time and another time reversed (to found fakezone and ground zone who need to be merged with MainGround) void MergeSideChunk(Direction direction, WorldChunk sideChunk, WorldChunkSettings setting) { Direction inverseDirection = Coord.GetDirectionInverse(direction); for (int chunkZone_idx = this.chunkComputed.zones.Count - 1; chunkZone_idx >= 0; chunkZone_idx--) { WorldChunkComputed.WorldChunkZone chunkZone = this.chunkComputed.zones [chunkZone_idx]; if (chunkZone.worldZoneRef.isMainGround) { continue; // Don't merge MainGround into another } // Found a zone who need to be merged on direction (and it's not already done ? we repass here when reverse) if (chunkZone.isDirectionChunkBorder [direction] && chunkZone.missingChunks.Contains(sideChunk.coord)) { bool machingFound = false; for (int sideChunkZone_idx = sideChunk.chunkComputed.zones.Count - 1; sideChunkZone_idx >= 0; sideChunkZone_idx--) { WorldChunkComputed.WorldChunkZone sideChunkZone = sideChunk.chunkComputed.zones [sideChunkZone_idx]; if (!sideChunkZone.isDirectionChunkBorder [inverseDirection]) { continue; } if (!sideChunkZone.missingChunks.Contains(this.coord)) { continue; } if (sideChunkZone.type != chunkZone.type) { continue; } if (this.MergeIfMatchingCoords(chunkZone, direction, sideChunk, sideChunkZone, setting)) { machingFound = true; } } // IT's a fake bordered zone ! Some coord are on the limit of the chunk but no one on the next if (!machingFound && !chunkZone.worldZoneRef.isMainGround) { chunkZone.missingChunks.Remove(sideChunk.coord); chunkZone.isDirectionChunkBorder [direction] = false; chunkZone.directionChunkBorderCoords [direction].Clear(); /* done by sideChunk.SeeMore() * if (chunkZone.worldZoneRef.GetMissingChunks ().Count == 0) { * chunkZone.worldZoneRef.OnMergeCompleted (); * }*/ } } } }
public static Texture2D WorldZonesMergingTexture(WorldChunk chunk, WorldChunkSettings setting) { Color groundMin = new Color(.25f, .25f, .25f); Color groundMax = new Color(.75f, .75f, .75f); Color[] colourMap = new Color[setting.scaledSize * setting.scaledSize]; bool[] isOnZone = new bool[setting.scaledSize * setting.scaledSize]; for (int idx = 0; idx < chunk.worldZonesRefs.Count; idx++) { // Only display Completed //if (chunk.worldZonesRefs [idx].isCompleted) { // Be sure this Wolrd zone contain this chunk if (chunk.worldZonesRefs [idx].chunkZones.ContainsKey(chunk.coord)) { for (int chunk_zone_idx = 0; chunk_zone_idx < chunk.worldZonesRefs [idx].chunkZones[chunk.coord].Count; chunk_zone_idx++) { WorldChunkComputed.WorldChunkZone zone = chunk.worldZonesRefs [idx].chunkZones[chunk.coord] [chunk_zone_idx]; foreach (Coord c in zone.coords) { if (zone.type == WorldZoneTypes.Water || zone.type == WorldZoneTypes.Mountain) { isOnZone [c.y * setting.scaledSize + c.x] = true; colourMap [c.y * setting.scaledSize + c.x] = zone.worldZoneRef.randomColor; } } } } //} } for (int y = 0; y < setting.scaledSize; y++) { for (int x = 0; x < setting.scaledSize; x++) { if (!isOnZone [y * setting.scaledSize + x]) { Coord c = new Coord(x, y); float height = chunk.chunkData.GetHeightValue(c, setting); float delta = (height - setting.water) * (1 / (setting.mountain - setting.water)); colourMap [y * setting.scaledSize + x] = Color.Lerp(groundMax, groundMin, delta); } } } return(TextureGenerator.TextureFromColorMap(colourMap, setting.scaledSize)); }
public List <Coord> GetMissingChunks() { List <Coord> coords = new List <Coord> (); for (int idx_chunk = 0; idx_chunk < this.chunks.Count; idx_chunk++) { for (int idx_zone = 0; idx_zone < this.chunkZones [this.chunks [idx_chunk]].Count; idx_zone++) { WorldChunkComputed.WorldChunkZone chunkZone = this.chunkZones [this.chunks [idx_chunk]] [idx_zone]; for (int idx_direction = 0; idx_direction < chunkZone.missingChunks.Count; idx_direction++) { if (!coords.Contains(chunkZone.missingChunks [idx_direction])) { coords.Add(chunkZone.missingChunks [idx_direction]); } } } } return(coords); }
public void CreateWorldZones(WorldChunk chunk, WorldChunkSettings setting) { // First create, AND AFTER ALL CREATED try to merge (or a chunk can think he's all merged but some zones are still not created) for (int idx = 0; idx < chunk.chunkComputed.zones.Count; idx++) { WorldChunkComputed.WorldChunkZone zone = chunk.chunkComputed.zones [idx]; // It's enought to be directly integrated to mainGround if (zone.isMainGround(setting)) { if (!this.mainGround.chunks.Contains(chunk.coord)) { this.mainGround.chunks.Add(chunk.coord); } if (!this.mainGround.chunkZones.ContainsKey(chunk.coord)) { this.mainGround.chunkZones[chunk.coord] = new List <WorldChunkComputed.WorldChunkZone>(); } this.mainGround.chunkZones [chunk.coord].Add(zone); // Add a ref to it zone.worldZoneRef = this.mainGround; if (!chunk.worldZonesRefs.Contains(this.mainGround)) { chunk.worldZonesRefs.Add(this.mainGround); } } else { // Create a new zone // If this zone already created on another side it's will be merged when all chunks are computed WorldZone worldZone = new WorldZone(chunk, zone); this.worldZones.Add(worldZone); zone.worldZoneRef = worldZone; chunk.worldZonesRefs.Add(worldZone); } } chunk.MergeZones(setting); }
public static Texture2D WorldMergingTexture(WorldChunk chunk, WorldChunkSettings setting) { Color blue = new Color(0f, 189f / 255f, 1f); Color yellow = new Color(1f, 245f / 255f, 0f); Color red = new Color(1f, 57f / 255f, 0f); Color black = new Color(0f, 0f, 0f); Color groundMin = new Color(.25f, .25f, .25f); Color groundMax = new Color(.75f, .75f, .75f); float water = setting.water; // min float mountain = setting.mountain; // max Color[] colourMap = new Color[setting.scaledSize * setting.scaledSize]; bool[] isOnZone = new bool[setting.scaledSize * setting.scaledSize]; for (int idx = 0; idx < chunk.worldZonesRefs.Count; idx++) { if (chunk.worldZonesRefs [idx].chunkZones.ContainsKey(chunk.coord)) { for (int chunk_zone_idx = 0; chunk_zone_idx < chunk.worldZonesRefs [idx].chunkZones[chunk.coord].Count; chunk_zone_idx++) { WorldChunkComputed.WorldChunkZone zone = chunk.worldZonesRefs [idx].chunkZones[chunk.coord] [chunk_zone_idx]; if (!zone.worldZoneRef.isMainGround && zone.worldZoneRef.state >= WorldZoneStates.Merged) { if (zone.containAllCoords) { for (int y = 0; y < setting.scaledSize; y++) { for (int x = 0; x < setting.scaledSize; x++) { Coord c = new Coord(x, y, setting); isOnZone [c.y * setting.scaledSize + c.x] = true; if (zone.type == WorldZoneTypes.Ground) { float height = chunk.chunkData.GetHeightValue(c, setting); float delta = (height - water) * (1 / (mountain - water)); colourMap [c.y * setting.scaledSize + c.x] = Color.Lerp(yellow, red, delta) / 1.5f; } else { colourMap [c.y * setting.scaledSize + c.x] = (zone.type == WorldZoneTypes.Water) ? blue : black; } } } } else { foreach (Coord c in zone.coords) { isOnZone [c.y * setting.scaledSize + c.x] = true; if (zone.type == WorldZoneTypes.Ground) { float height = chunk.chunkData.GetHeightValue(c, setting); float delta = (height - water) * (1 / (mountain - water)); colourMap [c.y * setting.scaledSize + c.x] = Color.Lerp(yellow, red, delta) / 1.5f; } else { colourMap [c.y * setting.scaledSize + c.x] = (zone.type == WorldZoneTypes.Water) ? blue : black; } } } } } } } for (int y = 0; y < setting.scaledSize; y++) { for (int x = 0; x < setting.scaledSize; x++) { Coord c = new Coord(x, y, setting); // DEV unicolor // colourMap [c.idx] = blue; // continue; // end DEV unicolor if (isOnZone [c.y * setting.scaledSize + c.x]) { continue; } float height = chunk.chunkData.GetHeightValue(c); float delta = (height - water) * (1 / (mountain - water)); colourMap [c.idx] = (chunk.state >= ChunkStates.Merged) ? Color.Lerp(yellow, red, delta) : Color.Lerp(groundMax, groundMin, delta); } } return(TextureGenerator.TextureFromColorMap(colourMap, setting.scaledSize)); }
public static Texture2D WorldChunksZoneStatesTexture(WorldChunk chunk, WorldChunkSettings setting) { Color blue = new Color(0f, 189f / 255f, 1f); Color yellow = new Color(1f, 245f / 255f, 0f); Color black = new Color(.2f, .2f, .2f); Color loaded = new Color(.2f, .2f, 1f); Color computed = new Color(.2f, 1f, .2f); Color merging = new Color(1f, .2f, .2f); Color merged = new Color(1f, .9f, .2f); Color groundMin = new Color(.25f, .25f, .25f); Color groundMax = new Color(.75f, .75f, .75f); Color[] colourMap = new Color[setting.scaledSize * setting.scaledSize]; bool[] isOnZone = new bool[setting.scaledSize * setting.scaledSize]; for (int idx = 0; idx < chunk.worldZonesRefs.Count; idx++) { // Only display Completed //if (chunk.worldZonesRefs [idx].isCompleted) { // Be sure this Wolrd zone contain this chunk if (chunk.worldZonesRefs [idx].chunkZones.ContainsKey(chunk.coord)) { for (int chunk_zone_idx = 0; chunk_zone_idx < chunk.worldZonesRefs [idx].chunkZones[chunk.coord].Count; chunk_zone_idx++) { WorldChunkComputed.WorldChunkZone zone = chunk.worldZonesRefs [idx].chunkZones[chunk.coord] [chunk_zone_idx]; foreach (Coord c in zone.coords) { isOnZone [c.y * setting.scaledSize + c.x] = true; if (zone.type == WorldZoneTypes.Ground) { colourMap [c.y * setting.scaledSize + c.x] = yellow; } else { colourMap [c.y * setting.scaledSize + c.x] = (zone.type == WorldZoneTypes.Water) ? blue : black; } if (zone.worldZoneRef.requireZoneState == WorldZoneStates.Created) { colourMap [c.y * setting.scaledSize + c.x] *= computed; } else if (zone.worldZoneRef.requireZoneState == WorldZoneStates.Merged && zone.worldZoneRef.state == WorldZoneStates.Created) { colourMap [c.y * setting.scaledSize + c.x] *= merging; } else if (zone.worldZoneRef.state >= WorldZoneStates.Merged) { colourMap [c.y * setting.scaledSize + c.x] *= merged; } } } } //} } for (int y = 0; y < setting.scaledSize; y++) { for (int x = 0; x < setting.scaledSize; x++) { if (!isOnZone [y * setting.scaledSize + x]) { Coord c = new Coord(x, y); float height = chunk.chunkData.GetHeightValue(c, setting); float delta = (height - setting.water) * (1 / (setting.mountain - setting.water)); colourMap [y * setting.scaledSize + x] = Color.Lerp(groundMax, groundMin, delta); } } } return(TextureGenerator.TextureFromColorMap(colourMap, setting.scaledSize)); }
// We found two WorldChunkZone who match ! // Remove the WorldZone related to this and merge into sideWorldZone void RemoveAndMergeIntoSideZone(WorldChunkComputed.WorldChunkZone chunkZone, Direction direction, WorldChunk sideChunk, WorldChunkComputed.WorldChunkZone sideChunkZone, List <int> matchingCoords, WorldChunkSettings setting) { Direction inverseDirection = Coord.GetDirectionInverse(direction); // Get ref everytime ! // (If A is merged to B, and try after to be merged with C, take ref to {AmergedB} instead of {deletedA}) WorldZone zone = chunkZone.worldZoneRef; WorldZone sideZone = sideChunkZone.worldZoneRef; /* * if (zone.state > sideZone.state) { * sideZone.state = zone.state; * }*/ if (zone.requireZoneState > sideZone.requireZoneState) { sideZone.requireZoneState = zone.requireZoneState; } // Loop all chunk who are on the zone to be remove for (int chunk_idx = zone.chunks.Count - 1; chunk_idx >= 0; chunk_idx--) { Coord zoneCoord = zone.chunks [chunk_idx]; // This chunk didn't exist on sideZone if (!sideZone.chunks.Contains(zoneCoord)) { sideZone.chunks.Add(zoneCoord); sideZone.chunkZones.Add(zoneCoord, new List <WorldChunkComputed.WorldChunkZone> ()); } // Remove missing chunk on both zone: chunkZone.missingChunks.Remove(sideChunk.coord); // sideChunkZone.missingChunks.Remove(this.coord); // Update matching coords chunkZone.directionChunkBorderCoords[direction] = matchingCoords; // sideChunkZone.directionChunkBorderCoords[inverseDirection] = matchingCoords; // if (zone.chunkZones.ContainsKey(zoneCoord)) { for (int zoneChunkZone_idx = zone.chunkZones [zoneCoord].Count - 1; zoneChunkZone_idx >= 0; zoneChunkZone_idx--) { WorldChunkComputed.WorldChunkZone zoneChunkZone = zone.chunkZones [zoneCoord] [zoneChunkZone_idx]; // In case of corners, the diagonal chunk will be merge to both sides (who are shared by diagonals) and a loop is created // Check it's not the same if (zoneChunkZone.worldZoneRef != sideChunkZone.worldZoneRef) { sideZone.chunkZones [zoneCoord].Add(zoneChunkZone); zoneChunkZone.worldZoneRef = sideChunkZone.worldZoneRef; } } } // Update all refs (to the new zone) on every chunk who contain this removed zone for (int chunkCoord_idx = zone.chunks.Count - 1; chunkCoord_idx >= 0; chunkCoord_idx--) { MapEndless.instance.worldChunks [zone.chunks [chunkCoord_idx]].worldZonesRefs.Remove(zone); if (!MapEndless.instance.worldChunks [zone.chunks [chunkCoord_idx]].worldZonesRefs.Contains(sideZone)) { MapEndless.instance.worldChunks [zone.chunks [chunkCoord_idx]].worldZonesRefs.Add(sideZone); } } this.worldZonesRefs.Remove(zone); if (!this.worldZonesRefs.Contains(sideZone)) { this.worldZonesRefs.Add(sideZone); } MapEndless.instance.worldZones.Remove(zone); zone.isDeleted = true; } }