private void SpawnGrassesOnTerrain(GStylizedTerrain t, Color[] maskData, List <Vector4> vertices)
        {
            int grassIndex = -1;
            List <GGrassInstance> grassInstances = new List <GGrassInstance>();
            Vector2 v0          = Vector2.zero;
            Vector2 v1          = Vector2.zero;
            Vector2 v2          = Vector2.zero;
            Vector2 center      = Vector2.zero;
            float   radius      = 0;
            Vector2 pos         = Vector2.zero;
            Vector3 bary        = Vector3.zero;
            float   maskValue   = 0;
            int     sampleCount = Mathf.Clamp(GrassDensity * GrassDensity / 10, 1, 1000);

            int trisCount = vertices.Count / 3;

            for (int i = 0; i < trisCount; ++i)
            {
                v0 = t.WorldPointToUV(vertices[i * 3 + 0]);
                v1 = t.WorldPointToUV(vertices[i * 3 + 1]);
                v2 = t.WorldPointToUV(vertices[i * 3 + 2]);

                center = (v0 + v1 + v2) / 3;
                radius = Vector2.Distance(center, v0);

                for (int s = 0; s < sampleCount; ++s)
                {
                    grassIndex = GrassPrototypeIndices[Random.Range(0, GrassPrototypeIndices.Count)];
                    pos        = center + Random.insideUnitCircle * radius;
                    if (pos.x < 0 || pos.x > 1 ||
                        pos.y < 0 || pos.x > 1)
                    {
                        continue;
                    }

                    GUtilities.CalculateBarycentricCoord(pos, v0, v1, v2, ref bary);
                    if (bary.x < 0 || bary.y < 0 || bary.z < 0)
                    {
                        continue;
                    }

                    maskValue = GUtilities.GetColorBilinear(maskData, MaskResolution, MaskResolution, pos).r;
                    if (Random.value > maskValue)
                    {
                        continue;
                    }

                    GGrassInstance grass = GGrassInstance.Create(grassIndex);
                    grass.Position = new Vector3(pos.x, 0, pos.y);
                    grass.Rotation = Quaternion.Euler(0, Random.Range(MinRotation, MaxRotation), 0);
                    grass.Scale    = Vector3.Lerp(MinScale, MaxScale, Random.value);

                    grassInstances.Add(grass);
                }
            }

            t.TerrainData.Foliage.AddGrassInstances(grassInstances);
        }
Exemplo n.º 2
0
        private static void RestoreGrassInstances(GStylizedTerrain t, string backupName)
        {
            string prototyeIndicesFileName = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.GRASS_SUFFIX, GBackupFile.PROTOTYPEINDEX_SUFFIX);
            string positionsFileName       = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.GRASS_SUFFIX, GBackupFile.POSITION_SUFFIX);
            string rotationsFileName       = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.GRASS_SUFFIX, GBackupFile.ROTATION_SUFFIX);
            string scalesFileName          = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.GRASS_SUFFIX, GBackupFile.SCALE_SUFFIX);

            byte[] protoIndicesData = GBackupFile.ReadAllBytes(backupName, prototyeIndicesFileName);
            byte[] positionsData    = GBackupFile.ReadAllBytes(backupName, positionsFileName);
            byte[] rotationData     = GBackupFile.ReadAllBytes(backupName, rotationsFileName);
            byte[] scalesData       = GBackupFile.ReadAllBytes(backupName, scalesFileName);
            if (protoIndicesData != null &&
                positionsData != null &&
                rotationData != null &&
                scalesData != null)
            {
                protoIndicesData = GCompressor.Decompress(protoIndicesData);
                positionsData    = GCompressor.Decompress(positionsData);
                rotationData     = GCompressor.Decompress(rotationData);
                scalesData       = GCompressor.Decompress(scalesData);

                int[]   indices   = new int[protoIndicesData.Length / sizeof(int)];
                float[] positions = new float[positionsData.Length / sizeof(float)];
                float[] rotations = new float[rotationData.Length / sizeof(float)];
                float[] scales    = new float[scalesData.Length / sizeof(float)];

                Buffer.BlockCopy(protoIndicesData, 0, indices, 0, protoIndicesData.Length);
                Buffer.BlockCopy(positionsData, 0, positions, 0, positionsData.Length);
                Buffer.BlockCopy(rotationData, 0, rotations, 0, rotationData.Length);
                Buffer.BlockCopy(scalesData, 0, scales, 0, scalesData.Length);

                List <GGrassInstance> grasses = new List <GGrassInstance>();
                for (int i = 0; i < indices.Length; ++i)
                {
                    GGrassInstance grass = GGrassInstance.Create(indices[i]);
                    grass.Position = new Vector3(
                        positions[i * 3 + 0],
                        positions[i * 3 + 1],
                        positions[i * 3 + 2]);
                    grass.Rotation = new Quaternion(
                        rotations[i * 4 + 0],
                        rotations[i * 4 + 1],
                        rotations[i * 4 + 2],
                        rotations[i * 4 + 3]);
                    grass.Scale = new Vector3(
                        scales[i * 3 + 0],
                        scales[i * 3 + 1],
                        scales[i * 3 + 2]);
                    grasses.Add(grass);
                }

                t.TerrainData.Foliage.ClearGrassInstances();
                t.TerrainData.Foliage.AddGrassInstances(grasses);

                t.TerrainData.SetDirty(GTerrainData.DirtyFlags.Foliage);
            }
        }
Exemplo n.º 3
0
        private void DoImportDetailLayer(int layerIndex, int[,] density, List <GGrassInstance> grasses)
        {
            GGrassPrototype prototype = DesData.Foliage.Grasses.Prototypes[layerIndex];

            Rand    rand       = new Rand(layerIndex + SrcData.detailResolution);
            int     resolution = SrcData.detailResolution;
            int     d          = 0;
            float   maxOffset  = 1.0f / resolution;
            Vector2 uv         = Vector2.zero;
            Vector3 pos        = Vector3.zero;

            for (int z = 0; z < resolution; ++z)
            {
                for (int x = 0; x < resolution; ++x)
                {
                    d = density[z, x];
                    for (int i = 0; i < d; ++i)
                    {
                        if (rand.NextDouble() > GrassDensity)
                        {
                            continue;
                        }
                        uv.Set(
                            Mathf.InverseLerp(0, resolution - 1, x),
                            Mathf.InverseLerp(0, resolution - 1, z));
                        pos.Set(
                            (float)(uv.x + rand.NextDouble() * maxOffset),
                            0,
                            (float)(uv.y + rand.NextDouble() * maxOffset));


                        GGrassInstance grass = GGrassInstance.Create(layerIndex);
                        grass.Position = pos;
                        grass.Rotation = Quaternion.Euler(0, (float)rand.NextDouble() * 360f, 0);
                        grass.Scale    = Mathf.Lerp(0.5f, 1f, (float)rand.NextDouble()) * Vector3.one;

                        grasses.Add(grass);
                    }
                }
            }

            //GC.Collect();
        }
Exemplo n.º 4
0
        private void SpawnGrassOnTerrain(GStylizedTerrain t, Color[] maskData, int layerIndex)
        {
            GFoliageStampLayer layer     = Layers[layerIndex];
            Vector3            centerPos = Vector3.zero;
            Vector3            samplePos = Vector3.zero;
            Vector2            uv        = Vector2.zero;
            float   maskValue            = 0;
            Vector3 terrainSize          = new Vector3(
                t.TerrainData.Geometry.Width,
                t.TerrainData.Geometry.Height,
                t.TerrainData.Geometry.Length);
            Vector3 scale = new Vector3(
                GUtilities.InverseLerpUnclamped(0, terrainSize.x, Scale.x),
                1,
                GUtilities.InverseLerpUnclamped(0, terrainSize.z, Scale.z));
            Matrix4x4 matrix = Matrix4x4.TRS(
                t.WorldPointToNormalized(Position),
                Rotation,
                scale);

            int grassIndex                = -1;
            int instanceCount             = 0;
            int attempt                   = 0;
            int maxAttempt                = layer.GrassInstanceCount * 100;
            List <GGrassInstance> grasses = new List <GGrassInstance>();

#if UNITY_EDITOR
            string title           = "Stamping on " + t.name;
            string info            = string.Format("Layer: {0}", !string.IsNullOrEmpty(layer.Name) ? layer.Name : layerIndex.ToString());
            int    currentPercent  = 0;
            int    attemptPercent  = 0;
            int    instancePercent = 0;
            GCommonGUI.CancelableProgressBar(title, info, 0);
#endif

            while (instanceCount < layer.GrassInstanceCount && attempt <= maxAttempt)
            {
                attempt += 1;

#if UNITY_EDITOR
                attemptPercent  = (int)(attempt * 100.0f / maxAttempt);
                instancePercent = (int)(instanceCount * 100.0f / layer.GrassInstanceCount);
                if (currentPercent != Mathf.Max(attemptPercent, instancePercent))
                {
                    currentPercent = Mathf.Max(attemptPercent, instancePercent);
                    GCommonGUI.CancelableProgressBar(title, string.Format("{0} ... {1}%", info, currentPercent), currentPercent / 100.0f);
                }
#endif

                grassIndex = layer.GrassIndices[Random.Range(0, layer.GrassIndices.Count)];

                centerPos.Set(Random.value - 0.5f, 0, Random.value - 0.5f);
                samplePos = matrix.MultiplyPoint(centerPos);
                if (samplePos.x < 0 || samplePos.x > 1 ||
                    samplePos.z < 0 || samplePos.z > 1)
                {
                    continue;
                }
                uv.Set(samplePos.x, samplePos.z);
                maskValue = GUtilities.GetColorBilinear(maskData, MaskResolution, MaskResolution, uv).r;
                if (Random.value > maskValue)
                {
                    continue;
                }

                GGrassInstance grass = GGrassInstance.Create(grassIndex);
                grass.Position = new Vector3(samplePos.x, 0, samplePos.z);
                grass.Rotation = Quaternion.Euler(0, Random.Range(layer.MinRotation, layer.MaxRotation), 0);
                grass.Scale    = Vector3.Lerp(layer.MinScale, layer.MaxScale, Random.value);

                grasses.Add(grass);
                instanceCount += 1;
            }

            t.TerrainData.Foliage.AddGrassInstances(grasses);

#if UNITY_EDITOR
            GCommonGUI.ClearProgressBar();
#endif
        }
Exemplo n.º 5
0
        private void HandleSpawnGrass(GStylizedTerrain terrain, GFoliagePainterArgs args)
        {
            int        grassIndex   = -1;
            Vector3    randomPos    = Vector3.zero;
            Vector3    rayOrigin    = Vector3.zero;
            Vector3    rayDirection = Vector3.down;
            float      sqrtTwo      = Mathf.Sqrt(2);
            Ray        ray          = new Ray();
            RaycastHit samplePoint;
            Vector3    bary0  = Vector3.zero;
            Vector3    bary1  = Vector3.zero;
            Vector2    maskUv = Vector2.zero;
            Vector2    samplePointTexcoord = Vector2.zero;
            Color      maskColor           = Color.white;
            Texture2D  clonedMask          = null;
            Texture2D  terrainMask         = null;

            if (args.Mask != null)
            {
                clonedMask = GCommon.CloneAndResizeTexture(args.Mask, 256, 256);
            }
            if (args.EnableTerrainMask)
            {
                terrainMask = terrain.TerrainData.Mask.MaskMap;
            }

            int prototypeCount = terrain.TerrainData.Foliage.Grasses.Prototypes.Count;
            int sampleCount    = args.Density;
            List <GGrassInstance> newInstances = new List <GGrassInstance>();

            for (int i = 0; i < sampleCount; ++i)
            {
                grassIndex = args.GrassIndices[Random.Range(0, args.GrassIndices.Count)];
                if (grassIndex < 0 || grassIndex >= prototypeCount)
                {
                    continue;
                }
                randomPos = args.HitPoint + Random.insideUnitSphere * args.Radius * sqrtTwo;
                rayOrigin.Set(
                    randomPos.x,
                    10000,
                    randomPos.z);
                ray.origin    = rayOrigin;
                ray.direction = rayDirection;
                if (terrain.Raycast(ray, out samplePoint, float.MaxValue))
                {
                    GUtilities.CalculateBarycentricCoord(
                        new Vector2(samplePoint.point.x, samplePoint.point.z),
                        new Vector2(args.WorldPointCorners[0].x, args.WorldPointCorners[0].z),
                        new Vector2(args.WorldPointCorners[1].x, args.WorldPointCorners[1].z),
                        new Vector2(args.WorldPointCorners[2].x, args.WorldPointCorners[2].z),
                        ref bary0);
                    GUtilities.CalculateBarycentricCoord(
                        new Vector2(samplePoint.point.x, samplePoint.point.z),
                        new Vector2(args.WorldPointCorners[0].x, args.WorldPointCorners[0].z),
                        new Vector2(args.WorldPointCorners[2].x, args.WorldPointCorners[2].z),
                        new Vector2(args.WorldPointCorners[3].x, args.WorldPointCorners[3].z),
                        ref bary1);
                    if (bary0.x >= 0 && bary0.y >= 0 && bary0.z >= 0)
                    {
                        maskUv = bary0.x * Vector2.zero + bary0.y * Vector2.up + bary0.z * Vector2.one;
                    }
                    else if (bary1.x >= 0 && bary1.y >= 0 && bary1.z >= 0)
                    {
                        maskUv = bary1.x * Vector2.zero + bary1.y * Vector2.one + bary1.z * Vector2.right;
                    }
                    else
                    {
                        continue;
                    }

                    //sample mask
                    if (clonedMask != null)
                    {
                        maskColor = clonedMask.GetPixelBilinear(maskUv.x, maskUv.y);
                        if (Random.value > maskColor.grayscale)
                        {
                            continue;
                        }
                    }
                    //sample terrain mask
                    if (args.EnableTerrainMask)
                    {
                        samplePointTexcoord = samplePoint.textureCoord;
                        maskColor           = terrainMask.GetPixelBilinear(samplePointTexcoord.x, samplePointTexcoord.y);
                        if (Random.value < maskColor.r)
                        {
                            continue;
                        }
                    }

                    //apply filter
                    GSpawnFilterArgs filterArgs = GSpawnFilterArgs.Create();
                    filterArgs.Terrain         = terrain;
                    filterArgs.Position        = samplePoint.point;
                    filterArgs.SurfaceNormal   = samplePoint.normal;
                    filterArgs.SurfaceTexcoord = samplePoint.textureCoord;

                    List <Type> suitableFilter = SuitableFilterTypes;
                    if (args.Filters != null)
                    {
                        for (int fIndex = 0; fIndex < args.Filters.Length; ++fIndex)
                        {
                            if (args.Filters[fIndex] != null &&
                                args.Filters[fIndex].Ignore != true)
                            {
                                if (suitableFilter.Contains(args.Filters[fIndex].GetType()))
                                {
                                    args.Filters[fIndex].Apply(ref filterArgs);
                                }
                            }
                            if (filterArgs.ShouldExclude)
                            {
                                break;
                            }
                        }
                    }

                    //spawn
                    if (filterArgs.ShouldExclude)
                    {
                        continue;
                    }

                    GGrassInstance grass = GGrassInstance.Create(grassIndex);
                    grass.Position = terrain.WorldPointToNormalized(filterArgs.Position);
                    grass.Rotation = filterArgs.Rotation;
                    grass.Scale    = filterArgs.Scale;
                    newInstances.Add(grass);
                }
            }

            terrain.TerrainData.Foliage.AddGrassInstances(newInstances);
            if (clonedMask != null)
            {
                Object.DestroyImmediate(clonedMask);
            }
        }