Пример #1
0
        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);
        }
Пример #2
0
        //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);
            }
        }
Пример #3
0
			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;
			}
Пример #4
0
        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);
        }
Пример #5
0
        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
        }
Пример #6
0
 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];
     }
 }
Пример #7
0
 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];
     }
 }
Пример #8
0
        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);
            }
        }
Пример #9
0
			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;
				}
			}
Пример #10
0
        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);
                    }
                }
            }
        }
Пример #11
0
			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;
			}
Пример #12
0
			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;
			}
Пример #13
0
			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;
			}
Пример #14
0
        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);
                    }
                }
            }
        }
Пример #15
0
 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;
     }
 }
Пример #16
0
				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
					}
				}
Пример #17
0
			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();
			}
Пример #18
0
			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();
			}
Пример #19
0
			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);
			}
Пример #20
0
        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;
        }
Пример #21
0
        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);
        }
Пример #22
0
		/*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;
					}
				}
			}
Пример #23
0
        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];
                }
            }
        }
Пример #24
0
 public void Deploy(CoordRect createRect, CoordRect removeRect, object parent = null, bool allowMove = true)
 {
     Deploy(new CoordRect[] { createRect }, new CoordRect[] { removeRect }, parent, allowMove);
 }
Пример #25
0
        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();
        }
Пример #26
0
        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;
            }
        }
Пример #27
0
        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;
                 * }*/
            }
        }
Пример #28
0
        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
        }
Пример #29
0
        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");
        }
Пример #30
0
        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);
            }
        }