Example #1
0
        public override void Generate(CoordRect rect, Chunk.Results results, Chunk.Size terrainSize, int seed, Func <float, bool> stop = null)
        {
            object obj = null;

            if (input.link != null && enabled)
            {
                obj = input.GetObject(results);
            }
            else
            {
                if (type == InoutType.Map)
                {
                    obj = new Matrix(rect);
                }
                if (type == InoutType.Objects)
                {
                    obj = new SpatialHash(new Vector2(rect.offset.x, rect.offset.z), rect.size.x, 16);
                }
            }

            if (stop != null && stop(0))
            {
                return;
            }
            output.SetObject(results, obj);
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            //getting inputs
            SpatialHash objs = (SpatialHash)objsIn.GetObject(chunk);

            /*Matrix substrate = (Matrix)substrateIn.GetObject(chunk);
             *
             * //return on stop/disable/null input
             * if (chunk.stop || objs==null) return;
             * if (!enabled || substrate==null) { objsOut.SetObject(chunk, objs); return; }
             *
             * //preparing output
             * objs = objs.Copy();
             *
             * for (int c=0; c<objs.cells.Length; c++)
             * {
             *      List<SpatialObject> objList = objs.cells[c].objs;
             *      int objsCount = objList.Count;
             *      for (int i=0; i<objsCount; i++)
             *      {
             *              SpatialObject obj = objList[i];
             *              //obj.height = substrate[(int)obj.pos.x, (int)obj.pos.y];
             *              obj.height = substrate.GetInterpolatedValue(obj.pos);
             *      }
             * }
             *
             * //setting output
             * if (chunk.stop) return;*/
            objsOut.SetObject(chunk, objs);
        }
Example #3
0
        static public void DrawObjects()
        {
            foreach (Chunk.Results result in mapMagic.Results())
            {
                if (result == null || !result.results.ContainsKey(previewOutput))
                {
                    continue;
                }

                object objsBox = Preview.previewOutput.GetObject <object>(result);

                SpatialHash objs = null;
                if (objsBox is SpatialHash)
                {
                    objs = (SpatialHash)objsBox;
                }
                if (objs == null)
                {
                    continue;
                }

                float pixelSize     = GetPixelSize();
                float terrainHeight = GetTerrainHeight();

                int objsCount = objs.Count;
                foreach (SpatialObject obj in objs)
                {
                    float height = 0;
                    if (result.heights != null)
                    {
                        height = result.heights.GetInterpolated(obj.pos.x, obj.pos.y);
                    }
                    Vector3 pos = new Vector3(obj.pos.x * pixelSize, (obj.height + height) * terrainHeight, obj.pos.y * pixelSize);
                    pos += MapMagic.instance.transform.position;

                    UnityEditor.Handles.color = new Color(0.3f, 1, 0.2f, 1);
                    UnityEditor.Handles.DrawLine(pos + new Vector3(obj.size / 2f, 0, 0), pos - new Vector3(obj.size / 2f, 0, 0));
                    UnityEditor.Handles.DrawLine(pos + new Vector3(0, 0, obj.size / 2f), pos - new Vector3(0, 0, obj.size / 2f));

                    if (objsCount < 300)
                    {
                        Vector3 oldPoint = pos;
                        foreach (Vector3 point in pos.CircleAround(obj.size / 2f, objsCount < 100? 12 : 4, true))
                        {
                            UnityEditor.Handles.DrawLine(oldPoint, point);
                            oldPoint = point;
                        }
                    }

                    UnityEditor.Handles.color = new Color(0.3f, 1, 0.2f, 0.3333f);
                    UnityEditor.Handles.DrawLine(new Vector3(pos.x, 0, pos.z), new Vector3(pos.x, terrainHeight, pos.z));
                }        // in objects
            }            //foreach chunk
        }
Example #4
0
        }                                                                                               //no extend, non-generic

        public void Add(SpatialHash addHash)
        {
            if (addHash.cells.Length != cells.Length)
            {
                UnityEngine.Debug.LogError("Add SpatialHash: cell number is different"); return;
            }
            for (int c = 0; c < cells.Length; c++)
            {
                cells[c].objs.AddRange(addHash.cells[c].objs);
                Count += cells[c].objs.Count;
            }
        }
Example #5
0
        public void ChangeResolution(int newResolution)
        {
            SpatialHash newHash = new SpatialHash(offset, size, newResolution);

            foreach (SpatialObject obj in AllObjs())
            {
                newHash.Add(obj);
            }

            resolution = newResolution;
            cells      = newHash.cells;
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            // Note - it's important that we *don't* change the seed based on the chunk coordinates, or else
            // we risk generating two different points.
            InstanceRandom rnd       = new InstanceRandom(MapMagic.instance.seed + seed /* + chunk.coord.x*1000 + chunk.coord.z */);
            Vector2        candidate = new Vector2(xMin + rnd.Random() * (xMax - xMin), zMin + rnd.Random() * (zMax - zMin));

            // MM works with coordinates specified in "terrain space". If the user specifies coordinates in
            // absolute world position, need to scale these based on resolution and size of terrain before
            // adding to the spatialhash
            if (coordinateSpace == CoordinateSpace.World)
            {
                float scaleFactor = (float)MapMagic.instance.resolution / (float)MapMagic.instance.terrainSize;
                candidate *= scaleFactor;
            }

            // If the spatial hash for this chunk does not contain the candidate point, simply return the default
            // spatial hash
            if (
                spatialHash.offset.x + spatialHash.size <= candidate.x || /* candidate point lies too far to the right */
                spatialHash.offset.x > candidate.x || /* candidate point lies too far to the left */
                spatialHash.offset.y + spatialHash.size <= candidate.y || /* candidate point lies too far forward */
                spatialHash.offset.y > candidate.y    /* candidate point lies too far backward */
                )
            {
                output.SetObject(chunk, spatialHash);
                return;
            }
            // If the candidate lies within this chunk's bounds, add it to the hash
            else
            {
                spatialHash.Add(candidate, 0, 0, 1);
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }
Example #7
0
			public void Purge ()
			{
				HeightOutput ho = MapMagic.instance.gens.GetGenerator<HeightOutput>(); if (ho==null || !ho.enabled) HeightOutput.Purge(this);
				
				SplatOutput so = MapMagic.instance.gens.GetGenerator<SplatOutput>();
				PreviewOutput po = MapMagic.instance.gens.GetGenerator<PreviewOutput>();
				if ( (po == null || !po.enabled) && (so==null || !so.enabled) ) SplatOutput.Purge(this);
				if (po == null || !po.enabled) previewObjs = null;
				
				GrassOutput go = MapMagic.instance.gens.GetGenerator<GrassOutput>(); if (go==null || !go.enabled) GrassOutput.Purge(this);
				ObjectOutput oo = MapMagic.instance.gens.GetGenerator<ObjectOutput>(); if (oo==null || !oo.enabled) ObjectOutput.Purge(this);
				TreesOutput to = MapMagic.instance.gens.GetGenerator<TreesOutput>(); if (to==null || !to.enabled) TreesOutput.Purge(this);
				purge = false;
			}
Example #8
0
        public SpatialHash Copy()
        {
            SpatialHash result = new SpatialHash(offset, size, resolution);

            for (int i = 0; i < cells.Length; i++)
            {
                result.cells[i].min  = cells[i].min;
                result.cells[i].max  = cells[i].max;
                result.cells[i].objs = new List <SpatialObject>(cells[i].objs);

                List <SpatialObject> objs = result.cells[i].objs;
                for (int o = objs.Count - 1; o >= 0; o--)
                {
                    objs[o] = objs[o].Copy();
                }
            }
            result.Count = Count;
            return(result);
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            // Note that spacing is specified in terms of the resolution of the terrain.
            // The *world spacing* will be equal to the spacing specified here / the terrain size * terrain resolution
            for (float z = zOffset; z < spatialHash.size; z += zSpacing)
            {
                for (float x = xOffset; x < spatialHash.size; x += xSpacing)
                {
                    Vector2 candidate = new Vector2((spatialHash.offset.x + x), (spatialHash.offset.y + z));
                    spatialHash.Add(candidate, 0, 0, 1); //adding only if some suitable candidate found
                    if (xSpacing == 0)
                    {
                        break;
                    }
                }
                if (zSpacing == 0)
                {
                    break;
                }
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }
Example #10
0
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if VOXELAND
            if (stop != null && stop(0))
            {
                return;
            }
            if (voxeland == null)
            {
                return;
            }

            //TODO get height factor
            int heightFactor = 200;

            //finding area by rect offset
            Coord areaCoord          = Coord.PickCell(rect.offset.x, rect.offset.z, voxeland.data.areaSize);
            Voxeland5.Data.Area area = voxeland.data.areas[areaCoord.x, areaCoord.z];

            //clearing objects
            area.ClearObjects();

            //preparing random
            Noise noise = new Noise(12345);             //to disable biome objects

            //processing
            foreach (VoxelandObjectsOutput gen in gens.GeneratorsOfType <VoxelandObjectsOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //reading output directly
                //Output output = gen.areaOutput;
                if (stop != null && stop(0))
                {
                    return;                                        //checking stop before reading output
                }
                //if (!results.results.ContainsKey(output)) continue;
                //Voxeland5.Data.Area genArea = (Voxeland5.Data.Area)results.results[output];

                //loading biome matrix
                Matrix biomeMask = null;
                if (gen.biome != null)
                {
                    object biomeMaskObj = gen.biome.mask.GetObject(results);
                    if (biomeMaskObj == null)
                    {
                        continue;                                         //adding nothing if biome has no mask
                    }
                    biomeMask = (Matrix)biomeMaskObj;
                    if (biomeMask == null)
                    {
                        continue;
                    }
                    if (biomeMask.IsEmpty())
                    {
                        continue;                                          //optimizing empty biomes
                    }
                }

                //iterating layers
                for (int l = 0; l < gen.layers.Length; l++)
                {
                    Layer layer = gen.layers[l];

                    //loading inputs
                    SpatialHash src = (SpatialHash)layer.input.GetObject(results);
                    if (src == null)
                    {
                        continue;
                    }

                    foreach (SpatialObject obj in src.AllObjs())
                    {
                        int objX = (int)(obj.pos.x + 0.5f);
                        int objZ = (int)(obj.pos.y + 0.5f);

                        //biome masking
                        float biomeVal = 1;
                        if (gen.biome != null)
                        {
                            if (biomeMask == null)
                            {
                                biomeVal = 0;
                            }
                            else
                            {
                                biomeVal = biomeMask[objX, objZ];
                            }
                        }
                        if (biomeVal < noise.Random(objX, objZ))
                        {
                            continue;
                        }

                        //flooring
                        float terrainHeight = layer.relativeHeight? results.heights[objX, objZ] : 0;
                        int   objHeight     = (int)((obj.height + terrainHeight) * heightFactor + 0.5f);

                        //area.AddObject(new CoordDir(objX, objHeight, objZ), (short)l);
                        area.AddObject(objX, objHeight, objZ, 0, (short)l);
                    }
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VoxelandOutput), null, replace: true);
                        #endif
        }
Example #11
0
        void OnGUI()
        {
            //updating layouts
            if (baseLayout == null)
            {
                baseLayout = new Layout();
            }
            baseLayout.maxZoom = 8; baseLayout.minZoom = 0.125f; baseLayout.zoomStep = 0.125f;
            baseLayout.Zoom(); baseLayout.Scroll();                     //scrolling and zooming

            if (infoLayout == null)
            {
                infoLayout = new Layout();
            }
            infoLayout.cursor = new Rect();
            infoLayout.margin = 10; infoLayout.rightMargin = 10;
            infoLayout.field  = new Rect(this.position.width - 200 - 10, this.position.height - 100 - 10, 200, 100);

            //no output exit
            if (Preview.previewOutput == null)
            {
                baseLayout.Label("No preview output is selected"); return;
            }


            //drawing main object
            //TODO: preview all of the textures in window
            int counter = 0;

            foreach (Chunk.Results result in Preview.mapMagic.Results())
            {
                //displaing currently selected chunk
                if (counter != displayedObjectNum)
                {
                    counter++; continue;
                }

                //no object
                if (result == null)
                {
                    baseLayout.Label("Please wait until preview \nresult is being generated."); return;
                }
                object previewBox = Preview.previewOutput.GetObject <object>(result);
                if (previewBox == null)
                {
                    baseLayout.Label("Please wait until preview \nobject is being generated."); return;
                }

                //displaying matrix
                if (Preview.previewOutput.type == Generator.InoutType.Map)
                {
                    //refreshing matrices if needed
                    if (Preview.RefreshMatricesNeeded())
                    {
                        Preview.RefreshMatrices(range.x, range.y);
                    }

                    //finding matrix and texture
                    Matrix    matrix  = (Matrix)previewBox;
                    Texture2D texture = Preview.matrices[matrix];

                    //drawing texture
                    EditorGUI.DrawPreviewTexture(baseLayout.ToDisplay(new Rect(0, 0, texture.width, texture.height)), texture);

                    //drawing texture info

                    UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                    UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                    infoLayout.Par(2);
                    infoLayout.Field(ref displayedObjectNum, "Tile number", fieldSize: 0.3f);
                    infoLayout.fieldSize = 0.7f;                             //infoLayout.inputSize = 0.3f;
                    infoLayout.Label("Size: " + texture.width + "x" + texture.height);
                    infoLayout.Field(ref baseLayout.zoom, "Zoom: ", min: baseLayout.minZoom, max: baseLayout.maxZoom, slider: true, quadratic: true);

                    infoLayout.Field(ref range, "Range: ", min: 0, max: 1, slider: true);
                    if (infoLayout.lastChange)
                    {
                        Preview.RefreshMatrices(range.x, range.y);
                    }

                    infoLayout.Par(3);
                    if (infoLayout.Button("Save To Texture"))
                    {
                                                        #if !UNITY_WEBPLAYER //you cannot get access to files for web player platform. Even for an editor. Seems to be Unity bug.
                        string path = UnityEditor.EditorUtility.SaveFilePanel(
                            "Save Output Texture",
                            "Assets",
                            "OutputTexture.png",
                            "png");
                        if (path != null && path.Length != 0)
                        {
                            byte[] bytes = texture.EncodeToPNG();
                            System.IO.File.WriteAllBytes(path, bytes);
                        }
                                                        #endif
                    }
                }

                else if (Preview.previewOutput.type == Generator.InoutType.Objects)
                {
                    SpatialHash spatialHash = (SpatialHash)previewBox;

                    for (int i = 0; i < spatialHash.cells.Length; i++)
                    {
                        SpatialHash.Cell cell = spatialHash.cells[i];

                        //drawing grid
                        UnityEditor.Handles.color = new Color(0.6f, 0.6f, 0.6f);                                 //TODO: meight be too light in pro skin
                        UnityEditor.Handles.DrawPolyLine(
                            baseLayout.ToDisplay((cell.min - spatialHash.offset) / spatialHash.size * 1000),
                            baseLayout.ToDisplay((new Vector2(cell.max.x, cell.min.y) - spatialHash.offset) / spatialHash.size * 1000),
                            baseLayout.ToDisplay((cell.max - spatialHash.offset) / spatialHash.size * 1000),
                            baseLayout.ToDisplay((new Vector2(cell.min.x, cell.max.y) - spatialHash.offset) / spatialHash.size * 1000),
                            baseLayout.ToDisplay((cell.min - spatialHash.offset) / spatialHash.size * 1000));

                        //drawing objects


                        UnityEditor.Handles.color = new Color(0.3f, 0.5f, 0.1f);
                        for (int j = 0; j < cell.objs.Count; j++)
                        {
                            Vector2 pos    = baseLayout.ToDisplay((cell.objs[j].pos - spatialHash.offset) / spatialHash.size * 1000);
                            float   radius = cell.objs[j].size * baseLayout.zoom / 2;
                            if (radius < 3)
                            {
                                radius = 3;
                            }

                            UnityEditor.Handles.DrawAAConvexPolygon(
                                pos + new Vector2(0, 1) * radius,
                                pos + new Vector2(0.71f, 0.71f) * radius,
                                pos + new Vector2(1, 0) * radius,
                                pos + new Vector2(0.71f, -0.71f) * radius,
                                pos + new Vector2(0, -1) * radius,
                                pos + new Vector2(-0.71f, -0.71f) * radius,
                                pos + new Vector2(-1, 0) * radius,
                                pos + new Vector2(-0.71f, 0.71f) * radius);
                        }
                    }

                    //drawing info
                    UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                    UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                    infoLayout.Par();
                    infoLayout.fieldSize = 0.7f;                             //infoLayout.inputSize = 0.3f;
                    infoLayout.Label("Count: " + spatialHash.Count);
                }

                break; //no need to do anything when selected chunk showed
            }          //foreach in results
        }              //OnGUI
Example #12
0
        void OnGUI()
        {
            //finding the preiew object
            if (mapMagic == null)
            {
                mapMagic = FindObjectOfType <MapMagic>();
            }
            if (mapMagic == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "No MapMagic object found, re-open the window."); return;
            }

            Vector3 camPos = new Vector3();

            if (UnityEditor.SceneView.lastActiveSceneView != null)
            {
                camPos = UnityEditor.SceneView.lastActiveSceneView.camera.transform.position;
            }

            Chunk.Results closestResults = mapMagic.ClosestResults(camPos);
            if (closestResults == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "No terrains are pinned for preview"); return;
            }

            if (Preview.previewOutput == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "No preview output is selected"); return;
            }

            object currentObj = Preview.previewOutput.GetObject <object>(closestResults);

            if (currentObj == null)
            {
                EditorGUI.LabelField(new Rect(10, 10, 200, 200), "Please wait until preview \nobject is being generated."); return;
            }

            if (currentObj != lastUsedObject)
            {
                Repaint();
            }

            //updating layouts
            if (baseLayout == null)
            {
                baseLayout = new Layout();
            }
            baseLayout.maxZoom = 8; baseLayout.minZoom = 0.125f; baseLayout.zoomStep = 0.125f;
            baseLayout.Zoom(); baseLayout.Scroll();                     //scrolling and zooming

            if (infoLayout == null)
            {
                infoLayout = new Layout();
            }
            infoLayout.cursor = new Rect();
            infoLayout.margin = 10; infoLayout.rightMargin = 10;
            infoLayout.field  = new Rect(this.position.width - 200 - 10, this.position.height - 80 - 10, 200, 80);



            //drawing hash preview
            if (currentObj is SpatialHash)
            {
                SpatialHash spatialHash = (SpatialHash)currentObj;

                for (int i = 0; i < spatialHash.cells.Length; i++)
                {
                    SpatialHash.Cell cell = spatialHash.cells[i];

                    //drawing grid
                    UnityEditor.Handles.color = Color.gray;
                    UnityEditor.Handles.DrawPolyLine(
                        baseLayout.ToDisplay((cell.min - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((new Vector2(cell.max.x, cell.min.y) - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((cell.max - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((new Vector2(cell.min.x, cell.max.y) - spatialHash.offset) / spatialHash.size * 1000),
                        baseLayout.ToDisplay((cell.min - spatialHash.offset) / spatialHash.size * 1000));

                    //drawing objects
                    UnityEditor.Handles.color = new Color(0.4f, 0.9f, 0.2f);
                    for (int j = 0; j < cell.objs.Count; j++)
                    {
                        DrawCircle(baseLayout.ToDisplay((cell.objs[j].pos - spatialHash.offset) / spatialHash.size * 1000), 5);
                    }
                }

                //drawing info
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                infoLayout.Par();
                infoLayout.fieldSize = 0.7f;                         //infoLayout.inputSize = 0.3f;
                infoLayout.Label("Count: " + spatialHash.Count);
            }

            //drawing matrix preview
            else if (currentObj is Matrix)
            {
                Matrix matrix = (Matrix)currentObj;

                //refreshing texture if matrix has changed
                if (matrix != lastUsedObject || (range - lastUsedRange).sqrMagnitude > 0.01f)
                {
                    lastUsedObject     = matrix; lastUsedRange = range;
                    texture            = new Texture2D(matrix.rect.size.x, matrix.rect.size.z);
                    texture.filterMode = FilterMode.Point;
                    matrix.SimpleToTexture(texture, rangeMin: range.x, rangeMax: range.y);
                }

                //drawing texture
                UnityEditor.EditorGUI.DrawPreviewTexture(baseLayout.ToDisplay(new Rect(0, 0, texture.width, texture.height)), texture);

                //drawing texture info
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                UnityEditor.EditorGUI.HelpBox(infoLayout.field, "", UnityEditor.MessageType.None);
                infoLayout.fieldSize = 0.7f;                         //infoLayout.inputSize = 0.3f;
                infoLayout.Label("Size: " + texture.width + "x" + texture.height);
                infoLayout.Field(ref baseLayout.zoom, "Zoom: ", min: baseLayout.minZoom, max: baseLayout.maxZoom, slider: true, quadratic: true);
                if (matrix != null)
                {
                    infoLayout.Field(ref range, "Range: ", min: 0, max: 1, slider: true);

                    infoLayout.Par(3);
                    if (infoLayout.Button("Save To Texture"))
                    {
                                                        #if !UNITY_WEBPLAYER
                        string path = UnityEditor.EditorUtility.SaveFilePanel(
                            "Save Output Texture",
                            "Assets",
                            "OutputTexture.png",
                            "png");
                        if (path != null && path.Length != 0)
                        {
                            byte[] bytes = texture.EncodeToPNG();
                            System.IO.File.WriteAllBytes(path, bytes);
                        }
                                                        #endif
                    }
                }
            }
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            //getting inputs
            SpatialHash minuend    = (SpatialHash)minuendIn.GetObject(chunk);
            SpatialHash subtrahend = (SpatialHash)subtrahendIn.GetObject(chunk);

            //return on stop/disable/null input
            if (chunk.stop || minuend == null)
            {
                return;
            }
            if (!enabled || subtrahend == null || subtrahend.Count == 0)
            {
                minuendOut.SetObject(chunk, minuend); return;
            }

            //preparing output
            SpatialHash result = new SpatialHash(minuend.offset, minuend.size, minuend.resolution);

            //transforming distance to map-space
            float dist = distance / MapMagic.instance.terrainSize * MapMagic.instance.resolution;

            //finding maximum seek distance
            float maxObjSize = 0;

            foreach (SpatialObject obj in subtrahend.AllObjs())
            {
                if (obj.size > maxObjSize)
                {
                    maxObjSize = obj.size;
                }
            }
            maxObjSize = maxObjSize / MapMagic.instance.terrainSize * MapMagic.instance.resolution;             //transforming to map-space
            float maxDist = dist * (1 - sizeFactor) + dist * maxObjSize * sizeFactor;

            foreach (SpatialObject obj in minuend.AllObjs())
            {
                bool inRange = false;

                foreach (SpatialObject closeObj in subtrahend.ObjsInRange(obj.pos, maxDist))
                {
                    float minDist = (obj.pos - closeObj.pos).magnitude;
                    if (minDist < dist * (1 - sizeFactor) + dist * closeObj.size * sizeFactor)
                    {
                        inRange = true; break;
                    }
                }

                if (!inRange)
                {
                    result.Add(obj);
                }

                //SpatialObject closestObj = subtrahend.Closest(obj.pos,false);
                //float minDist = (obj.pos - closestObj.pos).magnitude;

                //if (minDist > dist*(1-sizeFactor) + dist*closestObj.size*sizeFactor) result.Add(obj);
            }

            //setting output
            if (chunk.stop)
            {
                return;
            }
            minuendOut.SetObject(chunk, result);
        }
        public static void Process(CoordRect rect, Chunk.Results results, GeneratorsAsset gens, Chunk.Size terrainSize, Func <float, bool> stop = null)
        {
                        #if VEGETATION_STUDIO
            if (stop != null && stop(0))
            {
                return;
            }

            //preparing and clearing storage
            if (vetStorComponents == null || vetStorComponents.Count == 0)
            {
                return;                                                                        //vs not used (process runs anyway)
            }
            PersistentVegetationStorage storage = vetStorComponents[rect];

            int cellXCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize);
            int cellZCount = Mathf.CeilToInt(terrainSize.dimensions / cellSize);

            Noise noise = new Noise(12345, permutationCount: 128);            //to pick objects based on biome


            //clearing all of the items
            foreach (VegetationStudioOutput gen in gens.GeneratorsOfType <VegetationStudioOutput>(onlyEnabled:true, checkBiomes:true))
            {
                for (int b = 0; b < gen.layers.Length; b++)
                {
                    string id = gen.package.VegetationInfoList[b].VegetationItemID;
                    storage.RemoveVegetationItemInstances(id, VS_MM_id);
                }
                break;                 //iterating in one generator only - they use the same layers
            }

            if (stop != null && stop(0))
            {
                return;
            }

            //object outputs
            foreach (VegetationStudioOutput gen in gens.GeneratorsOfType <VegetationStudioOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //gen biome mask
                Matrix biomeMask = null;
                if (gen.biome != null)
                {
                    object biomeMaskObj = gen.biome.mask.GetObject(results);
                    if (biomeMaskObj == null)
                    {
                        continue;                                           //adding nothing if biome has no mask
                    }
                    biomeMask = (Matrix)biomeMaskObj;
                    if (biomeMask == null)
                    {
                        continue;
                    }
                    if (biomeMask.IsEmpty())
                    {
                        continue;                                          //optimizing empty biomes
                    }
                }

                //iterating in layers
                for (int b = 0; b < gen.layers.Length; b++)
                {
                    if (stop != null && stop(0))
                    {
                        return;                                            //checking stop before reading output
                    }
                    Layer layer = gen.layers[b];

                    string id = gen.package.VegetationInfoList[b].VegetationItemID;


                    //objects layer
                    if (layer.type == Layer.Type.Object)
                    {
                        //loading objects from input
                        SpatialHash hash = (SpatialHash)gen.layers[b].objInput.GetObject(results);
                        if (hash == null)
                        {
                            continue;
                        }

                        //filling instances (no need to check/add key in multidict)
                        foreach (SpatialObject obj in hash.AllObjs())
                        {
                            //skipping on biome not used
                            float biomeFactor = 0;
                            if (gen.biome == null)
                            {
                                biomeFactor = 1;
                            }
                            else if (biomeMask != null)
                            {
                                biomeFactor = biomeMask.GetInterpolated(obj.pos.x, obj.pos.y);
                            }
                            if (biomeFactor < 0.00001f)
                            {
                                continue;
                            }

                            float rnd;
                            switch (biomeBlendType)
                            {
                            case ObjectOutput.BiomeBlendType.Sharp: rnd = 0.5f; break;

                            case ObjectOutput.BiomeBlendType.AdditiveRandom:
                            case ObjectOutput.BiomeBlendType.NormalizedRandom:
                                rnd = noise.Random((int)obj.pos.x, (int)obj.pos.y);
                                if (biomeFactor > 0.5f)
                                {
                                    rnd = 1 - rnd;                                                           //test
                                }
                                break;

                            case ObjectOutput.BiomeBlendType.Scale: rnd = 0.0f; break;

                            default: rnd = 0.5f; break;
                            }

                            if (biomeFactor < rnd)
                            {
                                continue;
                            }

                            //flooring
                            float terrainHeight = 0;
                            if (layer.relativeHeight && results.heights != null)                             //if checbox enabled and heights exist (at least one height generator is in the graph)
                            {
                                terrainHeight = results.heights.GetInterpolated(obj.pos.x, obj.pos.y);
                            }
                            if (terrainHeight > 1)
                            {
                                terrainHeight = 1;
                            }


                            //terrain-space object position
                            Vector3 position = new Vector3(
                                (obj.pos.x - hash.offset.x) / hash.size * terrainSize.dimensions,
                                (obj.height + terrainHeight) * terrainSize.height,
                                (obj.pos.y - hash.offset.y) / hash.size * terrainSize.dimensions);

                            //cell number
                            int cx = (int)(position.x / cellSize);
                            int cz = (int)(position.z / cellSize);
                            PersistentVegetationCell cell = storage.PersistentVegetationStoragePackage.PersistentVegetationCellList[cz + cx * cellXCount];

                            //rotation + taking terrain normal
                            Quaternion rotation;
                            float      objRotation = layer.rotate ? obj.rotation % 360 : 0;
                            if (layer.takeTerrainNormal)
                            {
                                Vector3 terrainNormal = ObjectOutput.GetTerrainNormal(obj.pos.x, obj.pos.y, results.heights, terrainSize.height, terrainSize.pixelSize);
                                Vector3 sideVector    = new Vector3(Mathf.Sin((obj.rotation + 90) * Mathf.Deg2Rad), 0, Mathf.Cos((obj.rotation + 90) * Mathf.Deg2Rad));
                                Vector3 frontVector   = Vector3.Cross(sideVector, terrainNormal);
                                rotation = Quaternion.LookRotation(frontVector, terrainNormal);
                            }
                            else
                            {
                                rotation = objRotation.EulerToQuat();
                            }

                            //scale + biome scale mode
                            Vector3 scale = layer.scale ? new Vector3(layer.scaleY ? 1 : obj.size, obj.size, layer.scaleY ? 1 : obj.size) : Vector3.one;

                            if (biomeBlendType == ObjectOutput.BiomeBlendType.Scale && gen.biome != null)
                            {
                                float biomeVal = 1;
                                if (biomeMask != null)
                                {
                                    biomeVal = biomeMask[obj.pos];
                                }
                                if (biomeVal < 0.001f)
                                {
                                    continue;                                                     //skip zero-scaled objects
                                }
                                scale *= biomeVal;
                            }

                            //storage.AddVegetationItemInstance(id, position, scale, rotation, layer.applyMeshRotation, VS_MM_id, true);
                            cell.AddVegetationItemInstance(id, position, scale, rotation, VS_MM_id);
                        }

                        if (stop != null && stop(0))
                        {
                            return;
                        }
                    }


                    //map outputs
                    if (layer.type == Layer.Type.Map)
                    {
                        //reading output directly
                        //Output output = gen.layers[b].output;
                        //if (stop!=null && stop(0)) return; //checking stop before reading output
                        //if (!results.results.ContainsKey(output)) continue;
                        //Matrix matrix = (Matrix)results.results[output];

                        //loading from input
                        if (stop != null && stop(0))
                        {
                            return;
                        }
                        Matrix matrix = (Matrix)gen.layers[b].mapInput.GetObject(results);
                        if (matrix == null)
                        {
                            continue;
                        }
                        Matrix heights = results.heights;                         //get heights before the chunk is removed

                        //setting bush by bush using the sample dist
                        float sampleDist = 1f / layer.density;

                        //filling
                        float terrainPosX = 1f * rect.offset.x / terrainSize.resolution * terrainSize.dimensions;
                        float terrainPosZ = 1f * rect.offset.z / terrainSize.resolution * terrainSize.dimensions;



                        for (int cx = 0; cx <= cellXCount - 1; cx++)
                        {
                            for (int cz = 0; cz <= cellZCount - 1; cz++)
                            {
                                Vector3 cellCorner            = new Vector3(terrainPosX + (cellSize * cx), 0, terrainPosZ + (cellSize * cz));
                                PersistentVegetationCell cell = storage.PersistentVegetationStoragePackage.PersistentVegetationCellList[cz + cx * cellXCount];

                                for (float x = 0; x < cellSize; x += sampleDist)
                                {
                                    for (float z = 0; z < cellSize; z += sampleDist)
                                    {
                                        //world position
                                        float wx = cellSize * cx + x;
                                        float wz = cellSize * cz + z;

                                        //randomizing position
                                        wx += noise.Random((int)(wx * 10), (int)(wz * 10), 2) * sampleDist - sampleDist / 2;
                                        wz += noise.Random((int)(wx * 10), (int)(wz * 10), 3) * sampleDist - sampleDist / 2;

                                        //map position
                                        float mx = wx / terrainSize.dimensions * rect.size.x + rect.offset.x;                                    // relative (0-1) position * terrain res
                                        float mz = wz / terrainSize.dimensions * rect.size.z + rect.offset.z;

                                        float val = matrix.GetInterpolated(mx, mz);

                                        float biomeFactor = 0;
                                        if (gen.biome == null)
                                        {
                                            biomeFactor = 1;
                                        }
                                        else if (biomeMask != null)
                                        {
                                            biomeFactor = biomeMask.GetInterpolated(mx, mz);
                                        }

                                        //placing object
                                        float rnd = (noise.Random((int)(wx * 10), (int)(wz * 10)));
                                        if (rnd < val * biomeFactor)
                                        {
                                            float terrainHeight = heights.GetInterpolated(mx, mz) * terrainSize.height;

                                            //rotation + taking terrain normal
                                            Quaternion rotation;
                                            float      rotRnd      = noise.Random((int)(wx * 10), (int)(wz * 10), 1);
                                            float      objRotation = layer.rotate ? rotRnd * 360 : 0;
                                            if (layer.takeTerrainNormal)
                                            {
                                                Vector3 terrainNormal = ObjectOutput.GetTerrainNormal(mx, mz, heights, terrainSize.height, terrainSize.pixelSize);
                                                Vector3 sideVector    = new Vector3(Mathf.Sin((objRotation + 90) * Mathf.Deg2Rad), 0, Mathf.Cos((objRotation + 90) * Mathf.Deg2Rad));
                                                Vector3 frontVector   = Vector3.Cross(sideVector, terrainNormal);
                                                rotation = Quaternion.LookRotation(frontVector, terrainNormal);
                                            }
                                            else
                                            {
                                                rotation = objRotation.EulerToQuat();
                                            }

                                            //scale
                                            float rndScale = noise.Random((int)(wx * 10), (int)(wz * 10), 1);
                                            rndScale = layer.scaleMinMax.x + (layer.scaleMinMax.y - layer.scaleMinMax.x) * rndScale;
                                            Vector3 scale = new Vector3(rndScale, rndScale, rndScale);

                                            //storage.AddVegetationItemInstance(id, new Vector3(wx,terrainHeight,wz), scale, rotation, layer.applyMeshRotation, VS_MM_id, true);
                                            cell.AddVegetationItemInstance(id, new Vector3(wx, terrainHeight, wz), scale, rotation, VS_MM_id);
                                        }
                                    }
                                }

                                if (stop != null && stop(0))
                                {
                                    return;
                                }
                            }
                        }
                    }
                }
            }

            //refreshing billboards
            //calling it from thread ruins all the billboards
            //BillboardSystem billboardSys = billboardComponents[rect];
            //if (billboardSys != null)
            //	 billboardSys.RefreshBillboards();
                        #endif

            //pushing anything to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VegetationStudioOutput), null, replace: true);
        }
Example #15
0
			public void Preview ()
			{
				#if UNITY_EDITOR 
				if (Event.current == null || Event.current.type != EventType.Repaint) return;
					
				//clearing preview if prevew generator is off (or non-map)
				if (MapMagic.instance.previewOutput==null || MapMagic.instance.previewOutput.type!=Generator.InoutType.Map)
				{
					if (terrain.materialTemplate != null && terrain.materialTemplate.shader.name == "MapMagic/TerrainPreviewFirstPass")
					{
						terrain.materialType = MapMagic.ToUnityTerrMatType(MapMagic.instance.terrainMaterialType);
						terrain.materialTemplate = previewBackupMaterial;

						previewBackupMaterial = null;
						lastPreviewedMatrix = null;

						UnityEditor.SceneView.RepaintAll();
					}
				}
						
				if (MapMagic.instance.previewOutput!=null && MapMagic.instance.previewOutput.type == Generator.InoutType.Map)
				{
					//loading preview material from terrain (or creating new)
					Material previewMat = null;
					if (terrain.materialTemplate!=null && terrain.materialTemplate.shader.name=="MapMagic/TerrainPreviewFirstPass") previewMat = terrain.materialTemplate;
					if (previewMat == null) 
					{
						Shader previewShader = Shader.Find("MapMagic/TerrainPreviewFirstPass");
						previewMat = new Material(previewShader);

						previewBackupMaterial = terrain.materialTemplate;
						terrain.materialTemplate = previewMat;
						terrain.materialType = Terrain.MaterialType.Custom;
						
						UnityEditor.SceneView.RepaintAll();
					}

					//loading matrix
					Matrix matrix = MapMagic.instance.previewOutput.GetObject<Matrix>(this);

					//refreshing preview texture
					if (matrix != lastPreviewedMatrix)
					{
						Texture2D tex = null;
						
						//populate
						if (matrix != null) 
						{
							tex = new Texture2D(matrix.rect.size.x, matrix.rect.size.z);
			 
							Color[] line = new Color[matrix.rect.size.z];
							for (int x=0; x<matrix.rect.size.x; x++)
							{
								for (int z=0; z<matrix.rect.size.z; z++)
								{
									float val = matrix[x+matrix.rect.offset.x, z+matrix.rect.offset.z];
									line[z] = new Color(val, val, val);
								}
								tex.SetPixels(x,0,1,line.Length,line);
							}
						}
						else //in case the output is not generated
						{
							tex = Extensions.ColorTexture(2,2,Color.gray);
						}

						//apply
						tex.Apply();
						previewMat.SetTexture("_Preview", tex);
						if (MapMagic.instance.guiDebug) Debug.Log("Preview Applied");

						lastPreviewedMatrix = matrix;

						UnityEditor.SceneView.RepaintAll();
					}
				}

				//spatial hash
				if (MapMagic.instance.previewOutput!=null && MapMagic.instance.previewOutput.type == Generator.InoutType.Objects)
				{
					float pixelSize = 1f * MapMagic.instance.terrainSize / MapMagic.instance.resolution;
					
					SpatialHash objs = MapMagic.instance.previewOutput.GetObject<SpatialHash>(this);

					if (objs != null)
					{
						int objsCount = objs.Count;
						foreach (SpatialObject obj in objs)
						{
							float terrainHeight = 0;
							if (heights != null) terrainHeight = heights.GetInterpolated(obj.pos.x, obj.pos.y);
							Vector3 pos = new Vector3(obj.pos.x*pixelSize, (obj.height+terrainHeight)*MapMagic.instance.terrainHeight, obj.pos.y*pixelSize);
							pos += MapMagic.instance.transform.position;

							UnityEditor.Handles.color = new Color(1,1,1,1);
							UnityEditor.Handles.DrawLine(pos+new Vector3(obj.size/2f,0,0), pos-new Vector3(obj.size/2f,0,0));
							UnityEditor.Handles.DrawLine(pos+new Vector3(0,0,obj.size/2f), pos-new Vector3(0,0,obj.size/2f));

							if (objsCount < 100)
							{
								Vector3 oldPoint = pos;
								foreach (Vector3 point in pos.CircleAround(obj.size/2f, 12, true))
								{
									UnityEditor.Handles.DrawLine(oldPoint,point);
									oldPoint = point;
								}
							}

							UnityEditor.Handles.color = new Color(1,1,1,0.15f); 
							UnityEditor.Handles.DrawLine(new Vector3(pos.x, 0, pos.z), new Vector3(pos.x, MapMagic.instance.terrainHeight, pos.z));
						}
					}
				}

				#endif
			}
        public float uniformity = 0.1f;         //aka candidatesNum/100

        public override void Generate(Chunk chunk, Biome biome = null)
        {
            Matrix      probMatrix  = (Matrix)probability.GetObject(chunk);
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            // If the bounds of this chunk don't contain the specified zValue then return the
            // default spatialHash
            if (spatialHash.offset.y > zValue || spatialHash.offset.y + spatialHash.size <= zValue)
            {
                output.SetObject(chunk, spatialHash);
                return;
            }

            InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed + chunk.coord.x * 1000 + chunk.coord.z);

            int candidatesNum = (int)(uniformity * 100);

            for (int i = 0; i < count; i++)
            {
                Vector2 bestCandidate = Vector3.zero;
                float   bestDist      = 0;

                for (int c = 0; c < candidatesNum; c++)
                {
                    Vector2 candidate = new Vector2((spatialHash.offset.x + 1) + (rnd.Random() * (spatialHash.size - 2.01f)), zValue);

                    //checking if candidate available here according to probability map
                    if (probMatrix != null && probMatrix[candidate] < rnd.Random())
                    {
                        continue;
                    }

                    //checking if candidate is the furthest one
                    float dist = spatialHash.MinDist(candidate);
                    if (dist > bestDist)
                    {
                        bestDist = dist; bestCandidate = candidate;
                    }
                }

                if (bestDist > 0.001f)
                {
                    spatialHash.Add(bestCandidate, 0, 0, 1); //adding only if some suitable candidate found
                }
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }
Example #17
0
        public override void Generate(MapMagic.Chunk chunk)
        {
            //getting inputs
            SpatialHash objects = (SpatialHash)objectsIn.GetObject(chunk);
            Matrix      src     = (Matrix)canvasIn.GetObject(chunk);

            //return on stop/disable/null input
            if (chunk.stop || objects == null)
            {
                return;
            }
            if (!enabled)
            {
                output.SetObject(chunk, src); return;
            }

            //preparing output
            Matrix dst;

            if (src != null)
            {
                dst = src.Copy(null);
            }
            else
            {
                dst = chunk.defaultMatrix;
            }

            //finding maximum radius
            float maxRadius = radius;

            if (sizeFactor > 0.00001f)
            {
                float maxObjSize = 0;
                foreach (SpatialObject obj in objects.AllObjs())
                {
                    if (obj.size > maxObjSize)
                    {
                        maxObjSize = obj.size;
                    }
                }
                maxObjSize = maxObjSize / MapMagic.instance.terrainSize * MapMagic.instance.resolution;                 //transforming to map-space
                maxRadius  = radius * (1 - sizeFactor) + radius * maxObjSize * sizeFactor;
            }

            //preparing procedural matrices
            Matrix noiseMatrix   = new Matrix(new CoordRect(0, 0, maxRadius * 2 + 2, maxRadius * 2 + 2));
            Matrix percentMatrix = new Matrix(new CoordRect(0, 0, maxRadius * 2 + 2, maxRadius * 2 + 2));

            foreach (SpatialObject obj in objects.AllObjs())
            {
                //finding current radius
                float curRadius = radius * (1 - sizeFactor) + radius * obj.size * sizeFactor;
                curRadius = curRadius / MapMagic.instance.terrainSize * MapMagic.instance.resolution;                 //transforming to map-space

                //resizing procedural matrices
                CoordRect matrixSize = new CoordRect(0, 0, curRadius * 2 + 2, curRadius * 2 + 2);
                noiseMatrix.ChangeRect(matrixSize);
                percentMatrix.ChangeRect(matrixSize);

                //apply stamp
                noiseMatrix.rect.offset   = new Coord((int)(obj.pos.x - curRadius - 1), (int)(obj.pos.y - curRadius - 1));
                percentMatrix.rect.offset = new Coord((int)(obj.pos.x - curRadius - 1), (int)(obj.pos.y - curRadius - 1));

                CoordRect intersection = CoordRect.Intersect(noiseMatrix.rect, dst.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++)
                    {
                        float dist    = Mathf.Sqrt((x - obj.pos.x + 0.5f) * (x - obj.pos.x + 0.5f) + (z - obj.pos.y + 0.5f) * (z - obj.pos.y + 0.5f));
                        float percent = 1f - dist / curRadius;
                        if (percent < 0 || dist > curRadius)
                        {
                            percent = 0;
                        }

                        percentMatrix[x, z] = percent;
                    }
                }

                //adjusting value by curve
                Curve c = new Curve(curve);
                for (int i = 0; i < percentMatrix.array.Length; i++)
                {
                    percentMatrix.array[i] = c.Evaluate(percentMatrix.array[i]);
                }

                //adding some noise
                if (useNoise)
                {
                    NoiseGenerator.Noise(noiseMatrix, noiseSize, 0.5f, offset: Vector2.zero);

                    for (int x = min.x; x < max.x; x++)
                    {
                        for (int z = min.z; z < max.z; z++)
                        {
                            float val = percentMatrix[x, z];
                            if (val < 0.0001f)
                            {
                                continue;
                            }

                            float noise = noiseMatrix[x, z];
                            if (val < 0.5f)
                            {
                                noise *= val * 2;
                            }
                            else
                            {
                                noise = 1 - (1 - noise) * (1 - val) * 2;
                            }

                            percentMatrix[x, z] = noise * noiseAmount + val * (1 - noiseAmount);
                        }
                    }
                }

                //applying matrices
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        //float distSq = (x-obj.pos.x)*(x-obj.pos.x) + (z-obj.pos.y)*(z-obj.pos.y);
                        //if (distSq > radius*radius) continue;

                        float percent = percentMatrix[x, z];
                        dst[x, z] = (maxHeight? 1:obj.height) * percent + dst[x, z] * (1 - percent);
                    }
                }
            }

            Matrix mask = (Matrix)maskIn.GetObject(chunk);

            if (mask != null)
            {
                Matrix.Mask(src, dst, mask);
            }
            if (safeBorders != 0)
            {
                Matrix.SafeBorders(src, dst, safeBorders);
            }

            //setting output
            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, dst);
        }
        public float uniformity = 0.1f;         //aka candidatesNum/100

        public override void Generate(Chunk chunk, Biome biome = null)
        {
            Matrix      probMatrix  = (Matrix)probability.GetObject(chunk);
            SpatialHash spatialHash = chunk.defaultSpatialHash;

            if (!enabled)
            {
                output.SetObject(chunk, spatialHash); return;
            }
            if (chunk.stop)
            {
                return;
            }

            InstanceRandom rnd = new InstanceRandom(MapMagic.instance.seed + seed + chunk.coord.x * 1000 + chunk.coord.z);

            //Rect terrainRect = terrain.coord.ToRect(terrain.size);
            //terrainRect.position += Vector2.one; terrainRect.size-=Vector2.one*2;

            //SpatialHash spatialHash = new SpatialHash(terrain.coord.ToVector2(terrain.size), terrain.size, 16);


            //float square = terrainRect.width * terrainRect.height;
            //float count = square*(density/1000000); //number of items per terrain

            //positioned scatter

            /*float sideCount = Mathf.Sqrt(count);
             * float step = spatialHash.size / sideCount;
             *
             * //int uniformity = 100;
             * //Random.seed = 12345;
             * for (float x=spatialHash.offset.x+step/2; x<spatialHash.offset.x+spatialHash.size-step/2; x+=step)
             *      for (float y=spatialHash.offset.y+step/2; y<spatialHash.offset.y+spatialHash.size-step/2; y+=step)
             * {
             *      Vector2 offset = new Vector2(((Random.value*2-1)*uniformity), ((Random.value*2-1)*uniformity));
             *      Vector2 point = new Vector2(x,y) + offset;
             *      if (point.x > spatialHash.size) point.x -= spatialHash.size; if (point.x < 0) point.x += spatialHash.size;
             *      if (point.y > spatialHash.size) point.y -= spatialHash.size; if (point.y < 0) point.y += spatialHash.size;
             *      spatialHash.Add(point, 0,0,0);
             * }*/

            //realRandom algorithm
            int candidatesNum = (int)(uniformity * 100);

            for (int i = 0; i < count; i++)
            {
                Vector2 bestCandidate = Vector3.zero;
                float   bestDist      = 0;

                for (int c = 0; c < candidatesNum; c++)
                {
                    Vector2 candidate = new Vector2((spatialHash.offset.x + 1) + (rnd.Random() * (spatialHash.size - 2.01f)), (spatialHash.offset.y + 1) + (rnd.Random() * (spatialHash.size - 2.01f)));

                    //checking if candidate available here according to probability map
                    if (probMatrix != null && probMatrix[candidate] < rnd.Random() + 0.0001f)
                    {
                        continue;
                    }

                    //checking if candidate is the furthest one
                    float dist = spatialHash.MinDist(candidate);
                    if (dist > bestDist)
                    {
                        bestDist = dist; bestCandidate = candidate;
                    }
                }

                if (bestDist > 0.001f)
                {
                    spatialHash.Add(bestCandidate, 0, 0, 1);                                  //adding only if some suitable candidate found
                }
            }

            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, spatialHash);
        }