Пример #1
0
        public void Execute(int index)
        {
            GTreeInstance tree           = instances[index];
            Vector3       v              = targetPos - tree.position;
            float         sqrDistance    = v.x * v.x + v.y * v.y + v.z * v.z;
            float         sqrMaxDistance = maxDistance * maxDistance;

            cullResults[index] = sqrDistance <= sqrMaxDistance ? true : false;
        }
Пример #2
0
        private static void RestoreTreeInstances(GStylizedTerrain t, string backupName)
        {
            string prototyeIndicesFileName = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.PROTOTYPEINDEX_SUFFIX);
            string positionsFileName       = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.POSITION_SUFFIX);
            string rotationsFileName       = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.ROTATION_SUFFIX);
            string scalesFileName          = string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_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 <GTreeInstance> trees = new List <GTreeInstance>();
                for (int i = 0; i < indices.Length; ++i)
                {
                    GTreeInstance tree = GTreeInstance.Create(indices[i]);
                    tree.Position = new Vector3(
                        positions[i * 3 + 0],
                        positions[i * 3 + 1],
                        positions[i * 3 + 2]);
                    tree.Rotation = new Quaternion(
                        rotations[i * 4 + 0],
                        rotations[i * 4 + 1],
                        rotations[i * 4 + 2],
                        rotations[i * 4 + 3]);
                    tree.Scale = new Vector3(
                        scales[i * 3 + 0],
                        scales[i * 3 + 1],
                        scales[i * 3 + 2]);
                    trees.Add(tree);
                }

                t.TerrainData.Foliage.TreeInstances.Clear();
                t.TerrainData.Foliage.TreeInstances.AddRange(trees);
                t.TerrainData.SetDirty(GTerrainData.DirtyFlags.Foliage);
            }
        }
Пример #3
0
        private void DoImportTrees()
        {
            if (!ImportTreeInstancesOnly)
            {
                GTreePrototypeGroup treeGroup = DesData.Foliage.Trees;
                if (treeGroup == null ||
                    treeGroup == GRuntimeSettings.Instance.foliageDefault.trees)
                {
                    CreateNewTreePrototypesGroup = true;
                }

                if (CreateNewTreePrototypesGroup)
                {
                    treeGroup = ScriptableObject.CreateInstance <GTreePrototypeGroup>();

#if UNITY_EDITOR
                    if (!Application.isPlaying)
                    {
                        string path      = AssetDatabase.GetAssetPath(DesData);
                        string directory = Path.GetDirectoryName(path);
                        string filePath  = Path.Combine(directory, string.Format("Trees_{0}_{1}.asset", DesData.Id, System.DateTime.Now.Ticks));
                        AssetDatabase.CreateAsset(treeGroup, filePath);
                    }
#endif
                    DesData.Foliage.Trees = treeGroup;
                }

                treeGroup.Prototypes.Clear();
                TreePrototype[] treePrototypes = SrcData.treePrototypes;
                for (int i = 0; i < treePrototypes.Length; ++i)
                {
                    GTreePrototype proto = (GTreePrototype)treePrototypes[i];
                    treeGroup.Prototypes.Add(proto);
                }
                GCommon.SetDirty(treeGroup);
            }

            DesData.Foliage.TreeInstances.Clear();
            TreeInstance[] treeInstances = SrcData.treeInstances;
            for (int i = 0; i < treeInstances.Length; ++i)
            {
                GTreeInstance t = (GTreeInstance)treeInstances[i];
                DesData.Foliage.TreeInstances.Add(t);
            }

            if (DesTerrain != null)
            {
                DesData.Foliage.SetTreeRegionDirty(GCommon.UnitRect);
                DesTerrain.UpdateTreesPosition();
                DesData.Foliage.ClearTreeDirtyRegions();
            }

            DesData.SetDirty(GTerrainData.DirtyFlags.Foliage);
            //GC.Collect();
        }
        private void SpawnTreesOnTerrain(GStylizedTerrain t, Color[] maskData, List <Vector4> vertices)
        {
            int     treeIndex = -1;
            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 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 < TreeDensity; ++s)
                {
                    treeIndex = TreePrototypeIndices[Random.Range(0, TreePrototypeIndices.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;
                    }


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

                    t.TerrainData.Foliage.TreeInstances.Add(tree);
                }
            }
        }
Пример #5
0
        public void Execute(int index)
        {
            GTreeInstance tree = instances[index];
            Vector3       pos  = new Vector3(
                tree.position.x * terrainSize.x,
                tree.position.y * terrainSize.y,
                tree.position.z * terrainSize.z);

            tree.position    = pos;
            instances[index] = tree;
        }
Пример #6
0
        private void LateUpdate()
        {
            if (Terrain == null)
            {
                return;
            }
            if (Terrain.TerrainData == null)
            {
                return;
            }
            if (Terrain.TerrainData.Foliage.Trees == null)
            {
                return;
            }
            if (Terrain.TerrainData.Foliage.Trees.Prototypes.Count == 0)
            {
                return;
            }
            if (treeInstances == null || treeInstances.Length == 0)
            {
                return;
            }

            GameObject actualTarget = null;

            if (Target != null)
            {
                actualTarget = Target;
            }
            else if (Camera.main != null)
            {
                actualTarget = Camera.main.gameObject;
            }

            if (actualTarget == null)
            {
                return;
            }
            Vector3 targetLocalPos   = Terrain.transform.InverseTransformPoint(actualTarget.transform.position);
            GTreeColliderCullJob job = new GTreeColliderCullJob()
            {
                instances   = nativeTreeInstances,
                cullResults = nativeCullResults,
                maxDistance = distance,
                targetPos   = targetLocalPos
            };
            JobHandle handle = job.Schedule(nativeTreeInstances.Length, 100);

            handle.Complete();

            if (cullResults == null || cullResults.Length != nativeCullResults.Length)
            {
                cullResults = new bool[nativeCullResults.Length];
            }

            nativeCullResults.CopyTo(cullResults);

            List <GTreePrototype> prototypes = Terrain.TerrainData.Foliage.Trees.Prototypes;
            int     colliderIndex            = 0;
            Vector3 terrainPos = Terrain.transform.position;
            Vector3 worldPos   = Vector3.zero;

            if (terrain.TerrainData.Rendering.DrawTrees)
            {
                for (int i = 0; i < treeInstances.Length; ++i)
                {
                    if (cullResults[i] == false)
                    {
                        continue;
                    }

                    GTreeInstance  tree      = treeInstances[i];
                    GTreePrototype prototype = prototypes[tree.prototypeIndex];
                    if (prototype.prefab == null)
                    {
                        continue;
                    }
                    if (!prototype.hasCollider)
                    {
                        continue;
                    }

                    CapsuleCollider col = GetCollider(colliderIndex);
                    colliderIndex += 1;

                    worldPos.Set(
                        tree.position.x + terrainPos.x,
                        tree.position.y + terrainPos.y,
                        tree.position.z + terrainPos.z);
                    col.transform.position   = worldPos;
                    col.transform.rotation   = tree.rotation;
                    col.transform.localScale = tree.scale;
                    GTreeColliderInfo colliderInfo = prototype.colliderInfo;
                    col.center           = colliderInfo.center;
                    col.radius           = colliderInfo.radius;
                    col.height           = colliderInfo.height;
                    col.direction        = colliderInfo.direction;
                    col.gameObject.layer = prototype.layer;
                    if (CopyTreeTag)
                    {
                        col.gameObject.tag = prototype.prefab.tag;
                    }
                    col.gameObject.SetActive(true);
                }
            }

            int colliderCount = Colliders.Count;

            for (int i = colliderIndex; i < colliderCount; ++i)
            {
                CapsuleCollider col = GetCollider(i);
                col.gameObject.SetActive(false);
            }
        }
Пример #7
0
        private void SpawnTreeOnTerrain(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 treeIndex     = -1;
            int instanceCount = 0;
            int attempt       = 0;
            int maxAttempt    = layer.TreeInstanceCount * 100;

#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.TreeInstanceCount && attempt <= maxAttempt)
            {
                attempt += 1;

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

                treeIndex = layer.TreeIndices[Random.Range(0, layer.TreeIndices.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;
                }

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

                t.TerrainData.Foliage.TreeInstances.Add(tree);
                instanceCount += 1;
            }
#if UNITY_EDITOR
            GCommonGUI.ClearProgressBar();
#endif
        }
Пример #8
0
        private void HandleSpawnTree(GStylizedTerrain terrain, GFoliagePainterArgs args)
        {
            int        treeIndex    = -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.Trees.Prototypes.Count;
            List <GTreeInstance> newInstances = new List <GTreeInstance>();

            for (int i = 0; i < args.Density; ++i)
            {
                treeIndex = args.TreeIndices[Random.Range(0, args.TreeIndices.Count)];
                if (treeIndex < 0 || treeIndex >= 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;
                    }

                    GTreeInstance tree = GTreeInstance.Create(treeIndex);
                    tree.Position = terrain.WorldPointToNormalized(filterArgs.Position);
                    tree.Rotation = filterArgs.Rotation;
                    tree.Scale    = filterArgs.Scale;
                    newInstances.Add(tree);
                }
            }
            terrain.TerrainData.Foliage.AddTreeInstances(newInstances);
            newInstances.Clear();

            if (clonedMask != null)
            {
                Object.DestroyImmediate(clonedMask);
            }
        }
Пример #9
0
        public void Paint(Pinwheel.Griffin.GStylizedTerrain terrain, GFoliagePainterArgs args)
        {
            if (args.TreeIndices.Count == 0)
            {
                return;
            }
            if (terrain.TerrainData == null)
            {
                return;
            }
            if (terrain.TerrainData.Foliage.Trees == null)
            {
                return;
            }
            if (args.MouseEventType == GPainterMouseEventType.Up || args.ShouldCommitNow)
            {
                terrain.UpdateTreesPosition();
                terrain.TerrainData.Foliage.ClearTreeDirtyRegions();
                GCommon.SetDirty(terrain.TerrainData.Foliage);
                return;
            }

            Vector2[] uvCorners = new Vector2[args.WorldPointCorners.Length];
            for (int i = 0; i < uvCorners.Length; ++i)
            {
                uvCorners[i] = terrain.WorldPointToUV(args.WorldPointCorners[i]);
            }

            Rect dirtyRect = GUtilities.GetRectContainsPoints(uvCorners);

            if (!dirtyRect.Overlaps(new Rect(0, 0, 1, 1)))
            {
                return;
            }

            Texture2D clonedMask = null;

            if (args.Mask != null)
            {
                clonedMask = GCommon.CloneAndResizeTexture(args.Mask, 256, 256);
            }

            int     multiplier  = args.ActionType == GPainterActionType.Normal ? 1 : -1;
            int     treeIndex   = -1;
            Vector3 terrainSize = new Vector3(
                terrain.TerrainData.Geometry.Width,
                terrain.TerrainData.Geometry.Height,
                terrain.TerrainData.Geometry.Length);
            Vector3 localPos  = Vector3.zero;
            Vector3 worldPos  = Vector3.zero;
            Vector3 bary0     = Vector3.zero;
            Vector3 bary1     = Vector3.zero;
            Vector2 maskUv    = Vector2.zero;
            Color   maskColor = Color.white;
            Vector3 scale     = Vector3.zero;
            List <GTreeInstance> instances = terrain.TerrainData.Foliage.TreeInstances;
            int instanceCount = instances.Count;

            for (int i = 0; i < instanceCount; ++i)
            {
                treeIndex = args.TreeIndices[Random.Range(0, args.TreeIndices.Count)];
                GTreeInstance tree = instances[i];
                if (tree.PrototypeIndex != treeIndex)
                {
                    continue;
                }

                localPos.Set(
                    tree.Position.x * terrainSize.x,
                    tree.Position.y * terrainSize.y,
                    tree.Position.z * terrainSize.z);
                worldPos = terrain.transform.TransformPoint(localPos);
                GUtilities.CalculateBarycentricCoord(
                    new Vector2(worldPos.x, worldPos.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(worldPos.x, worldPos.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;
                }

                if (clonedMask != null)
                {
                    maskColor = clonedMask.GetPixelBilinear(maskUv.x, maskUv.y);
                    if (Random.value > maskColor.grayscale)
                    {
                        continue;
                    }
                }

                scale.Set(
                    Mathf.Max(0, tree.Scale.x + multiplier * maskColor.grayscale * args.ScaleStrength * GUtilities.DELTA_TIME),
                    Mathf.Max(0, tree.Scale.y + multiplier * maskColor.grayscale * args.ScaleStrength * GUtilities.DELTA_TIME),
                    Mathf.Max(0, tree.Scale.z + multiplier * maskColor.grayscale * args.ScaleStrength * GUtilities.DELTA_TIME));

                GSpawnFilterArgs filterArgs = GSpawnFilterArgs.Create();
                filterArgs.Terrain  = terrain;
                filterArgs.Position = worldPos;
                filterArgs.Rotation = tree.Rotation;
                filterArgs.Scale    = scale;
                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;
                        }
                    }
                }

                tree.Scale   = filterArgs.Scale;
                instances[i] = tree;
            }

            terrain.TerrainData.Foliage.SetTreeRegionDirty(dirtyRect);
            terrain.TerrainData.SetDirty(GTerrainData.DirtyFlags.Foliage);
            GUtilities.MarkCurrentSceneDirty();
        }
Пример #10
0
        private static void BackupTreeInstances(GStylizedTerrain t, string backupName)
        {
            if (t.TerrainData.Foliage.Trees == null)
            {
                return;
            }
            List <GTreeInstance> trees = t.TerrainData.Foliage.TreeInstances;

            int[]   protoIndices = new int[trees.Count];
            float[] positions    = new float[trees.Count * 3];
            float[] rotations    = new float[trees.Count * 4];
            float[] scales       = new float[trees.Count * 3];
            for (int i = 0; i < trees.Count; ++i)
            {
                GTreeInstance tree = trees[i];
                protoIndices[i] = tree.PrototypeIndex;

                positions[i * 3 + 0] = tree.Position.x;
                positions[i * 3 + 1] = tree.Position.y;
                positions[i * 3 + 2] = tree.Position.z;

                rotations[i * 4 + 0] = tree.Rotation.x;
                rotations[i * 4 + 1] = tree.Rotation.y;
                rotations[i * 4 + 2] = tree.Rotation.z;
                rotations[i * 4 + 3] = tree.Rotation.w;

                scales[i * 3 + 0] = tree.Scale.x;
                scales[i * 3 + 1] = tree.Scale.y;
                scales[i * 3 + 2] = tree.Scale.z;
            }

            byte[] protoIndicesData = new byte[Buffer.ByteLength(protoIndices)];
            Buffer.BlockCopy(protoIndices, 0, protoIndicesData, 0, protoIndicesData.Length);
            protoIndicesData = GCompressor.Compress(protoIndicesData);

            byte[] positionsData = new byte[Buffer.ByteLength(positions)];
            Buffer.BlockCopy(positions, 0, positionsData, 0, positionsData.Length);
            positionsData = GCompressor.Compress(positionsData);

            byte[] rotationsData = new byte[Buffer.ByteLength(rotations)];
            Buffer.BlockCopy(rotations, 0, rotationsData, 0, rotationsData.Length);
            rotationsData = GCompressor.Compress(rotationsData);

            byte[] scalesData = new byte[Buffer.ByteLength(scales)];
            Buffer.BlockCopy(scales, 0, scalesData, 0, scalesData.Length);
            scalesData = GCompressor.Compress(scalesData);

            GBackupFile.Create(
                backupName,
                string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.PROTOTYPEINDEX_SUFFIX),
                protoIndicesData);
            GBackupFile.Create(
                backupName,
                string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.POSITION_SUFFIX),
                positionsData);
            GBackupFile.Create(
                backupName,
                string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.ROTATION_SUFFIX),
                rotationsData);
            GBackupFile.Create(
                backupName,
                string.Format("{0}_{1}_{2}", t.TerrainData.Id, GBackupFile.TREE_SUFFIX, GBackupFile.SCALE_SUFFIX),
                scalesData);
        }
Пример #11
0
        public void Execute(int index)
        {
            GTreeInstance tree = instances[index];

            if (tree.prototypeIndex < 0 || tree.prototypeIndex >= prototypePivotOffset.Length)
            {
                cullResult[index] = flagCulled;
                return;
            }

            if (tree.position.x < cullBoxMin.x || tree.position.x > cullBoxMax.x ||
                tree.position.y < cullBoxMin.y || tree.position.y > cullBoxMax.y ||
                tree.position.z < cullBoxMin.z || tree.position.z > cullBoxMax.z)
            {
                cullResult[index] = flagCulled;
                return;
            }

            float   pivotOffset = prototypePivotOffset[tree.prototypeIndex];
            Vector3 worldPos    = new Vector3(
                tree.position.x * terrainSize.x + terrainPos.x,
                tree.position.y * terrainSize.y + terrainPos.y + pivotOffset,
                tree.position.z * terrainSize.z + terrainPos.z);

            float sqrDistance     = Vector3.SqrMagnitude(worldPos - cameraPos);
            float sqrTreeDistance = treeDistance * treeDistance;

            if (sqrDistance > sqrTreeDistance)
            {
                cullResult[index] = flagCulled;
                return;
            }

            Vector3 baseScale  = prototypeBaseScale[tree.prototypeIndex];
            Vector3 worldScale = new Vector3(
                tree.scale.x * baseScale.x,
                tree.scale.y * baseScale.y,
                tree.scale.z * baseScale.z);

            bool testFrustum = prototypeWillDoFrustumTest[tree.prototypeIndex];

            if (testFrustum)
            {
                BoundingSphere b = prototypeBounds[tree.prototypeIndex];
                b.position = worldPos;
                b.radius  *= Mathf.Max(worldScale.x, Mathf.Max(worldScale.y, worldScale.z));
                b.radius  += cullVolumeBias;
                if (!DoFrustumTest(frustum, b))
                {
                    cullResult[index] = flagCulled;
                    return;
                }
            }

            float sqrBillboardStart = billboardStart * billboardStart;

            if (sqrDistance >= sqrBillboardStart)
            {
                cullResult[index] = flagBillboard;
            }
            else
            {
                cullResult[index] = flagVisible;
            }

            if (prototypeIndices[index] < 0)
            {
                Quaternion baseRotation  = prototypeBaseRotation[tree.prototypeIndex];
                Quaternion worldRotation = tree.rotation * baseRotation;

                Matrix4x4 matrix = Matrix4x4.TRS(worldPos, worldRotation, worldScale);
                transforms[index]       = matrix;
                prototypeIndices[index] = tree.prototypeIndex;
            }
        }