public override void Generate(Chunk chunk, Biome biome = null)
        {
            //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 static void Noise(Matrix matrix, float size, float intensity = 1, float bias = 0, float detail = 0.5f, Vector2 offset = new Vector2(), int seed = 12345, Matrix mask = null)
        {
            int step = (int)(4096f / matrix.rect.size.x);

            int totalSeedX = ((int)offset.x + MapMagic.instance.seed + seed * 7) % 77777;
            int totalSeedZ = ((int)offset.y + MapMagic.instance.seed + seed * 3) % 73333;

            //get number of iterations
            int   numIterations = 1;           //max size iteration included
            float tempSize      = size;

            for (int i = 0; i < 100; i++)
            {
                tempSize = tempSize / 2;
                if (tempSize < 1)
                {
                    break;
                }
                numIterations++;
            }

            //making some noise
            Coord min = matrix.rect.Min; Coord max = matrix.rect.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    float result    = 0.5f;
                    float curSize   = size * 10;
                    float curAmount = 1;

                    //applying noise
                    for (int i = 0; i < numIterations; i++)
                    {
                        float perlin = Mathf.PerlinNoise(
                            (x + totalSeedX + 1000 * (i + 1)) * step / (curSize + 1),
                            (z + totalSeedZ + 100 * i) * step / (curSize + 1));
                        perlin = (perlin - 0.5f) * curAmount + 0.5f;

                        //applying overlay
                        if (perlin > 0.5f)
                        {
                            result = 1 - 2 * (1 - result) * (1 - perlin);
                        }
                        else
                        {
                            result = 2 * perlin * result;
                        }

                        curSize   *= 0.5f;
                        curAmount *= detail;                         //detail is 0.5 by default
                    }

                    //apply contrast and bias
                    result  = result * intensity;
                    result -= 0 * (1 - bias) + (intensity - 1) * bias;             //0.5f - intensity*bias;

                    if (result < 0)
                    {
                        result = 0;
                    }
                    if (result > 1)
                    {
                        result = 1;
                    }

                    if (mask == null)
                    {
                        matrix[x, z] += result;
                    }
                    else
                    {
                        matrix[x, z] += result * mask[x, z];
                    }
                }
            }
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            Matrix matrix = (Matrix)input.GetObject(chunk); if (matrix != null)

            {
                matrix = matrix.Copy(null);
            }

            if (matrix == null)
            {
                matrix = chunk.defaultMatrix;
            }
            Matrix mask = (Matrix)maskIn.GetObject(chunk);

            if (chunk.stop)
            {
                return;
            }
            if (!enabled || intensity == 0 || cellCount == 0)
            {
                output.SetObject(chunk, matrix); return;
            }

            //NoiseGenerator.Noise(matrix,200,0.5f,Vector2.zero);
            //matrix.Multiply(amount);

            InstanceRandom random = new InstanceRandom(MapMagic.instance.seed + seed);

            //creating point matrix
            float             cellSize = 1f * matrix.rect.size.x / cellCount;
            Matrix2 <Vector3> points   = new Matrix2 <Vector3>(new CoordRect(0, 0, cellCount + 2, cellCount + 2));

            points.rect.offset = new Coord(-1, -1);

            Coord matrixSpaceOffset = new Coord((int)(matrix.rect.offset.x / cellSize), (int)(matrix.rect.offset.z / cellSize));

            //scattering points
            for (int x = -1; x < points.rect.size.x - 1; x++)
            {
                for (int z = -1; z < points.rect.size.z - 1; z++)
                {
                    Vector3 randomPoint = new Vector3(x + random.CoordinateRandom(x + matrixSpaceOffset.x, z + matrixSpaceOffset.z), 0, z + random.NextCoordinateRandom());
                    Vector3 centerPoint = new Vector3(x + 0.5f, 0, z + 0.5f);
                    Vector3 point       = randomPoint * (1 - uniformity) + centerPoint * uniformity;
                    point        = point * cellSize + new Vector3(matrix.rect.offset.x, 0, matrix.rect.offset.z);
                    point.y      = random.NextCoordinateRandom();
                    points[x, z] = point;
                }
            }

            Coord min = matrix.rect.Min; Coord max = matrix.rect.Max;

            for (int x = min.x; x < max.x; x++)
            {
                for (int z = min.z; z < max.z; z++)
                {
                    //finding current cell
                    Coord cell = new Coord((int)((x - matrix.rect.offset.x) / cellSize), (int)((z - matrix.rect.offset.z) / cellSize));

                    //finding min dist
                    float minDist = 200000000; float secondMinDist = 200000000;
                    float minHeight = 0;             //float secondMinHeight = 0;
                    for (int ix = -1; ix <= 1; ix++)
                    {
                        for (int iz = -1; iz <= 1; iz++)
                        {
                            Coord nearCell = new Coord(cell.x + ix, cell.z + iz);
                            //if (!points.rect.CheckInRange(nearCell)) continue; //no need to perform test as points have 1-cell border around matrix

                            Vector3 point = points[nearCell];
                            float   dist  = (x - point.x) * (x - point.x) + (z - point.z) * (z - point.z);
                            if (dist < minDist)
                            {
                                secondMinDist = minDist; minDist = dist;
                                minHeight     = point.y;
                            }
                            else if (dist < secondMinDist)
                            {
                                secondMinDist = dist;
                            }
                        }
                    }

                    float val = 0;
                    switch (blendType)
                    {
                    case BlendType.flat: val = minHeight; break;

                    case BlendType.closest: val = minDist / (MapMagic.instance.resolution * 16); break;

                    case BlendType.secondClosest: val = secondMinDist / (MapMagic.instance.resolution * 16); break;

                    case BlendType.cellular: val = (secondMinDist - minDist) / (MapMagic.instance.resolution * 16); break;

                    case BlendType.organic: val = (secondMinDist + minDist) / 2 / (MapMagic.instance.resolution * 16); break;
                    }
                    if (mask == null)
                    {
                        matrix[x, z] += val * intensity;
                    }
                    else
                    {
                        matrix[x, z] += val * intensity * mask[x, z];
                    }
                }
            }

            if (chunk.stop)
            {
                return;                         //do not write object is generating is stopped
            }
            output.SetObject(chunk, matrix);
        }
예제 #4
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;
            }

            //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 grass
            area.ClearGrass();

            //preparing random
            //Noise noise = new Noise(12345); //to switch grass depending on it's opacity

            //processing
            foreach (VoxelandGrassOutput gen in gens.GeneratorsOfType <VoxelandGrassOutput>(onlyEnabled:true, checkBiomes:true))
            {
                //reading output directly
                if (stop != null && stop(0))
                {
                    return;                                        //checking stop before reading 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
                    Matrix src = (Matrix)layer.input.GetObject(results);
                    if (src == null)
                    {
                        continue;
                    }
                    //multiplying with biome mask - in SetGrassLayer

                    //apply
                    //area.SetGrassLayer(src, (byte)l, layer.density, noise:noise, layerNum:l, mask:biomeMask);
                    area.SetGrassLayer(src.rect.offset.x, src.rect.offset.z, src.rect.size.x, src.array, (byte)l, layer.density, l, biomeMask == null? null : biomeMask.array);
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VoxelandOutput), null, replace: true);
                        #endif
        }
        public override void Generate(Chunk chunk, Biome biome = null)
        {
            if (!enabled || chunk.stop)
            {
                return;
            }

            CoordRect scaledRect = new CoordRect(
                (int)(offset.x * MapMagic.instance.resolution / MapMagic.instance.terrainSize),
                (int)(offset.y * MapMagic.instance.resolution / MapMagic.instance.terrainSize),
                (int)(MapMagic.instance.resolution * scale),
                (int)(MapMagic.instance.resolution * scale));
            Matrix stampMatrix = new Matrix(scaledRect);

            float gradientStep = 1f / stampMatrix.rect.size.x;
            Coord center = scaledRect.Center;
            float radius = stampMatrix.rect.size.x / 2f;
            Coord min = stampMatrix.rect.Min; Coord max = stampMatrix.rect.Max;

            switch (type)
            {
            case FormType.GradientX:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        stampMatrix[x, z] = x * gradientStep;
                    }
                }
                break;

            case FormType.GradientZ:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        stampMatrix[x, z] = z * gradientStep;
                    }
                }
                break;

            case FormType.Pyramid:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float valX = x * gradientStep; if (valX > 1 - valX)
                        {
                            valX = 1 - valX;
                        }
                        float valZ = z * gradientStep; if (valZ > 1 - valZ)
                        {
                            valZ = 1 - valZ;
                        }
                        stampMatrix[x, z] = valX < valZ? valX * 2 : valZ * 2;
                    }
                }
                break;

            case FormType.Cone:
                for (int x = min.x; x < max.x; x++)
                {
                    for (int z = min.z; z < max.z; z++)
                    {
                        float val = 1 - (Coord.Distance(new Coord(x, z), center) / radius);
                        if (val < 0)
                        {
                            val = 0;
                        }
                        stampMatrix[x, z] = val;
                    }
                }
                break;
            }

            Matrix matrix = chunk.defaultMatrix;

            matrix.Replicate(stampMatrix, tile: tile);
            matrix.Multiply(intensity);


            //if (tile) textureMatrix.FromTextureTiled(texture);
            //else textureMatrix.FromTexture(texture);

            //if (!Mathf.Approximately(scale,1)) textureMatrix = textureMatrix.Resize(matrix.rect, result:matrix);
            if (chunk.stop)
            {
                return;
            }
            output.SetObject(chunk, matrix);
        }
예제 #6
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
        }
예제 #7
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 area
            area.ClearLand();

            //finding a list of areas and their opacities
            List <Voxeland5.Data.Area> areas = new List <Voxeland5.Data.Area>();
            List <Matrix> opacities          = new List <Matrix>();
            foreach (VoxelandOutput gen in gens.GeneratorsOfType <VoxelandOutput>(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
                    }
                }

                areas.Add(genArea);
                opacities.Add(biomeMask);
            }

            //merge areas using biome mask
            if (areas.Count >= 2)
            //area.MixAreas(areas.ToArray(), opacities.ToArray());
            {
                float[][] opacityArrays = new float[opacities.Count][];
                for (int i = 0; i < opacityArrays.Length; i++)
                {
                    if (opacities[i] != null)
                    {
                        opacityArrays[i] = opacities[i].array;
                    }
                }
                area.MixAreas(areas.ToArray(), rect.offset.x, rect.offset.z, rect.size.x, opacityArrays);
            }
            else
            {
                Voxeland5.Data.Area.CopyLand(areas[0], area);
            }

            //reading heights
            if (results.heights == null || results.heights.rect.size.x != rect.size.x)
            {
                results.heights = new Matrix(rect);
            }
            if (results.heights.rect != rect)
            {
                results.heights.Resize(rect);
            }
            results.heights.Clear();

            for (int x = 0; x < results.heights.rect.size.x; x++)
            {
                for (int z = 0; z < results.heights.rect.size.z; z++)
                {
                    results.heights[x + results.heights.rect.offset.x, z + results.heights.rect.offset.z] = 1f * area.lines[x].columns[z].topLevel / heightFactor;
                }
            }

            //pushing to apply
            if (stop != null && stop(0))
            {
                return;
            }
            results.apply.CheckAdd(typeof(VoxelandOutput), null, replace: true);
                        #endif
        }
예제 #8
0
        public IEnumerator Apply(MapMagic.CoordRect rect, Terrain terrain, object dataBox, Func <float, bool> stop = null)
        {
            TupleSet <float[, , ], SplatPrototypeWrapper[]> splatsTuple = (TupleSet <float[, , ], SplatPrototypeWrapper[]>)dataBox;

            float[,,] splats3D = splatsTuple.item1;
            SplatPrototypeWrapper[] prototypes = splatsTuple.item2;

            if (splats3D.GetLength(2) == 0)
            {
                Purge(rect, terrain); yield break;
            }

            //TerrainData data = terrain.terrainData;

            //setting resolution
            //int size = splats3D.GetLength(0);
            //if (data.alphamapResolution != size) data.alphamapResolution = size;

            //checking prototypes texture
            for (int i = 0; i < prototypes.Length; i++)
            {
                if (prototypes[i].Texture == null)
                {
                    prototypes[i].Texture = defaultTex;
                }
            }
            yield return(null);

            //welding
            if (MapMagic.MapMagic.instance != null && MapMagic.MapMagic.instance.splatsWeldMargins != 0)
            {
                MapMagic.Coord coord = MapMagic.Coord.PickCell(rect.offset, MapMagic.MapMagic.instance.resolution);
                //Chunk chunk = MapMagic.MapMagic.instance.chunks[coord.x, coord.z];

                Chunk neigPrevX = MapMagic.MapMagic.instance.chunks[coord.x - 1, coord.z];
                if (neigPrevX != null && neigPrevX.worker.ready)
                {
                    WeldTerrains.WeldSplatToPrevX(ref splats3D, neigPrevX.terrain, MapMagic.MapMagic.instance.splatsWeldMargins);
                }

                Chunk neigNextX = MapMagic.MapMagic.instance.chunks[coord.x + 1, coord.z];
                if (neigNextX != null && neigNextX.worker.ready)
                {
                    WeldTerrains.WeldSplatToNextX(ref splats3D, neigNextX.terrain, MapMagic.MapMagic.instance.splatsWeldMargins);
                }

                Chunk neigPrevZ = MapMagic.MapMagic.instance.chunks[coord.x, coord.z - 1];
                if (neigPrevZ != null && neigPrevZ.worker.ready)
                {
                    WeldTerrains.WeldSplatToPrevZ(ref splats3D, neigPrevZ.terrain, MapMagic.MapMagic.instance.splatsWeldMargins);
                }

                Chunk neigNextZ = MapMagic.MapMagic.instance.chunks[coord.x, coord.z + 1];
                if (neigNextZ != null && neigNextZ.worker.ready)
                {
                    WeldTerrains.WeldSplatToNextZ(ref splats3D, neigNextZ.terrain, MapMagic.MapMagic.instance.splatsWeldMargins);
                }
            }
            yield return(null);

            terrain.terrainData.splatPrototypes = new[] { new SplatPrototype()
                                                          {
                                                              texture = defaultTex
                                                          } };                                                       // To stop MapMagic purging what we're doing here alter on...

            var wrapper        = terrain.gameObject.GetOrAddComponent <TerrainWrapper>();
            var MMTerrainLayer = wrapper.GetLayer <MMTerrainLayer>(LayerName, false, true);

            MMTerrainLayer.SplatData.Clear();

            var splatWidth  = splats3D.GetLength(0);
            var splatHeight = splats3D.GetLength(1);

            if (terrain.terrainData.alphamapResolution != splatWidth)
            {
                Debug.Log("Set alphamapResolution to " + splatWidth);
                terrain.terrainData.alphamapResolution = splatWidth;
            }

            var data = new float[splatWidth, splatHeight];

            for (int i = 0; i < prototypes.Length; i++)
            {
                var splatPrototypeWrapper = prototypes[i];
                for (var u = 0; u < splatWidth; ++u)
                {
                    for (var v = 0; v < splatHeight; ++v)
                    {
                        data[v, u] = splats3D[u, v, i];
                    }
                }
                MMTerrainLayer.SetSplatmap(splatPrototypeWrapper, 0, 0, data, splatWidth);
            }

            global::MapMagic.MapMagic.OnApplyCompleted -= MapMagicIntegrationUtilities.MapMagicOnOnApplyCompleted;
            global::MapMagic.MapMagic.OnApplyCompleted += MapMagicIntegrationUtilities.MapMagicOnOnApplyCompleted;

            wrapper.SetDirtyAbove(MMTerrainLayer);
            yield return(null);
        }
예제 #9
0
        static void DrawMatrices()
        {
            //refreshing matrices if needed
            if (RefreshMatricesNeeded())
            {
                RefreshMatrices();
            }

            //getting pixel size
            float pixelSize = GetPixelSize();

            //preparing shader
            Shader previewShader = MapMagic.instance.previewShader;             //Shader.Find("MapMagic/TerrainPreview");

            //apply matrix textures to all objects
            foreach (Transform tfm in mapMagic.Transforms())
            {
                MeshRenderer renderer = tfm.GetComponent <MeshRenderer>();
                Terrain      terrain  = tfm.GetComponent <Terrain>();
                if (renderer == null && terrain == null)
                {
                    continue;
                }

                //finding object rect
                Rect worldRect = new Rect(0, 0, 0, 0);
                if (renderer != null)
                {
                    worldRect = new Rect(renderer.bounds.min.x, renderer.bounds.min.z, renderer.bounds.size.x, renderer.bounds.size.z);
                }
                else if (terrain != null)
                {
                    worldRect = new Rect(terrain.transform.localPosition.x, terrain.transform.localPosition.z, terrain.terrainData.size.x, terrain.terrainData.size.z);
                }

                CoordRect matrixRect = CoordRect.PickIntersectingCellsByPos(worldRect, pixelSize);

                //finding a matrix/texture that object should use
                Coord center = matrixRect.Center;
                foreach (KeyValuePair <Matrix, Texture2D> kvp in matrices)
                {
                    Matrix matrix = kvp.Key;

                    // Using the matrix that contains center - it would be the biggest intersection
                    if (matrix.rect.Contains(center.x, center.z))
                    {
                        Texture2D texture = kvp.Value;

                        //assigning material
                        Material material = null;
                        if (renderer != null)
                        {
                            if (renderer.sharedMaterial.shader != previewShader)
                            {
                                if (!originalMaterials.ContainsKey(tfm))
                                {
                                    originalMaterials.Add(tfm, renderer.sharedMaterial);
                                }
                                renderer.sharedMaterial = new Material(previewShader);
                            }
                            material = renderer.sharedMaterial;
                        }
                        else if (terrain != null)
                        {
                                                        #if UNITY_2019_2_OR_NEWER
                            if (terrain.materialTemplate == null || terrain.materialTemplate.shader != previewShader)
                            {
                                if (!originalMaterials.ContainsKey(tfm))
                                {
                                    originalMaterials.Add(tfm, terrain.materialTemplate);
                                }
                                else
                                {
                                    originalMaterials[tfm] = terrain.materialTemplate;
                                }

                                terrain.materialTemplate = new Material(previewShader);
                            }
                                                        #else
                            if (terrain.materialTemplate == null || terrain.materialTemplate.shader != previewShader)
                            {
                                if (terrain.materialType == Terrain.MaterialType.Custom && !originalMaterials.ContainsKey(tfm))
                                {
                                    originalMaterials.Add(tfm, terrain.materialTemplate);
                                }
                                terrain.materialTemplate = new Material(previewShader);
                            }
                            terrain.materialType = Terrain.MaterialType.Custom;
                                                        #endif
                            material = terrain.materialTemplate;
                        }

                        //assigning texture and params
                        material.name = tfm.name + " Preview";

                        //calculate parent MM object offset
                        //Vector3 offset = tfm.parent.position / (worldRect.size.x/matrix.rect.size.x); // /pixelsize

                        material.SetTexture("_Preview", texture);
                        material.SetVector("_Rect", new Vector4(matrix.rect.offset.x, matrix.rect.offset.z, matrix.rect.size.x, matrix.rect.size.z));
                        material.SetFloat("_Scale", pixelSize);

                        break;                         //interrupting when texture assigned (to center)
                    }
                }
            }
        }
예제 #10
0
        public IEnumerator Apply(MapMagic.CoordRect rect, Terrain terrain, object dataBox, Func <float, bool> stop = null)
        {
            //init heights
            #if UN_MapMagic
                        #if WDEBUG
            Profiler.BeginSample("UNature");
                        #endif

            uNatureHeightTuple heightTuple;
            float[,] heights2D;

            if (FoliageCore_MainManager.instance != null)
            {
                heightTuple = (uNatureHeightTuple)dataBox; // get data
                heights2D   = heightTuple.normalizedHeights;
                UNMapMagic_Manager.ApplyHeightOutput(heightTuple, terrain);
            }
            else
            {
                //Debug.LogError("uNature_MapMagic extension is enabled but no foliage manager exists on the scene.");
                //yield break;
                heights2D = (float[, ])dataBox;
            }

                        #if WDEBUG
            Profiler.EndSample();
                        #endif
                        #else
            float[,] heights2D = (float[, ])dataBox;
                        #endif

            heights2D = heights2D.Flip();

            //quick lod apply

            /*if (chunk.lod)
             * {
             *      //if (chunk.lodTerrain == null) { chunk.lodTerrain = (MapMagic.instance.transform.AddChild("Terrain " + chunk.coord.x + "," + chunk.coord.z + " LOD")).gameObject.AddComponent<Terrain>(); chunk.lodTerrain.terrainData = new TerrainData(); }
             *      if (chunk.lodTerrain.terrainData==null) chunk.lodTerrain.terrainData = new TerrainData();
             *
             *      chunk.lodTerrain.Resize(heights2D.GetLength(0), new Vector3(MapMagic.instance.terrainSize, MapMagic.instance.terrainHeight, MapMagic.instance.terrainSize));
             *      chunk.lodTerrain.terrainData.SetHeightsDelayLOD(0,0,heights2D);
             *
             *      yield break;
             * }*/

            //determining data
            if (terrain == null || terrain.terrainData == null)
            {
                yield break;                                                         //chunk removed during apply
            }
            TerrainData data = terrain.terrainData;

            //resizing terrain (standard terrain resize is extremely slow. Even when creating a new terrain)
            Vector3 terrainSize       = terrain.terrainData.size;       //new Vector3(MapMagic.instance.terrainSize, MapMagic.instance.terrainHeight, MapMagic.instance.terrainSize);
            int     terrainResolution = heights2D.GetLength(0);         //heights2D[0].GetLength(0);
            if ((data.size - terrainSize).sqrMagnitude > 0.01f || data.heightmapResolution != terrainResolution)
            {
                if (terrainResolution <= 64)                 //brute force
                {
                    data.heightmapResolution = terrainResolution;
                    data.size = new Vector3(terrainSize.x, terrainSize.y, terrainSize.z);
                }

                else                 //setting res 64, re-scaling to 1/64, and then changing res
                {
                    data.heightmapResolution = 65;
                    terrain.Flush();                     //otherwise unity crushes without an error
                    int resFactor = (terrainResolution - 1) / 64;
                    data.size = new Vector3(terrainSize.x / resFactor, terrainSize.y, terrainSize.z / resFactor);
                    data.heightmapResolution = terrainResolution;
                }
            }
            yield return(null);

            var heightSize = heights2D.GetLength(0);
            for (int x = 0; x < heightSize - 1; x++)
            {
                for (int z = 0; z < heightSize - 1; z++)
                {
                    heights2D[z, x] = Mathf.Clamp01(heights2D[z, x]);
                }
            }

            var wrapper        = terrain.gameObject.GetOrAddComponent <TerrainWrapper>();
            var MMTerrainLayer = wrapper.GetLayer <MMTerrainLayer>(LayerName, false, true);
            MMTerrainLayer.SetHeights(0, 0, heights2D, MapMagic.MapMagic.instance.resolution + 1);
            _pendingWrappers.Remove(rect);

            //welding
            if (MapMagic.MapMagic.instance != null && MapMagic.MapMagic.instance.heightWeldMargins != 0)
            {
                MapMagic.Coord coord = MapMagic.Coord.PickCell(rect.offset, MapMagic.MapMagic.instance.resolution);
                Chunk          chunk = MapMagic.MapMagic.instance.chunks[coord.x, coord.z];

                Chunk neigPrevX = MapMagic.MapMagic.instance.chunks[coord.x - 1, coord.z];
                if (neigPrevX != null && !_pendingWrappers.Contains(neigPrevX.rect) && neigPrevX.terrain && neigPrevX.terrain.terrainData.heightmapResolution == terrainResolution)
                {
                    var neighbourWrapper = neigPrevX.terrain.GetComponent <TerrainWrapper>();
                    if (neigPrevX.worker.ready && neighbourWrapper)
                    {
                        WeldTerrains.WeldToPrevZ(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                    }
                    //WeldTerrains.WeldToPrevX(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                    Chunk.SetNeigsX(neigPrevX, chunk);
                }

                Chunk neigNextX = MapMagic.MapMagic.instance.chunks[coord.x + 1, coord.z];
                if (neigNextX != null && !_pendingWrappers.Contains(neigNextX.rect) && neigNextX.terrain.terrainData.heightmapResolution == terrainResolution)
                {
                    var neighbourWrapper = neigNextX.terrain.GetComponent <TerrainWrapper>();
                    if (neigNextX.worker.ready && neighbourWrapper)
                    {
                        WeldTerrains.WeldToNextZ(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                    }
                    //WeldTerrains.WeldToNextX(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                    Chunk.SetNeigsX(chunk, neigNextX);
                }

                Chunk neigPrevZ = MapMagic.MapMagic.instance.chunks[coord.x, coord.z - 1];
                if (neigPrevZ != null && !_pendingWrappers.Contains(neigPrevZ.rect) && neigPrevZ.terrain.terrainData.heightmapResolution == terrainResolution)
                {
                    var neighbourWrapper = neigPrevZ.terrain.GetComponent <TerrainWrapper>();
                    if (neigPrevZ.worker.ready && neighbourWrapper)
                    {
                        //WeldTerrains.WeldToNextX(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                        WeldTerrains.WeldToPrevX(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                    }
                    Chunk.SetNeigsZ(neigPrevZ, chunk);
                }

                Chunk neigNextZ = MapMagic.MapMagic.instance.chunks[coord.x, coord.z + 1];
                if (neigNextZ != null && !_pendingWrappers.Contains(neigNextZ.rect) && neigNextZ.terrain.terrainData.heightmapResolution == terrainResolution)
                {
                    var neighbourWrapper = neigNextZ.terrain.GetComponent <TerrainWrapper>();
                    if (neigNextZ.worker.ready && neighbourWrapper)
                    {
                        //WeldTerrains.WeldToPrevX(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                        WeldTerrains.WeldToNextX(ref heights2D, neighbourWrapper, MapMagic.MapMagic.instance.heightWeldMargins);
                    }
                    Chunk.SetNeigsZ(chunk, neigNextZ);
                }
            }
            yield return(null);

            MMTerrainLayer.SetHeights(0, 0, heights2D, MapMagic.MapMagic.instance.resolution + 1);
            global::MapMagic.MapMagic.OnApplyCompleted -= MapMagicIntegrationUtilities.MapMagicOnOnApplyCompleted;
            global::MapMagic.MapMagic.OnApplyCompleted += MapMagicIntegrationUtilities.MapMagicOnOnApplyCompleted;

            wrapper.SetDirtyAbove(MMTerrainLayer);

            yield return(null);
        }