/// <summary>
        /// Writes <paramref name="offset"/> to <paramref name="terrain"/> height data.
        /// </summary>
        /// <param name="terrainData">Terrain to modify.</param>
        /// <param name="offset">Height offset.</param>
        private static TerrainUtils.NativeHeights WriteTerrainDataOffset(Terrain terrain, float offset)
        {
            var terrainData      = terrain.terrainData;
            var nativeHeightData = TerrainUtils.FindHeights(terrainData);
            var tmp = new float[, ] {
                { 0.0f }
            };

            for (int i = 0; i < nativeHeightData.Heights.Count; ++i)
            {
                var newHeight = nativeHeightData.Heights[i] += offset;

                var vertexX = i % nativeHeightData.ResolutionX;
                var vertexY = i / nativeHeightData.ResolutionY;

                tmp[0, 0] = (float)newHeight / terrainData.heightmapScale.y;
                terrainData.SetHeightsDelayLOD(TerrainUtils.TerrainDataResolution(terrainData) - vertexX - 1,
                                               TerrainUtils.TerrainDataResolution(terrainData) - vertexY - 1,
                                               tmp);
            }
#if UNITY_2019_1_OR_NEWER
            terrainData.SyncHeightmap();
#else
            terrain.ApplyDelayedHeightmapModification();
#endif

            return(nativeHeightData);
        }
        public bool FindAllTreeInstancesAroundPosition(Vector3 worldPosition, float selectionRange, Terrain terrain, ref List <TreeNode> nodes, bool clear = true)
        {
            if (clear)
            {
                nodes.Clear();
            }

            TerrainUtils.WorldPositionToTerrain(worldPosition, terrain, out var belongsToTile);

            if (!belongsToTile)
            {
                return(false);
            }

            var treeData = _terrainToTreeData[terrain];
            var quadTree = treeData.QuadTree;

            var rect = new Rect(worldPosition.x, worldPosition.z, selectionRange, selectionRange);

            quadTree.RetrieveObjectsInAreaNoAlloc(rect, ref nodes);

            if (!nodes.Any())
            {
                Debug.Log("No nodes found in area");
                return(false);
            }

            return(true);
        }
Beispiel #3
0
    public void GenerateTreePrototypeData()
    {
        List <string>     prefabNames = new List <string>();
        List <GameObject> prefabs     = new List <GameObject>();

        System.Array.ForEach(m_ItemsToExtract, (x) => { prefabNames.Add(x.m_ItemPrefab.name); prefabs.Add(x.m_ItemPrefab); });

        if (TerrainUtils.TreeHashCheck(prefabNames.ToArray()))
        {
            Debug.LogError("Tree name hash collision, fix!");
            return;
        }

        GameObject[] proto = prefabs.ToArray();
        List <TreeSystemPrototypeData> managed = new List <TreeSystemPrototypeData>();

        for (int i = 0; i < proto.Length; i++)
        {
            GameObject prefab = proto[i];

            if (PrefabUtility.GetPrefabType(prefab) != PrefabType.ModelPrefab ||
                prefab.GetComponent <LODGroup>() == null ||
                prefab.GetComponentInChildren <BillboardRenderer>() == null)
            {
                Debug.LogError("Invalid prefab: " + prefab.name + ". Make sure that it is a SpeedTree, that it contains a 'LODGroup' and that it has a 'BillboardRenderer' component.");
                continue;
            }

            TreeSystemPrototypeData data = new TreeSystemPrototypeData();
            data.m_TreePrototype = prefab;
            // Use hash here instead of the old index
            data.m_TreePrototypeHash = TUtils.GetStableHashCode(prefab.name);

            // Instantiate LOD data that is going to be populated at runtime
            LOD[] lods = prefab.GetComponent <LODGroup>().GetLODs();
            TreeSystemLODData[] lodData = new TreeSystemLODData[lods.Length];
            // Generate some partial LOD data that doesn't have to be calculated at runtime
            data.m_LODData = lodData;

            for (int lod = 0; lod < lodData.Length; lod++)
            {
                TreeSystemLODData d = new TreeSystemLODData();
                lodData[lod] = d;
            }

            data.m_MaxLod3DIndex = lodData.Length - 2;

            managed.Add(data);
        }

        m_ManagedPrototypes = managed.ToArray();

        // Try and set the prototypes to our tree system
        TreeSystem t = FindObjectOfType <TreeSystem>();

        if (t)
        {
            t.m_ManagedPrototypes = m_ManagedPrototypes;
        }
    }
Beispiel #4
0
    /**
     * Parse file and render buildings when scene starts
     */
    private void Start()
    {
        Caching.ClearCache();
        //hide and lock cursor into center
        UiUtils.HideCursor();

        TutorialUtils.InitTutorial(TutorialCanvas, Settings);
        BuildingPickerCanvas.SetActive(false);
        ExitCanvasDialog.SetActive(false);

        //load XML file tags
        var xmlFile = new XmlDocument();

        //load file
        xmlFile.Load(FileUtils.GetFullMapPath(Map.MapName));
        //get node and way tags
        var nodeTags = xmlFile.SelectNodes(".//node");
        var wayTags  = xmlFile.SelectNodes(".//way");
        //cache IDs in node tag for coordinate pairing
        var nodeTagIds = CacheNodeTagIds(nodeTags);

        //parse building and roads
        var buildings      = BuildingLoader.Get().LoadFile(nodeTags, nodeTagIds, wayTags);
        var roads          = RoadLoader.Get().LoadFile(nodeTags, nodeTagIds, wayTags);
        var trees          = TreeLoader.Get().LoadFile();
        var mapMiddlePoint = GetMiddlePoint(buildings, roads);

        //download elevation data
        AltitudeLoader.Get().SetAltitude(TerrainUtils.GetLatLngGrid(mapMiddlePoint));
        //render terrain, buildings, roads etc.
        StartCoroutine(RenderObjects(mapMiddlePoint, buildings, roads, trees));
    }
Beispiel #5
0
    private void Start()
    {
        switch (MenuManager.terrainType)
        {
        case TerrainType.PERMEAVEL:
            range = 20;
            riverHeightCountMax = 4.0f;
            break;

        case TerrainType.SEMI_PERMEAVEL:
            range = 35;
            riverHeightCountMax = 8.0f;
            break;

        case TerrainType.IMPERMEAVEL:
            range = 50;
            riverHeightCountMax = 16.0f;
            break;
        }

        minPosition = river.position.y;
        maxPosition = river.position.y + range;

        TerrainUtils terrainUtils = new TerrainUtils(terrain.terrainData);

        terrainUtils.SetTerrainTexture(MenuManager.terrainType);
    }
Beispiel #6
0
    private int DecideWallVarient(int x, int y)
    {
        Terrain[,] locality = new Terrain[3, 3];
        for (int j = x - 1; j <= x + 1; j++)
        {
            for (int k = y - 1; k <= y + 1; k++)
            {
                if (Util.WithinArrayBounds2D(ref Locations, j, k))
                {
                    locality[j - (x - 1), k - (y - 1)] = Locations[j, k].terrain;
                }
                else
                {
                    locality[j - (x - 1), k - (y - 1)] = Terrain.Empty;
                }
            }
        }

        for (int i = 0; i < Constants.WALL_VARIENTS_MAPPING.GetLength(0); i++)
        {
            if (TerrainUtils.EqualArrays2D(locality, Util.Get2DFrom3D(Constants.WALL_VARIENTS_MAPPING, i)))
            {
                return(i);
            }
        }
        return(0);
    }
        public void Generate()
        {
            UnityEngine.Random.InitState(Seed);

            //pick a random position for the feature(s)
            var     position      = this.Generator.GetRandomPointInChunk();
            float   sampleheight  = ParentChunk.Terrain.terrainData.GetHeight(position.X, position.Z);
            Vector3 worldPosition = new Vector3(
                (ChunkCoords.X * TerrainChunkSettings.ChunkSize) + position.X,
                sampleheight - 0.5f,
                (ChunkCoords.Z * TerrainChunkSettings.ChunkSize) + position.Z
                );
            var        randomRotation = Quaternion.Euler(0, UnityEngine.Random.Range(0, 360), 0);
            GameObject dungeontower   = (GameObject)Resources.Load("DungeonTower");
            var        spawntower     = Instantiate(dungeontower, worldPosition, randomRotation);

            Generator.FeatureAssets.Add(
                spawntower
                );


            //setting the seed for the dungeon in the tower we just placed
            DungeonEntranceTrigger enterancetrigger = spawntower.gameObject.transform.GetComponentInChildren <DungeonEntranceTrigger>();

            enterancetrigger.Seed = ChunkCoords.X * ChunkCoords.Z + 123456;

            //raycasting the tower to the ground level
            float distanceToGround = TerrainUtils.RaycastToTerrain(spawntower.transform.position);
            var   pos = spawntower.transform.position;

            pos = new Vector3(pos.x, (pos.y + distanceToGround), pos.z);
            spawntower.transform.position = pos;
            spawntower.transform.SetParent(this.transform);
            RemoveOverlappingAssets();
        }
Beispiel #8
0
    public void GenerateTrees()
    {
        if (m_ManagedTerrains.Length != m_CellSizes.Length)
        {
            Debug.LogError("Invalid cell sizes for the count of managed terrains!");
            return;
        }

        for (int i = 0; i < m_ManagedTerrains.Length; i++)
        {
            Terrain t = m_ManagedTerrains[i];

            if (t.transform.rotation != Quaternion.identity)
            {
                Debug.LogError("Terrains must not be rotated, sorry!");
                return;
            }

            if (TerrainUtils.CanGridify(t, m_CellSizes[i]) == false)
            {
                Debug.LogError("Can't gridify terrain [" + t + "] with cell size: " + m_CellSizes[i]);
                return;
            }
        }

        List <TreeSystemTerrain> systemTerrains = new List <TreeSystemTerrain>();

        // Set the cell holder in the origin and mark it static
        if (!m_CellHolder)
        {
            m_CellHolder = new GameObject("TreeSystemCellHolder");
        }

        m_CellHolder.transform.position   = Vector3.zero;
        m_CellHolder.transform.localScale = Vector3.one;
        m_CellHolder.transform.rotation   = Quaternion.identity;
        m_CellHolder.isStatic             = true;

        for (int i = 0; i < m_ManagedTerrains.Length; i++)
        {
            GameObject cellHolder = new GameObject();
            cellHolder.isStatic = true;
            cellHolder.name     = m_ManagedTerrains[i].name + "_TreeSystem_Managed_" + i;

            // Destroy any previous data
            if (m_CellHolder.transform.Find(cellHolder.name))
            {
                DestroyImmediate(m_CellHolder.transform.Find(cellHolder.name).gameObject);
            }

            // Set parent
            cellHolder.transform.parent = m_CellHolder.transform;

            systemTerrains.Add(ProcessTerrain(m_ManagedTerrains[i], m_CellSizes[i], cellHolder));
        }

        // TODO: implement a scriptable object maybe? But it works fine with 250k trees so...
        FindObjectOfType <TreeSystem>().m_ManagedTerrains = systemTerrains.ToArray();
    }
    public List <WorldPos> OccupiedBlocks()
    {
        List <WorldPos> pos = new List <WorldPos>();

        pos.Add(TerrainUtils.GetBlockPos(_playerRayOrigin));
        pos.Add(new WorldPos(pos[0].x, pos[0].y - 1));
        return(pos);
    }
        public int FindTreeInstanceThroughBVH(Vector3 worldPosition, out Terrain ownerTerrain, out TreeNode node)
        {
            node         = null;
            ownerTerrain = null;

            foreach (var pair in _terrainToTreeData)
            {
                var terrain = pair.Key;
                var local   = TerrainUtils.WorldPositionToTerrain(worldPosition, terrain, out bool belongsToTile);
                if (!belongsToTile)
                {
                    continue;
                }

                ownerTerrain = terrain;

                var quadTree = pair.Value.QuadTree;

                var rect = new Rect(worldPosition.x, worldPosition.z, SelectionRange, SelectionRange);

                var nodes = quadTree.RetrieveObjectsInArea(rect);
                _lastCheckedPosition = worldPosition;

                if (!nodes.Any())
                {
                    Debug.Log("Found no tree nodes around the specified area through BVH check");
                    return(-1);
                }

                if (nodes.Count == 1)
                {
                    node = nodes[0];
                    Debug.Log($"Found exactly one tree node around the specified area through BVH check. Index: {node.TreeIndex}");
                    return(nodes[0].TreeIndex);
                }
                else
                {
                    Debug.Log($"Found multiple tree nodes around the specified area through BVH check. Count: {nodes.Count}");

                    var   twoDimWorldPos = new Vector2(worldPosition.x, worldPosition.z);
                    float minDist        = Single.MaxValue;
                    foreach (var treeNode in nodes)
                    {
                        var squaredDistance = (twoDimWorldPos - treeNode.Position).SqrMagnitude();
                        if (squaredDistance >= minDist)
                        {
                            node    = treeNode;
                            minDist = squaredDistance;
                        }
                    }

                    return(-1);
                }
            }

            return(-1);
        }
Beispiel #11
0
    void Awake()
    {
        if (GameObject.Find("Terrain")) terrainUtils = GameObject.Find ("Terrain").GetComponent<TerrainUtils>();
        selector = gameObject.AddComponent<Selector>();
        input = gameObject.AddComponent<InputController>();
        time = gameObject.AddComponent<TimeController>();

        commanderSkin = Resources.Load("CommanderGUI") as GUISkin;
    }
        private void GenerateHeightmapThread()
        {
            BiomeType[] impactors = new BiomeType[2]; //Out to BIOME_SAMPLES
            int         offsetX   = this.Position.X * (Settings.HeightmapResolution);
            int         offsetZ   = this.Position.Z * (Settings.HeightmapResolution);

            Heightmap = new float[Settings.HeightmapResolution, Settings.HeightmapResolution];

            lock (HeightmapThreadLockObject)
            {
                ChunkBlend = WorldGenerator.ChunkBlendProvider;
                impactors  = WorldGenerator.GetChunkBiomes(Position);
                this.Biomes.AddRange(impactors);
                //Debug.Log("Chunk " + this.Position.X + ", " + this.Position.Z + ":: " + impactors[0] + ", " + impactors[1]);
                var biomeA       = GetBiomeNoiseProvider(impactors[0]);
                var biomeB       = GetBiomeNoiseProvider(impactors[1]);
                var SelectModule = new Select(biomeA, biomeB, this.ChunkBlend.Provider);
                SelectModule.FallOff = 0.125f;
                SelectModule.SetBounds(0, 0.3);

                var heightmap = new float[Settings.HeightmapResolution, Settings.HeightmapResolution];

                for (var zRes = 0; zRes < Settings.HeightmapResolution; zRes++)
                {
                    for (var xRes = 0; xRes < Settings.HeightmapResolution; xRes++)
                    {
                        var xCoordinate = Position.X + (float)xRes / (Settings.HeightmapResolution - 1);
                        var zCoordinate = Position.Z + (float)zRes / (Settings.HeightmapResolution - 1);

                        heightmap[zRes, xRes] = (float)SelectModule.GetValue(xCoordinate, 0, zCoordinate) / 2f + 0.5f;
                    }
                }

                //if this chunk is a world edge, we need to  mask it to blend with the ocean
                if (this.EdgeType != ChunkEdge.NotEdge)
                {
                    Debug.Log("[" + Position.X + "," + Position.Z + "] is a " + this.EdgeType + " edge so will mask.");
                    //interpolation causes seams, we fix that here:

                    float[,] mask = TerrainUtils.GetEdgeMask(this.EdgeType);
                    for (int x = 0; x < TerrainChunkSettings.ChunkSize; x++)
                    {
                        for (int z = 0; z < TerrainChunkSettings.ChunkSize; z++)
                        {
                            heightmap[x, z] *= mask[x, z];
                        }
                    }
                }

                Heightmap = heightmap;
            }
            this.HeightmapReady = true;
        }
Beispiel #13
0
    public void PrintPossibleCellCounts()
    {
        Debug.Log("------------------------------------");

        foreach (TerrainExtract t in m_ManagedTerrains)
        {
            Debug.Log("---- BEGIN TERRAIN INFO ----");
            TerrainUtils.CellInfo(t.m_ManagedTerrain);
            Debug.Log("---- END TERRAIN INFO ----");
        }

        Debug.Log("------------------------------------");
    }
        public int FindTreeInstanceInTerrain(Vector3 worldPosition, Terrain terrain, out TreeNode node)
        {
            node = null;
            TerrainUtils.WorldPositionToTerrain(worldPosition, terrain, out var belongsToTile);

            if (!belongsToTile)
            {
                return(-1);
            }

            var treeData = _terrainToTreeData[terrain];
            var quadTree = treeData.QuadTree;

            var rect = new Rect(worldPosition.x, worldPosition.z, SelectionRange, SelectionRange);

            var nodes = quadTree.RetrieveObjectsInArea(rect);

            _lastCheckedPosition = worldPosition;

            if (!nodes.Any())
            {
                Debug.Log("Found no tree nodes around the specified area through BVH check");
                return(-1);
            }

            if (nodes.Count == 1)
            {
                node = nodes[0];
                Debug.Log($"Found exactly one tree node around the specified area through BVH check. Index: {node.TreeIndex}");
                return(nodes[0].TreeIndex);
            }
            else
            {
                Debug.Log($"Found multiple tree nodes around the specified area through BVH check. Count: {nodes.Count}");
                // TODO find the closest through raw distance and return it
                var   twoDimWorldPos = new Vector2(worldPosition.x, worldPosition.z);
                float minDist        = Single.MaxValue;
                foreach (var treeNode in nodes)
                {
                    var squaredDistance = (twoDimWorldPos - treeNode.Position).SqrMagnitude();
                    if (squaredDistance >= minDist)
                    {
                        node    = treeNode;
                        minDist = squaredDistance;
                    }
                }

                return(-1);
            }
        }
Beispiel #15
0
        public void Cut(CutEntry cutEntry, bool cutDetails)
        {
            if (cutEntry.RemoveDetailsOnly == 0)
            {
                transparencyMap.SetPixel(cutEntry.X, cutEntry.Z, Color.clear);
            }

            if (cutDetails)
            {
                var tData        = digger.Terrain.terrainData;
                var detailMapPos = TerrainUtils.AlphamapPositionToDetailMapPosition(tData, cutEntry.X, cutEntry.Z);
                CutDetailMaps(tData, detailMapPos.y, detailMapPos.x);
            }
        }
        public void PlaceTreeUnderCursor(Vector3 worldPosition, Terrain terrain)
        {
            if (terrain == null)
            {
                Debug.LogError("Tried to place a tree but the terrain was null");
                return;
            }

            var localSpace           = TerrainUtils.WorldPositionToTerrain(worldPosition, terrain, out var belongsToTile);
            var normalizedLocalSpace = localSpace / (terrain.terrainData.heightmapResolution - TerrainUtils.UnityTextureBorder);

            var treeInstance = new TreeInstance();

            treeInstance.position       = normalizedLocalSpace;
            treeInstance.color          = Color.green;
            treeInstance.lightmapColor  = Color.green;
            treeInstance.prototypeIndex = IndexOfLivePrototype;
            treeInstance.heightScale    = 1;
            treeInstance.rotation       = 1;
            treeInstance.widthScale     = 1;


            var treeInstancesCopy = terrain.terrainData.treeInstances.ToArray();
            var length            = treeInstancesCopy.Length;

            Array.Resize(ref treeInstancesCopy, length + 1);
            treeInstancesCopy[length] = treeInstance;

            terrain.terrainData.SetTreeInstances(treeInstancesCopy, false);

            var treeData = _terrainToTreeData[terrain];
            var treeNode = new TreeNode()
            {
                Position  = new Vector2(worldPosition.x, worldPosition.z),
                TreeIndex = length,
                TreeType  = (byte)IndexOfLivePrototype
            };

            var quadTree = treeData.QuadTree;

            quadTree.Insert(treeNode);

            var handler = treeData.Handler;

            handler.MarkTreeLive(terrain.terrainData.GetTreeInstance(length));

            terrain.Flush();
        }
Beispiel #17
0
    void Awake()
    {
        weightedSpawnables = new WeightedList <Spawnable>();

        foreach (Spawnable s in Spawnables)
        {
            weightedSpawnables.Add(s, s.weight);
        }

        WorldContainer = new GameObject("WorldContainer");
        WorldContainer.transform.parent = transform;
        Terrain = GetComponentInChildren <Terrain>();
        bounds  = TerrainUtils.GetTerrainBounds(Terrain);

        positions = new List <ObjectLocation>();
    }
Beispiel #18
0
    public void PrintPossibleCellCounts()
    {
        Log.d("------------------------------------");

        Log.d("---- BEGIN MAIN TERRAIN INFO ----");
        TerrainUtils.CellInfo(m_MainManagedTerrain);
        Log.d("---- END MAIN TERRAIN INFO ----");

        foreach (Terrain t in m_ManagedTerrains)
        {
            Log.d("---- BEGIN TERRAIN INFO ----");
            TerrainUtils.CellInfo(t);
            Log.d("---- END TERRAIN INFO ----");
        }

        Log.d("------------------------------------");
    }
Beispiel #19
0
        /// <summary>
        /// Writes <paramref name="offset"/> to <paramref name="terrain"/> height data.
        /// </summary>
        /// <param name="terrainData">Terrain to modify.</param>
        /// <param name="offset">Height offset.</param>
        private static TerrainUtils.NativeHeights WriteTerrainDataOffset(Terrain terrain, float offset)
        {
            var terrainData      = terrain.terrainData;
            var nativeHeightData = TerrainUtils.FindHeights(terrainData);
            var tmp = new float[, ] {
                { 0.0f }
            };
            var dataMaxHeight    = terrainData.size.y;
            var maxClampedHeight = -1.0f;

            for (int i = 0; i < nativeHeightData.Heights.Count; ++i)
            {
                var newHeight = nativeHeightData.Heights[i] += offset;

                var vertexX = i % nativeHeightData.ResolutionX;
                var vertexY = i / nativeHeightData.ResolutionY;

                tmp[0, 0] = (float)newHeight / terrainData.heightmapScale.y;
                if (newHeight > dataMaxHeight)
                {
                    maxClampedHeight = System.Math.Max(maxClampedHeight, (float)newHeight);
                }

                terrainData.SetHeightsDelayLOD(TerrainUtils.TerrainDataResolution(terrainData) - vertexX - 1,
                                               TerrainUtils.TerrainDataResolution(terrainData) - vertexY - 1,
                                               tmp);
            }

            if (maxClampedHeight > 0.0f)
            {
                Debug.LogWarning("Terrain heights were clamped: UnityEngine.TerrainData max height = " +
                                 dataMaxHeight +
                                 " and AGXUnity.Model.DeformableTerrain.MaximumDepth = " +
                                 offset +
                                 ". Resolve this by increasing max height and lower the terrain or decrease Maximum Depth.", terrain);
            }

#if UNITY_2019_1_OR_NEWER
            terrainData.SyncHeightmap();
#else
            terrain.ApplyDelayedHeightmapModification();
#endif

            return(nativeHeightData);
        }
    public override void OnInspectorGUI()
    {
        TerrainUtils utils = (TerrainUtils)target;

        serializedObject.Update();
        if (utils == null)
        {
            return;
        }

        lineStartProp.vector3Value = EditorGUILayout.Vector3Field("LineStartPos", lineStartProp.vector3Value);
        lineEndProp.vector3Value   = EditorGUILayout.Vector3Field("LineEndPos", lineEndProp.vector3Value);
        lineWidthProp.floatValue   = EditorGUILayout.FloatField("Line Width", lineWidthProp.floatValue);
        if (EditorGUILayout.ToggleLeft("Paint Line", false))
        {
            utils.PaintLine();
        }
        serializedObject.ApplyModifiedProperties();
    }
Beispiel #21
0
 private void SmoothWorld(ref Terrain[,] world)
 {
     Terrain[,] newWorld = (Terrain[, ])world.Clone();
     for (int x = 1; x < world.GetLength(0) - 1; x++)
     {
         for (int y = 1; y < world.GetLength(1) - 1; y++)
         {
             if (TerrainUtils.CountLocalTerrain(ref world, Terrain.Wall, x, y) >= 5)
             {
                 newWorld[x, y] = Terrain.Wall;
             }
             else
             {
                 newWorld[x, y] = Terrain.Floor;
             }
         }
     }
     world = newWorld;
 }
Beispiel #22
0
        /// <summary>
        /// Creates native height field object given current Unity Terrain
        /// object - if present (in component level or in parents).
        /// </summary>
        /// <returns>Native height field shape object.</returns>
        protected override agxCollide.Shape CreateNative()
        {
            var terrainData = TerrainData;

            if (terrainData == null)
            {
                return(null);
            }

            var heights = TerrainUtils.FindHeights(terrainData);
            var hf      = new agxCollide.HeightField((uint)heights.ResolutionX,
                                                     (uint)heights.ResolutionY,
                                                     GetWidth(),
                                                     GetHeight(),
                                                     heights.Heights,
                                                     false,
                                                     150.0);

            return(hf);
        }
    private void Update()
    {
        // Block Interaction
        Plane playerPlane = new Plane(Vector3.back, transform.position);

        _playerRayOrigin = new Vector3(transform.position.x, transform.position.y + 0.4f, transform.position.z);
        Ray          mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit2D hit;

        float d;

        if (playerPlane.Raycast(mouseRay, out d))
        {
            Vector3 hitPoint = mouseRay.GetPoint(d);

            if (Input.GetMouseButtonDown(0))
            {
                hit = Physics2D.Raycast(_playerRayOrigin, (hitPoint - _playerRayOrigin).normalized, 100, RaycastMask);
                Debug.Log(hit.collider.name);
                if (hit.collider != null)
                {
                    TerrainUtils.SetBlock(hit, new BlockAir());
                }
            }

            if (Input.GetMouseButtonDown(1))
            {
                hit = Physics2D.Raycast(_playerRayOrigin, (hitPoint - _playerRayOrigin).normalized, 100, RaycastMask);
                if (hit.collider != null)
                {
                    TerrainUtils.SetBlock(hit, new Block(), true);
                }
            }
            Debug.DrawRay(_playerRayOrigin, (hitPoint - _playerRayOrigin).normalized, Color.red);
        }

        Debug.DrawRay(Camera.main.transform.position, mouseRay.direction, Color.yellow);
    }
Beispiel #24
0
        /// <summary>
        /// Invoked when the tool will be updated
        /// </summary>
        protected override void OnToolUpdate()
        {
            base.OnToolUpdate();

            m_mouseTerrainPosition = TerrainUtils.GetTerrainMousePosition();

            // Checks if mouse is over UI
            if (!m_mouseHoverOptionPanel && !m_mouseHoverScrollablePanel && !m_mouseHoverToolbar)
            {
                m_action?.OnUpdate(m_mouseTerrainPosition.Value);

                if (Input.GetMouseButtonDown(0))
                {
                    m_action?.OnLeftMouseIsDown(m_mouseTerrainPosition.Value);
                }
                else if (Input.GetMouseButton(0))
                {
                    m_action?.OnLeftMouseIsPressed(m_mouseTerrainPosition.Value);
                }
                else if (Input.GetMouseButtonUp(0))
                {
                    m_action?.OnLeftMouseIsUp(m_mouseTerrainPosition.Value);
                }

                if (Input.GetMouseButtonDown(1))
                {
                    m_action?.OnRightMouseIsDown(m_mouseTerrainPosition.Value);
                }
                else if (Input.GetMouseButton(1))
                {
                    m_action?.OnRightMouseIsPressed(m_mouseTerrainPosition.Value);
                }
                else if (Input.GetMouseButtonUp(1))
                {
                    m_action?.OnRightMouseIsUp(m_mouseTerrainPosition.Value);
                }
            }
        }
        public void GlobalGenerateTrees(int count = 10000)
        {
            for (var index = _terrainToTreeData.Count - 1; index >= 0; index--)
            {
                var dataPair = _terrainToTreeData.ElementAt(index);
                var terrain  = dataPair.Key;
                var treeData = dataPair.Value;

                var handler  = treeData.Handler;
                var quadTree = treeData.QuadTree;
                quadTree.Clear();

                TerrainUtils.MassPlaceTreesOfPrototype(terrain.terrainData, count, IndexOfLivePrototype, Color.green);
                terrain.Flush();

                var regenTreeData = PrepareTerrainTreeData(terrain);
                regenTreeData.Handler = handler;

                _terrainToTreeData[terrain]  = regenTreeData;
                _handlersToTreeData[handler] = regenTreeData;

                handler.ReInit(regenTreeData);
            }
        }
 public void Execute(int i)
 {
     results[i] = TerrainUtils.TerrainVectorBarycentric(positions[i], nativeHeightmap, -size / 2f, -size / 2f, 0f, size, maxHeight, res).y;
 }
    void HeightsTest()
    {
        Unity.Mathematics.Random r = new Unity.Mathematics.Random(seed);
        float3[] positions         = new float3[numberOfPoints];

        for (int i = 0; i < numberOfPoints; i++)
        {
            positions[i] = (new Vector3(r.NextFloat(-size / 2f, size / 2f), 0f, r.NextFloat(-size / 2f, size / 2f)));
        }

        NativeArray <float>  nativeHeightmap = TerrainUtils.ManagedToNativeHeightmap(heightmap);
        NativeArray <float3> nativePositions = new NativeArray <float3>(positions, Allocator.Persistent);
        NativeArray <float>  yBarycentricJob = new NativeArray <float>(numberOfPoints, Allocator.Persistent);
        NativeArray <float>  steepnessJob    = new NativeArray <float>(numberOfPoints, Allocator.Persistent);

        float[] yUnity         = new float[numberOfPoints];
        float[] yBilinear      = new float[numberOfPoints];
        float[] yInlined       = new float[numberOfPoints];
        float[] yNativeArray   = new float[numberOfPoints];
        float[] yBarycentric   = new float[numberOfPoints];
        float[] steepnessUnity = new float[numberOfPoints];

        // Unity;
        Stopwatch stopwatch = new Stopwatch();

        stopwatch.Start();

        for (int i = 0; i < numberOfPoints; i++)
        {
            yUnity[i] = TerrainUtils.TerrainVectorUnity(positions[i], terrain).y;
        }

        double tUnity = stopwatch.Elapsed.TotalMilliseconds;

        // Bilinear;
        for (int i = 0; i < numberOfPoints; i++)
        {
            yBilinear[i] = TerrainUtils.TerrainVectorBilinear(positions[i], heightmap, -size / 2f, -size / 2f, 0f, size, maxHeight, resolution).y;
        }

        double tBilinear = stopwatch.Elapsed.TotalMilliseconds;

        // Inlined;
        for (int i = 0; i < numberOfPoints; i++)
        {
            yInlined[i] = TerrainUtils.TerrainVectorInlined(positions[i], heightmap, -size / 2f, -size / 2f, 0f, size, maxHeight, resolution).y;
        }

        double tInlined = stopwatch.Elapsed.TotalMilliseconds;

        // Native array;
        for (int i = 0; i < numberOfPoints; i++)
        {
            yNativeArray[i] = TerrainUtils.TerrainVectorNativeArray(positions[i], nativeHeightmap, -size / 2f, -size / 2f, 0f, size, maxHeight, resolution).y;
        }

        double tNativeArray = stopwatch.Elapsed.TotalMilliseconds;

        // Native array;
        for (int i = 0; i < numberOfPoints; i++)
        {
            yBarycentric[i] = TerrainUtils.TerrainVectorBarycentric(positions[i], nativeHeightmap, -size / 2f, -size / 2f, 0f, size, maxHeight, resolution).y;
        }

        double tBarycentric = stopwatch.Elapsed.TotalMilliseconds;

        TerrainVectorBarycentricJob terrainVectorBarycentricJob = new TerrainVectorBarycentricJob
        {
            positions       = nativePositions,
            nativeHeightmap = nativeHeightmap,
            size            = size,
            maxHeight       = maxHeight,
            res             = resolution,
            results         = yBarycentricJob
        };

        terrainVectorBarycentricJob.Schedule(numberOfPoints, System.Environment.ProcessorCount).Complete();
        double tBarycentricJob = stopwatch.Elapsed.TotalMilliseconds;

        // Steepness Unity
        for (int i = 0; i < numberOfPoints; i++)
        {
            steepnessUnity[i] = TerrainUtils.TerrainSteepnessUnity(terrainData, positions[i], terrain.transform.position);
        }

        double tSteepnessUnity = stopwatch.Elapsed.TotalMilliseconds;

        // Steepness manual
        TerrainSteepnessJob terrainSteepnessJob = new TerrainSteepnessJob
        {
            positions       = nativePositions,
            nativeHeightmap = nativeHeightmap,
            size            = size,
            maxHeight       = maxHeight,
            res             = resolution,
            results         = steepnessJob
        };

        terrainSteepnessJob.Schedule(numberOfPoints, System.Environment.ProcessorCount).Complete();
        double tSteepnessJob = stopwatch.Elapsed.TotalMilliseconds;

        float maxDiffBilinear       = 0f;
        float maxDiffInlined        = 0f;
        float maxDiffNativeArray    = 0f;
        float maxDiffBarycentric    = 0f;
        float maxDiffBarycentricJob = 0f;
        float maxDiffSteepnessJob   = 0f;

        float maxDiffBilinearFrac       = 0f;
        float maxDiffInlinedFrac        = 0f;
        float maxDiffNativeArrayFrac    = 0f;
        float maxDiffBarycentricFrac    = 0f;
        float maxDiffBarycentricJobFrac = 0f;
        float maxDiffSteepnessJobFrac   = 0f;

        for (int i = 0; i < numberOfPoints; i++)
        {
            maxDiffBilinear       = math.max(maxDiffBilinear, math.abs(yBilinear[i] - yUnity[i]));
            maxDiffInlined        = math.max(maxDiffInlined, math.abs(yInlined[i] - yUnity[i]));
            maxDiffNativeArray    = math.max(maxDiffNativeArray, math.abs(yNativeArray[i] - yUnity[i]));
            maxDiffBarycentric    = math.max(maxDiffBarycentric, math.abs(yBarycentric[i] - yUnity[i]));
            maxDiffBarycentricJob = math.max(maxDiffBarycentricJob, math.abs(yBarycentricJob[i] - yUnity[i]));
            maxDiffSteepnessJob   = math.max(maxDiffSteepnessJob, math.abs(steepnessJob[i] - steepnessUnity[i]));

            maxDiffBilinearFrac       = math.max(maxDiffBilinearFrac, math.abs(yBilinear[i] - yUnity[i]) / yUnity[i]);
            maxDiffInlinedFrac        = math.max(maxDiffInlinedFrac, math.abs(yInlined[i] - yUnity[i]) / yUnity[i]);
            maxDiffNativeArrayFrac    = math.max(maxDiffNativeArrayFrac, math.abs(yNativeArray[i] - yUnity[i]) / yUnity[i]);
            maxDiffBarycentricFrac    = math.max(maxDiffBarycentricFrac, math.abs(yBarycentric[i] - yUnity[i]) / yUnity[i]);
            maxDiffBarycentricJobFrac = math.max(maxDiffBarycentricJobFrac, math.abs(yBarycentric[i] - yUnity[i]) / yUnity[i]);
            maxDiffSteepnessJobFrac   = math.max(maxDiffSteepnessJobFrac, math.abs(steepnessJob[i] - steepnessUnity[i]) / 90f);
        }

        UnityEngine.Debug.Log($"Setup : resolution={resolution} size={size} maxHeight={maxHeight} numberOfPoints={numberOfPoints} noiseSize={noiseSize}");
        UnityEngine.Debug.Log($"Unity : dt={tUnity}ms");
        UnityEngine.Debug.Log($"Bilinear : diff={maxDiffBilinear} frac={maxDiffBilinearFrac * 100f}% dt={tBilinear - tUnity}ms");
        UnityEngine.Debug.Log($"Inlined : diff={maxDiffInlined} frac={maxDiffInlinedFrac * 100f}% dt={tInlined - tBilinear}ms");
        UnityEngine.Debug.Log($"NativeArray : diff={maxDiffNativeArray} frac={maxDiffNativeArrayFrac * 100f}% dt={tNativeArray - tInlined}ms");
        UnityEngine.Debug.Log($"Barycentric : diff={maxDiffBarycentric} frac={maxDiffBarycentricFrac * 100f}% dt={tBarycentric - tNativeArray}ms");
        UnityEngine.Debug.Log($"Barycentric Job : diff={maxDiffBarycentricJob} frac={maxDiffBarycentricJobFrac * 100f}% dt={tBarycentricJob - tBarycentric}ms");
        UnityEngine.Debug.Log($"Steepness Unity : dt={tSteepnessUnity - tBarycentricJob}ms");
        UnityEngine.Debug.Log($"Steepness Job : diff={maxDiffSteepnessJob} frac={maxDiffSteepnessJobFrac * 100f}% dt={tSteepnessJob - tSteepnessUnity}ms");

        nativeHeightmap.Dispose();
        nativePositions.Dispose();
        yBarycentricJob.Dispose();
        steepnessJob.Dispose();
    }
Beispiel #28
0
 /// <summary>
 /// Shape offset, rotates native height field from z up to y up, flips x and z (?) and
 /// moves to center of the terrain (Unity Terrain has origin "lower corner").
 /// </summary>
 /// <returns>Shape transform to be used between native geometry and shape.</returns>
 public override agx.AffineMatrix4x4 GetNativeGeometryOffset()
 {
     return(TerrainUtils.CalculateNativeOffset(transform, TerrainData));
 }
Beispiel #29
0
        /**
         * Create trees on the terrain
         */
        public void GenerateTrees(LatLngObject middleMapPoint, List <TreeObject> trees)
        {
            Vector3 middleMapXyz;

            ConiferousTree = Resources.Load("3DObjects/Trees/Prefabs/Fir_Tree", typeof(GameObject)) as GameObject;
            LeafyTree      = Resources.Load("3DObjects/Trees/Prefabs/Poplar_Tree", typeof(GameObject)) as GameObject;
            //default position, if map does not contain any building or road
            if (middleMapPoint.Equals(new LatLngObject()))
            {
                middleMapXyz = Vector3.zero;
            }
            else
            {
                middleMapXyz = Converter.ConvertLatLngToXyz(middleMapPoint);
            }

            var         treeCount = Main.Settings.NumberOfTrees;
            const float treeScale = 0.06f;
            var         terrain   = TerrainRender.Get().Terrain;
            var         random    = new Random();

            //GENERATE RANDOM TREE POSITIONS
            if (trees.Count == 0)
            {
                for (var i = 0; i < treeCount; i++)
                {
                    var       decimalRandomPartX = random.NextDouble();
                    var       decimalRandomPartZ = random.NextDouble();
                    const int limitX             = (TerrainUtils.MapWidth / 2) - 2;
                    const int limitZ             = (TerrainUtils.MapHeight / 2) - 2;
                    var       randomX            = random.Next((int)(middleMapXyz.x - limitX), (int)(middleMapXyz.x + limitX));
                    // + 2 a + 1 kvuli korekcim umisteni na hranice terenu
                    var randomZ    = random.Next((int)(middleMapXyz.z - limitZ + 2), (int)(middleMapXyz.z + limitZ + 1));
                    var randomDecX = (float)(randomX + decimalRandomPartX);
                    var randomDecZ = (float)(randomZ + decimalRandomPartZ);
                    var randomPos  = new Vector3(randomDecX, 0, randomDecZ);
                    var terrainY   = terrain.SampleHeight(randomPos);
                    randomPos.y = terrainY;

                    var randNumberTree = random.Next(0, 2);
                    if (!IsPointInCollision(randomPos))
                    {
                        GameObject tree;
                        switch (randNumberTree)
                        {
                        case 0:
                            tree = Instantiate(LeafyTree);
                            break;

                        default:
                            tree = Instantiate(ConiferousTree);
                            break;
                        }

                        var treeTransform = tree.transform;
                        treeTransform.position   = randomPos;
                        treeTransform.localScale = new Vector3(treeScale, treeScale, treeScale);
                    }
                    else
                    {
                        --i;
                    }
                }
            }
            //CUSTOM TREE POSITIONS
            else
            {
                foreach (var currentTree in trees)
                {
                    var treePos = Converter.ConvertLatLngToXyz(currentTree.LatLngCoordinate);
                    //if tree is outside the map
                    if (TerrainUtils.IsObjectOutsideMap(treePos, middleMapXyz))
                    {
                        continue;
                    }

                    //set y position from terrain
                    var terrainY = terrain.SampleHeight(treePos);
                    treePos.y = terrainY;

                    var        randNumberTree = random.Next(0, 2);
                    GameObject tree;
                    switch (randNumberTree)
                    {
                    case 0:
                        tree = Instantiate(LeafyTree);
                        break;

                    default:
                        tree = Instantiate(ConiferousTree);
                        break;
                    }

                    var treeTransform = tree.transform;
                    treeTransform.position   = treePos;
                    treeTransform.localScale = new Vector3(treeScale, treeScale, treeScale);
                }
            }
        }
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        TerrainUtils utils = (TerrainUtils)target;

        // Set the trees only
        if (GUILayout.Button("Set Tree Prototypes Only"))
        {
            utils.CopyTerrainTreePrototypes();
        }

        if (GUILayout.Button("Set Heightmap Only"))
        {
            utils.CopyTerrainHeightmap();
        }

        if (GUILayout.Button("Copy Trees"))
        {
            utils.CopyTerrainTrees();
        }

        if (GUILayout.Button("Copy Details"))
        {
            utils.CopyTerrainDetailPrototypes();
        }

        if (GUILayout.Button("Copy Textures"))
        {
            utils.CopyTerrainTextures();
        }

        if (GUILayout.Button("Delete Main Terrain Trees"))
        {
            utils.ClearMainTerrainTrees();
        }

        if (GUILayout.Button("Delete Terrain Trees"))
        {
            utils.ClearTrees();
        }

        if (GUILayout.Button("Count Trees"))
        {
            Debug.Log("Tree count: " + utils.m_MainTerrain.terrainData.treeInstanceCount);
        }

        if (GUILayout.Button("Cell Info"))
        {
            utils.CellInfo();
        }

        if (GUILayout.Button("Full Copy"))
        {
            utils.FullCopy();
        }

        if (GUILayout.Button("Convert Main Terrain Splatmap"))
        {
            utils.ConvertTerrainResolution();
        }

        if (GUILayout.Button("Add Trees From Main And Delete"))
        {
            utils.AddFromMainAndDelete();
        }
    }
        public void Execute(int i)
        {
            float3 pos = positions[i];

            results[i] = TerrainUtils.GetTerrainSteepnessTriangle(nativeHeightmap, -size / 2f, -size / 2f, size, pos.x, pos.z, maxHeight, res);
        }