public static bool IsIntersecting(CoordRect c1, CoordRect c2) { if (c2.Contains(c1.offset.x, c1.offset.z) || c2.Contains(c1.offset.x + c1.size.x, c1.offset.z) || c2.Contains(c1.offset.x, c1.offset.z + c1.size.z) || c2.Contains(c1.offset.x + c1.size.x, c1.offset.z + c1.size.z)) { return(true); } if (c1.Contains(c2.offset.x, c2.offset.z) || c1.Contains(c2.offset.x + c2.size.x, c2.offset.z) || c1.Contains(c2.offset.x, c2.offset.z + c1.size.z) || c1.Contains(c2.offset.x + c2.size.x, c2.offset.z + c2.size.z)) { return(true); } return(false); }
//TODO: test public static int DistanceAxisAligned(Coord c, CoordRect rect) //NOT manhattan dist. offset and size are instead of UnityEngine.Rect { //finding x distance int distPosX = rect.offset.x - c.x; int distNegX = c.x - rect.offset.x - rect.size.x; int distX; if (distPosX >= 0) { distX = distPosX; } else if (distNegX >= 0) { distX = distNegX; } else { distX = 0; } //finding z distance int distPosZ = rect.offset.z - c.z; int distNegZ = c.z - rect.offset.z - rect.size.z; int distZ; if (distPosZ >= 0) { distZ = distPosZ; } else if (distNegZ >= 0) { distZ = distNegZ; } else { distZ = 0; } //returning the maximum(!) distance if (distX > distZ) { return(distX); } else { return(distZ); } }
public Matrix TestResize (CoordRect newRect) { Matrix result = new Matrix(newRect); Coord min = result.rect.Min; Coord max = result.rect.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) { float percentX = 1f*(x-result.rect.offset.x)/result.rect.size.x; float origX = percentX*this.rect.size.x + this.rect.offset.x; float percentZ = 1f*(z-result.rect.offset.z)/result.rect.size.z; float origZ = percentZ*this.rect.size.z + this.rect.offset.z; result[x,z] = this.OutdatedGetInterpolated(origX, origZ); } return result; }
public CoordRect Approximate(int val) { CoordRect approx = new CoordRect(); approx.size.x = (size.x / val + 1) * val; approx.size.z = (size.z / val + 1) * val; approx.offset.x = offset.x - (approx.size.x - size.x) / 2; approx.offset.z = offset.z - (approx.size.z - size.z) / 2; approx.offset.x = (int)(approx.offset.x / val + 0.5f) * val; approx.offset.z = (int)(approx.offset.z / val + 0.5f) * val; return(approx); }
public void Rebuild() //calculating height/typemap and placing object + updating visibility in apply { #if WDEBUG Profiler.BeginSample("Rebuild"); #endif //preparing worker if (repositionWorker == null) { repositionWorker = new ThreadWorker(); repositionWorker.name = "Horizon Reposition"; repositionWorker.Calculate += CalculateReposition; repositionWorker.Apply += ApplyReposition; repositionWorker.tag = "VoxelandHorizon"; repositionWorker.priority = 2; //prior to everything! } //placing object //transform.localPosition = camCoord.vector3; //moving in apply to prevent while-generate-mismatch //transform.localScale = new Vector3(voxeland.chunks.cellSize, 1, voxeland.chunks.cellSize); //saving ref variables usedAreas.Clear(); //CoordRect areasRect = new CoordRect(currentCoord, (int)(meshSize*voxeland.chunks.cellSize/2), voxeland.data.areas.cellRes); CoordRect areasRect = CoordRect.PickIntersectingCellsByPos(transform.position, voxeland.data.areaSize / 2, cellSize: voxeland.data.areaSize); foreach (Data.Area area in voxeland.data.areas.WithinRect(areasRect)) { if (!area.generateWorker.ready) { continue; } usedAreas.Add(area); } //starting worker if (heightmap == null) { CalculateReposition(); ApplyReposition(); } else { repositionWorker.Start(); } #if WDEBUG Profiler.EndSample(); #endif }
public Matrix2(Coord offset, Coord size, T[] array = null) { rect = new CoordRect(offset, size); count = rect.size.x * rect.size.z; if (array != null && array.Length < count) { Debug.Log("Array length: " + array.Length + " is lower then matrix capacity: " + count); } if (array != null && array.Length >= count) { this.array = array; } else { this.array = new T[count]; } }
public Matrix2(int x, int z, T[] array = null) { rect = new CoordRect(0, 0, x, z); count = x * z; if (array != null && array.Length < count) { Debug.LogError("Array length: " + array.Length + " is lower then matrix capacity: " + count); } if (array != null && array.Length >= count) { this.array = array; } else { this.array = new T[count]; } }
public void Fill(Matrix2 <T> m, bool removeBorders = false) { CoordRect intersection = CoordRect.Intersect(rect, m.rect); Coord min = intersection.Min; Coord max = intersection.Max; for (int x = min.x; x < max.x; x++) { for (int z = min.z; z < max.z; z++) { this[x, z] = m[x, z]; } } if (removeBorders) { RemoveBorders(intersection); } }
public void FromTextureAlpha (Texture2D texture) { CoordRect textureRect = new CoordRect(0,0, texture.width, texture.height); CoordRect intersection = CoordRect.Intersect(textureRect, rect); Color[] colors = texture.GetPixels(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z); Coord min = intersection.Min; Coord max = intersection.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) { int tx = x-min.x; int tz = z-min.z; Color col = colors[tz*(max.x-min.x) + tx]; this[x,z] = (col.r+col.g+col.b+col.a)/4; } }
public void RemoveObjsInRange(float posX, float posZ, float range) //TODO: test, then replace CellNumsInRect. Or better replace with callback { Rect rect = new Rect(posX - range, posZ - range, range * 2, range * 2); rect = CoordinatesExtensions.Intersect(rect, this.rect); foreach (int c in CellNumsInRect(rect.min, rect.max)) { for (int p = cells.array[c].count - 1; p >= 0; p--) { float distSq = (cells.array[c].poses[p].x - posX) * (cells.array[c].poses[p].x - posX) + (cells.array[c].poses[p].z - posZ) * (cells.array[c].poses[p].z - posZ); if (distSq < range * range) { Remove(c, p); } } } }
public Matrix OutdatedResize (CoordRect newRect, float smoothness=1, Matrix result=null) { //calculating ratio int upscaleRatio = newRect.size.x / rect.size.x; int downscaleRatio = rect.size.x / newRect.size.x; //checking if rect could be rescaled if (upscaleRatio > 1 && !newRect.Divisible(upscaleRatio)) Debug.LogError("Matrix rect " + rect + " could not be upscaled to " + newRect + " with factor " + upscaleRatio); if (downscaleRatio > 1 && !rect.Divisible(downscaleRatio)) Debug.LogError("Matrix rect " + rect + " could not be downscaled to " + newRect + " with factor " + downscaleRatio); //scaling if (upscaleRatio > 1) result = OutdatedUpscale(upscaleRatio, result:result); if (downscaleRatio > 1) result = OutdatedDownscale(downscaleRatio, smoothness:smoothness, result:result); //returning clone if all ratios are 1 if (upscaleRatio <= 1 && downscaleRatio <= 1) return Copy(result); else return result; }
public float[,,] ReadSplatmap (TerrainData data, int channel, float[,,] array=null) { CoordRect intersection = CoordRect.Intersect(rect, new CoordRect(0,0,data.alphamapResolution, data.alphamapResolution)); //get heights if (array==null) array = data.GetAlphamaps(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z); //returns x and z swapped //reading array Coord min = intersection.Min; Coord max = intersection.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) this[x,z] = array[z-min.z, x-min.x, channel]; //removing borders RemoveBorders(intersection); return array; }
public float[,] ReadHeighmap (TerrainData data, float height=1) { CoordRect intersection = CoordRect.Intersect(rect, new CoordRect(0,0,data.heightmapResolution, data.heightmapResolution)); //get heights float[,] array = data.GetHeights(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z); //returns x and z swapped //reading 2d array Coord min = intersection.Min; Coord max = intersection.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) this[x,z] = array[z-min.z, x-min.x] * height; //removing borders RemoveBorders(intersection); return array; }
public IEnumerable <Coord> DistanceArea(CoordRect rect) //same as distance are, but clamped by rect { int maxDist = Mathf.Max(x - rect.offset.x, rect.Max.x - x, z - rect.offset.z, rect.Max.z - z) + 1; if (rect.CheckInRange(this)) { yield return(this); } for (int i = 0; i < maxDist; i++) { foreach (Coord c in DistancePerimeter(i)) { if (rect.CheckInRange(c)) { yield return(c); } } } }
public void ClampByRect(CoordRect rect) { if (x < rect.offset.x) { x = rect.offset.x; } if (x >= rect.offset.x + rect.size.x) { x = rect.offset.x + rect.size.x - 1; } if (z < rect.offset.z) { z = rect.offset.z; } if (z >= rect.offset.z + rect.size.z) { z = rect.offset.z + rect.size.z - 1; } }
public Stacker (CoordRect smallRect, CoordRect bigRect) { this.smallRect = smallRect; this.bigRect = bigRect; isDownscaled = false; //do not create additional matrices if rect sizes are the same if (bigRect==smallRect) { upscaled = downscaled = new Matrix(bigRect); } else { downscaled = new Matrix(smallRect); upscaled = new Matrix(bigRect); difference = new Matrix(bigRect); //once arrays created they should not be resized } }
public void WriteTextureInterpolated (Texture2D texture, CoordRect textureRect, WrapMode wrap=WrapMode.Once, float rangeMin=0, float rangeMax=1) { float pixelSizeX = 1f * textureRect.size.x / texture.width; float pixelSizeZ = 1f * textureRect.size.z / texture.height; Rect pixelTextureRect = new Rect(0, 0, texture.width, texture.height); Rect pixelMatrixRect = new Rect( (textureRect.offset.x - rect.offset.x) / pixelSizeX, (textureRect.offset.z - rect.offset.z) / pixelSizeZ, rect.size.x/pixelSizeX, rect.size.z/pixelSizeZ); Rect pixelIntersection = CoordinatesExtensions.Intersect(pixelTextureRect, pixelMatrixRect); CoordRect intersect = new CoordRect( Mathf.CeilToInt(pixelIntersection.x), Mathf.CeilToInt(pixelIntersection.y), Mathf.FloorToInt(pixelIntersection.width), Mathf.FloorToInt(pixelIntersection.height) ); Color[] colors = new Color[intersect.size.x*intersect.size.z]; Coord min = intersect.Min; Coord max = intersect.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) { float wx = x*pixelSizeX - textureRect.offset.x + rect.offset.x*2; float wz = z*pixelSizeZ - textureRect.offset.z + rect.offset.z*2; //float val = this[x,z]; //TODO: direct float val = GetInterpolated(wx, wz); val -= rangeMin; val /= rangeMax-rangeMin; //val = 1; colors[(z-min.z)*(max.x-min.x) + (x-min.x)] = new Color(val, val, val); //TODO: r should not be == r and ==b, there should be 1 byte diff } texture.SetPixels(intersect.offset.x, intersect.offset.z, intersect.size.x, intersect.size.z, colors); texture.Apply(); }
public void FillTexture (Texture2D texture=null, Color[] colors=null, float rangeMin=0, float rangeMax=1, bool resizeTexture=false) { //creating or resizing texture if (texture == null) texture = new Texture2D(rect.size.x, rect.size.z); if (resizeTexture) texture.Resize(rect.size.x, rect.size.z); //finding matrix-texture intersection Coord textureSize = new Coord(texture.width, texture.height); CoordRect textureRect = new CoordRect(new Coord(0,0), textureSize); CoordRect intersection = CoordRect.Intersect(textureRect, rect); //checking ref color array if (colors == null || colors.Length != intersection.size.x*intersection.size.z) colors = new Color[intersection.size.x*intersection.size.z]; //filling texture Coord min = intersection.Min; Coord max = intersection.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) { float val = this[x,z]; //adjusting value to range val -= rangeMin; val /= rangeMax-rangeMin; //making color gradient float byteVal = val * 256; int flooredByteVal = (int)byteVal; float remainder = byteVal - flooredByteVal; float flooredVal = flooredByteVal/256f; float ceiledVal = (flooredByteVal+1)/256f; //saving to colors int tx = x-min.x; int tz = z-min.z; colors[tz*(max.x-min.x) + tx] = new Color(flooredVal, remainder>0.333f ? ceiledVal : flooredVal, remainder>0.666f ? ceiledVal : flooredVal); } texture.SetPixels(intersection.offset.x, intersection.offset.z, intersection.size.x, intersection.size.z, colors); texture.Apply(); }
public void WriteHeightmap (TerrainData data, float[,] array=null, float brushFallof=0.5f, bool delayLod=false) { CoordRect intersection = CoordRect.Intersect(rect, new CoordRect(0,0,data.heightmapResolution, data.heightmapResolution)); //checking ref array if (array == null || array.Length != intersection.size.x*intersection.size.z) array = new float[intersection.size.z,intersection.size.x]; //x and z swapped //write to 2d array Coord min = intersection.Min; Coord max = intersection.Max; for (int x=min.x; x<max.x; x++) for (int z=min.z; z<max.z; z++) { float fallofFactor = Fallof(x,z,brushFallof); if (Mathf.Approximately(fallofFactor,0)) continue; array[z-min.z, x-min.x] = this[x,z]*fallofFactor + array[z-min.z, x-min.x]*(1-fallofFactor); //array[z-min.z, x-min.x] += this[x,z]; } if (delayLod) data.SetHeightsDelayLOD(intersection.offset.x, intersection.offset.z, array); else data.SetHeights(intersection.offset.x, intersection.offset.z, array); }
public MatrixWorld(CoordRect rect, CoordRect worldRect, float[] array = null) { //standard matrix initialization this.rect = rect; count = rect.size.x * rect.size.z; if (array != null && array.Length < count) { Debug.Log("Array length: " + array.Length + " is lower then matrix capacity: " + count); } if (array != null && array.Length >= count) { this.array = array; } else { this.array = new float[count]; } //world rect this.worldRect = worldRect; }
public static Rect Intersect(Rect r1, CoordRect r2) { Rect result = new Rect(0, 0, 0, 0); result.x = Mathf.Max(r1.x, r2.offset.x); result.y = Mathf.Max(r1.y, r2.offset.z); result.max = new Vector2( Mathf.Min(r1.max.x, r2.offset.x + r2.size.x), Mathf.Min(r1.max.y, r2.offset.z + r2.size.z)); if (result.size.x < 0) { result.size = new Vector2(0, result.size.y); } if (result.size.y < 0) { result.size = new Vector2(result.size.y, 0); } return(result); }
/*public void OverBlur (int iterations=20) { Matrix blurred = this.Clone(null); for (int i=1; i<=iterations; i++) { if (i==1 || i==2) blurred.Blur(step:1); else if (i==3) { blurred.Blur(step:1); blurred.Blur(step:1); } else blurred.Blur(step:i-2); //i:4, step:2 for (int p=0; p<count; p++) { float b = blurred.array[p] * i; float a = array[p]; array[p] = a + b + a*b; } } }*/ /*public void LossBlur (System.Func<float,float,float,float> blurFn=null, //prev, curr, next = output float intensity=0.666f, int step=1, Matrix reference=null, bool horizontal=true, bool vertical=true) { Coord min = rect.Min; Coord max = rect.Max; if (reference==null) reference = this; int lastX = max.x-1; int lastZ = max.z-1; if (horizontal) for (int z=min.z; z<=lastZ; z++) { float next = reference[min.x,z]; float curr = next; float prev = next; float blurred = next; float lastBlurred = next; for (int x=min.x+step; x<=lastX; x+=step) { //blurring if (blurFn==null) blurred = (prev+next)/2f; else blurred = blurFn(prev, curr, next); blurred = curr*(1-intensity) + blurred*intensity; //shifting values prev = curr; //this[x,z]; curr = next; //this[x+step,z]; try { next = reference[x+step*2,z]; } //this[x+step*2,z]; catch { next = reference[lastX,z]; } //filling between-steps distance if (step==1) this[x,z] = blurred; else for (int i=0; i<step; i++) { float percent = 1f * i / step; this[x-step+i,z] = blurred*percent + lastBlurred*(1-percent); } lastBlurred = blurred; } } if (vertical) for (int x=min.x; x<=lastX; x++) { float next = reference[x,min.z]; float curr = next; float prev = next; float blurred = next; float lastBlurred = next; for (int z=min.z+step; z<=lastZ; z+=step) { //blurring if (blurFn==null) blurred = (prev+next)/2f; else blurred = blurFn(prev, curr, next); blurred = curr*(1-intensity) + blurred*intensity; //shifting values prev = curr; curr = next; try { next = reference[x,z+step*2]; } catch { next = reference[x,lastZ]; } //filling between-steps distance if (step==1) this[x,z] = blurred; else for (int i=0; i<step; i++) { float percent = 1f * i / step; this[x,z-step+i] = blurred*percent + lastBlurred*(1-percent); } lastBlurred = blurred; } } }*/ #endregion #endregion #region Other /*public float GetOnWorldRect (Vector2 worldPos, Rect worldRect) { float relativeX = (worldPos.x - worldRect.x) / worldRect.width; float relativeZ = (worldPos.y - worldRect.y) / worldRect.height; int posX = Mathf.RoundToInt( relativeX*rect.size.x + rect.offset.x ); int posZ = Mathf.RoundToInt( relativeZ*rect.size.z + rect.offset.z ); posX = Mathf.Clamp(posX,rect.Min.x+1,rect.Max.x-1); posZ = Mathf.Clamp(posZ,rect.Min.z+1,rect.Max.z-1); return this[posX,posZ]; }*/ static public void BlendLayers (Matrix[] matrices, float[] opacity=null) //changes splatmaps in photoshop layered style so their summary value does not exceed 1 { //finding any existing matrix int anyMatrixNum = -1; for (int i=0; i<matrices.Length; i++) if (matrices[i]!=null) { anyMatrixNum = i; break; } if (anyMatrixNum == -1) { Debug.LogError("No matrices were found to blend " + matrices.Length); return; } //finding rect CoordRect rect = matrices[anyMatrixNum].rect; //checking rect size #if WDEBUG for (int i=0; i<matrices.Length; i++) if (matrices[i]!=null && matrices[i].rect!=rect) { Debug.LogError("Matrix rect mismatch " + rect + " " + matrices[i].rect); return; } #endif int rectCount = rect.Count; for (int pos=0; pos<rectCount; pos++) { float sum = 0; for (int i=matrices.Length-1; i>=0; i--) //layer 0 is background, layer Length-1 is the top one { if (matrices[i] == null) continue; float val = matrices[i].array[pos]; if (opacity != null) val *= opacity[i]; float overly = sum + val - 1; if (overly < 0) overly = 0; //faster then calling Math.Clamp if (overly > 1) overly = 1; matrices[i].array[pos] = val - overly; sum += val - overly; } } }
public void Deploy(CoordRect[] createRects, CoordRect[] removeRects, object parent = null, bool allowMove = true) { //it would be easier to create new grid and fill it then, but Dictionary <int, T> dstGrid = new Dictionary <int, T>(); Dictionary <int, T> srcGrid = new Dictionary <int, T>(); //no change should be made in original grid because of multithreading foreach (KeyValuePair <int, T> kvp in grid) { srcGrid.Add(kvp.Key, kvp.Value); } //adding pinned objs List <T> pinnedObjs = new List <T>(); foreach (KeyValuePair <int, T> kvp in srcGrid) { T obj = kvp.Value; if (obj.pinned) { pinnedObjs.Add(obj); } } int pinnedObjsCount = pinnedObjs.Count; for (int i = 0; i < pinnedObjsCount; i++) { T obj = pinnedObjs[i]; //hash int aax = obj.coord.x >= 0? obj.coord.x:-obj.coord.x; int aaz = obj.coord.z >= 0? obj.coord.z :-obj.coord.z; int hash = (obj.coord.x >= 0? 0x40000000:0) | (obj.coord.z >= 0? 0x20000000:0) | ((aax & 0x3FFF) << 14) | (aaz & 0x3FFF); //copy from src to dst dstGrid.Add(hash, obj); srcGrid.Remove(hash); } //adding objects within remove rect for (int r = 0; r < removeRects.Length; r++) { CoordRect rect = removeRects[r]; Coord min = rect.Min; Coord max = rect.Max; for (int bx = min.x; bx < max.x; bx++) { for (int bz = min.z; bz < max.z; bz++) { //hash int aax = bx >= 0? bx:-bx; int aaz = bz >= 0? bz :-bz; int hash = (bx >= 0? 0x40000000:0) | (bz >= 0? 0x20000000:0) | ((aax & 0x3FFF) << 14) | (aaz & 0x3FFF); //adding to new grid if (srcGrid.ContainsKey(hash)) { T obj = srcGrid[hash]; if (obj != null && !obj.Equals(null)) { dstGrid.Add(hash, obj); } srcGrid.Remove(hash); } } } } //filling create rects empty areas with unused (or new) objects for (int r = 0; r < createRects.Length; r++) { //CoordRect rect = createRects[r]; //Coord center = rect.Center; //foreach (Coord c in center.DistanceArea(rect)) CoordRect rect = createRects[r]; Coord min = rect.Min; Coord max = rect.Max; for (int bx = min.x; bx < max.x; bx++) { for (int bz = min.z; bz < max.z; bz++) { //hash int aax = bx >= 0? bx:-bx; int aaz = bz >= 0? bz :-bz; int hash = (bx >= 0? 0x40000000:0) | (bz >= 0? 0x20000000:0) | ((aax & 0x3FFF) << 14) | (aaz & 0x3FFF); if (dstGrid.ContainsKey(hash)) { continue; } //moving if (srcGrid.Count != 0 && allowMove) { KeyValuePair <int, T> first = srcGrid.First(); T obj = first.Value; srcGrid.Remove(first.Key); Coord oldCoord = obj.coord; obj.coord = new Coord(bx, bz); //obj.rect = new CoordRect(bx*cellRes, bz*cellRes, cellRes, cellRes); //obj.pos = new Rect(bx*cellSize, bz*cellSize, cellSize, cellSize); obj.hash = hash; obj.OnMove(oldCoord, obj.coord); dstGrid.Add(hash, obj); } //creating else { T obj = defaultObj; obj.coord = new Coord(bx, bz); //obj.rect = new CoordRect(bx*cellRes, bz*cellRes, cellRes, cellRes); //obj.pos = new Rect(bx*cellSize, bz*cellSize, cellSize, cellSize); obj.hash = hash; obj.OnCreate(parent); dstGrid.Add(hash, obj); } } } } //calling pre-remove fn on all other objs left foreach (KeyValuePair <int, T> kvp in srcGrid) { kvp.Value.OnRemove(); } //assigning new grid and deployed rects lock (grid) { grid = dstGrid; deployedRects = new CoordRect[createRects.Length]; for (int i = 0; i < deployedRects.Length; i++) { deployedRects[i] = createRects[i]; } } }
public void Deploy(CoordRect createRect, CoordRect removeRect, object parent = null, bool allowMove = true) { Deploy(new CoordRect[] { createRect }, new CoordRect[] { removeRect }, parent, allowMove); }
public void OnMove(Coord oldCoord, Coord newCoord) { rect = new CoordRect(coord.x * voxeland.chunkSize, coord.z * voxeland.chunkSize, voxeland.chunkSize, voxeland.chunkSize); transform.localPosition = rect.offset.vector3; gameObject.name = voxeland.chunkName + " " + coord.x + "," + coord.z; string coordString = "(" + coord.x + "," + coord.z + ")"; if (meshWorker != null) { meshWorker.Stop(); meshWorker.name = "Chunk " + coordString; meshWorker.tag = "VoxelandChunk " + coordString; } if (ambientWorker != null) { ambientWorker.Stop(); ambientWorker.name = "Ambient " + coordString; ambientWorker.tag = "VoxelandChunk " + coordString; } if (objectsWorker != null) { objectsWorker.Stop(); objectsWorker.name = "Objects " + coordString; objectsWorker.tag = "VoxelandChunk " + coordString; } if (colliderApplier != null) { colliderApplier.Stop(); colliderApplier.name = "Collider " + coordString; colliderApplier.tag = "VoxelandChunk " + coordString; } if (voxeland.guiHideWireframe) { transform.ToggleDisplayWireframe(false); } meshRenderer.enabled = false; voxeland.CallOnChunkVisibilityChanged(this, false); meshRequired = false; colliderRequired = false; objectsRequired = false; //copy layer, tag, scripts from to chunks if (voxeland.copyLayersTags) { GameObject go = gameObject; go.layer = voxeland.gameObject.layer; go.isStatic = voxeland.gameObject.isStatic; try { go.tag = voxeland.gameObject.tag; } catch { Debug.LogError("Voxeland: could not copy object tag"); } } if (voxeland.copyComponents) { GameObject go = gameObject; MonoBehaviour[] components = voxeland.GetComponents <MonoBehaviour>(); for (int i = 0; i < components.Length; i++) { if (components[i] is Voxeland || components[i] == null) { continue; //if Voxeland itself or script not assigned } if (gameObject.GetComponent(components[i].GetType()) == null) { ReflectionExtensions.CopyComponent(components[i], go); } } } ClearAll(); }
public void InitWorkers() { //sequence: //- generate area - mesh thread - mesh apply \ (force amb.ap.) // \ ambient thread / - ambient apply // \ collider apply //checking workers if (!meshWorker.initialized) { meshWorker.Calculate += CalculateMesh; meshWorker.Apply += ApplyMesh; meshWorker.threadCondition = delegate() { //checking if area is generated CoordRect areasRect = CoordRect.PickIntersectingCells(rect.Expanded(voxeland.meshMargin + 1), voxeland.data.areaSize); foreach (Data.Area area in voxeland.data.areas.WithinRect(areasRect, skipMissing:false)) { if (area == null || !area.generateWorker.ready) { return(false); } } return(true); }; meshWorker.applyCondition = delegate() { //applies mesh only when ambient is calculated return(ambientWorker.calculated); }; } if (!ambientWorker.initialized) { ambientWorker.Calculate += CalculateAmbient; ambientWorker.Apply += ApplyAmbient; ambientWorker.threadCondition = delegate() { //checking if area is generated CoordRect areasRect = CoordRect.PickIntersectingCells(rect.Expanded(voxeland.meshMargin + 1), voxeland.data.areaSize); foreach (Data.Area area in voxeland.data.areas.WithinRect(areasRect, skipMissing:false)) { if (area == null || !area.generateWorker.ready) { return(false); } } return(true); }; ambientWorker.applyCondition = delegate() { //checking if mesh is built return(meshWorker.ready && !meshWorker.processing); //condition is ignored when ambient is forced to apply in mesh }; } if (!colliderApplier.initialized) { colliderApplier.Apply += delegate() { if (colliderApplier.stop || this == null) { return; } //meshCollider.sharedMesh = null; //needs to be reset only when previous mesh was empty meshCollider.sharedMesh = loMesh; colliderIndexToCoord = indexToCoord; voxeland.prevCoordReseted = true; }; colliderApplier.applyCondition = delegate() { if (this == null || colliderApplier.stop) { return(true); } return(meshWorker.ready); }; } if (!objectsWorker.initialized) { objectsWorker.Apply += ApplyObjects; } }
public static void SettleMudflow(float[] heights, float[] mudflow, int[] order, CoordRect rect = new CoordRect(), float ruffle = 0.1f) { //int seed = 12345; for (int j = heights.Length - 1; j >= 0; j--) { //writing heights heights[j] += mudflow[j]; /*seed = 214013*seed + 2531011; * float random = ((seed>>16)&0x7FFF) / 32768f; * * int pos = order[j]; * if (pos<0) continue; * * //float[] m = heights; int sizeX = rect.size.x; * //float h = m[pos]; float hx = m[pos-1]; float hX = m[pos+1]; float hz = m[pos-sizeX]; float hZ = m[pos+sizeX]; * Cross height = new Cross(heights, pos, rect.size.x); * * //smoothing sediments a bit * float s = mudflow[pos]; * if (s > 0.0001f) * { * float smooth = s/2f; if (smooth > 0.75f) smooth = 0.75f; * heights[pos] = heights[pos]*(1-smooth) + height.AvgSides()*smooth; * } * * else * { * float maxHeight = height.MaxSides(); * float minHeight = height.MinSides(); * float randomHeight = random*(maxHeight-minHeight) + minHeight; * // heights[pos] = heights[pos]*(1-ruffle) + randomHeight*ruffle; * }*/ } }
public static void TransferMudflow(float[] heights, float[] mudflow, float[] sediments, int[] order, CoordRect rect = new CoordRect(), int erosionFluidityIterations = 3) { for (int i = 0; i < sediments.Length; i++) { sediments[i] = 0; } #region Settling sediment for (int l = 0; l < erosionFluidityIterations; l++) { for (int j = heights.Length - 1; j >= 0; j--) { //finding column ordered by height int pos = order[j]; if (pos < 0) { continue; } Cross height = new Cross(heights, pos, rect.size.x); Cross sediment = new Cross(mudflow, pos, rect.size.x); float sedimentSum = sediment.Sum(); if (sedimentSum < 0.00001f) { continue; } Cross pour = Cross.Pour(height, sedimentSum); pour.SetToMatrix(mudflow, pos, rect.size.x); if (sediments != null) { pour.AddToMatrix(sediments, pos, rect.size.x); } } } //for (int i=0; i<heights.Length; i++) // if (float.IsNaN(heights[i])) Debug.Log("NaN"); #endregion }
public static void ErosionRef(float[] heights, float[] torrents, float[] mudflow, int[] order, CoordRect rect = new CoordRect(), float erosionDurability = 0.9f, float erosionAmount = 1f, float sedimentAmount = 0.5f) { for (int i = 0; i < mudflow.Length; i++) { mudflow[i] = 0; } for (int j = heights.Length - 1; j >= 0; j--) { //finding column ordered by height int pos = order[j]; if (pos < 0) { continue; } Cross height = new Cross(heights, pos, rect.size.x); float h_min = height.Min(); //getting height values // float[] m = heights; int i=pos; int sizeX = rect.size.x; // float h = m[i]; float hx = m[i-1]; float hX = m[i+1]; float hz = m[i-sizeX]; float hZ = m[i+sizeX]; //height minimum // float h_min = h; // if (hx<h_min) h_min=hx; if (hX<h_min) h_min=hX; if (hz<h_min) h_min=hz; if (hZ<h_min) h_min=hZ; //erosion line float erodeLine = (heights[pos] + h_min) / 2f; //halfway between current and maximum height if (heights[pos] < erodeLine) { continue; } //raising soil float raised = heights[pos] - erodeLine; float maxRaised = raised * (torrents[pos] - 1) * (1 - erosionDurability); if (raised > maxRaised) { raised = maxRaised; } raised *= erosionAmount; //saving arrays heights[pos] -= raised; mudflow[pos] += raised * sedimentAmount; //if (erosion != null) erosion.array[pos] += raised; //and writing to ref } //for (int i=0; i<heights.Length; i++) // if (float.IsNaN(heights[i])) Debug.Log("NaN"); }
public static void CreateTorrentsRef(float[] heights, int[] order, float[] torrents, CoordRect rect = new CoordRect()) { for (int i = 0; i < heights.Length; i++) { torrents[i] = 1; //casting initial rain } for (int j = heights.Length - 1; j >= 0; j--) { //finding column ordered by height int pos = order[j]; if (pos < 0) { continue; } MooreCross height = new MooreCross(heights, pos, rect.size.x); MooreCross torrent = new MooreCross(torrents, pos, rect.size.x); //moore if (torrent.vals[4] > 200000000) { torrent.vals[4] = 200000000; } MooreCross delta = height.vals[4] - height; delta = MooreCross.ClampMax(delta, 0); MooreCross percents = MooreCross.Zero(); float sum = delta.Sum(); if (sum > 0.00001f) { percents = delta / sum; } MooreCross newTorrent = percents * torrent.vals[4]; newTorrent.AddToMatrix(torrents, pos, rect.size.x); } }