예제 #1
0
        public void Mold(IUndoManager undo)
        {
            MeshCollider mc = GetComponent <MeshCollider>();

            if (mc != null && mc.sharedMesh != null)
            {
                Terrain t = TerrainManager.GetTerrain(transform.position);
                if (t != null)
                {
                    if (EnableUndo)
                    {
                        undo.RecordObject(t.terrainData, "Molded " + t.terrainData.name);
                    }
                    Debug.Log(TerrainMeshMold.MoldToMesh(t, mc, Additive, SaftyMargin, OffsetY, StrengthFromColor, DoNotAddHeight, InvertStrength));
                }
                else
                {
                    Debug.Log("Couldn't find terrain");
                }
            }
            else
            {
                Debug.LogError("Needs meshcollider");
            }
        }
예제 #2
0
        public static void GenerateHeightMap(TerrainExtension ter, string path)
        {
            Texture2D heightMap = ter.GetHeightMap();

            if (heightMap.format != TextureFormat.RGBA32)
            {
                Debug.LogError("Format must be RGBA32 it is now " + heightMap.format);
                return;
            }
            Terrain t            = ter.GetComponent <Terrain>();
            float   pixelWidthT  = 1 / (float)heightMap.width;
            float   pixelWidthT2 = pixelWidthT * 0.5f;

            int splatMapWidth = t.terrainData.alphamapWidth;

            float[,,] splatmapData = t.terrainData.GetAlphamaps(0, 0, splatMapWidth, splatMapWidth);

            float sh = TerrainManager.FindInstance().SnowHeight;

            for (int j = 0; j < heightMap.height; j++)
            {
                for (int i = 0; i < heightMap.width; i++)
                {
                    float tu = i / ((float)heightMap.width) + pixelWidthT2;
                    float tv = j / ((float)heightMap.height) + pixelWidthT2;

                    int   sxi       = Mathf.Clamp(Mathf.RoundToInt((float)splatMapWidth * tv), 0, splatMapWidth - 1);
                    int   syi       = Mathf.Clamp(Mathf.RoundToInt((float)splatMapWidth * tu), 0, splatMapWidth - 1);
                    float snowDepth = sh * (splatmapData[sxi, syi, 0] + splatmapData[sxi, syi, 2]);

                    Vector3 normal = t.terrainData.GetInterpolatedNormal(tu, tv);
                    normal = ter.transform.InverseTransformDirection(normal);

                    Vector3 pos = t.GetPosition();
                    pos.x += tu * t.terrainData.size.x; //+pixelWidth*0.5f;
                    pos.z += tv * t.terrainData.size.z; //+pixelWidth*0.5f;

                    float intHeight = t.terrainData.GetInterpolatedHeight(tu, tv) + snowDepth;
                    //pos.y += intHeight;
                    //pos.y += snowDepth;

                    float   h    = Mathf.Clamp01((intHeight) / t.terrainData.size.y);
                    float[] encs = EncodeFloatRGBA(h);
                    Color   c    = new Color(encs[0], encs[1], encs[2], encs[3]);
                    heightMap.SetPixel(i, j, c);
                }
            }
            heightMap.Apply();

            byte[] bytes = heightMap.EncodeToPNG();

            //string path = AssetDatabase.GetAssetOrScenePath(heightMap);
            Debug.Log("Writing to path" + path);
            if (!string.IsNullOrEmpty(path))
            {
                File.WriteAllBytes(path, bytes);
            }
        }
예제 #3
0
        public static void SetGroundOffset(Transform t)
        {
            Vector3?pos = TerrainManager.GetGroundPoint(t.position);

            if (pos.HasValue)
            {
                t.position = pos.Value;
            }
        }
예제 #4
0
        public static void AlignToGroundNormal(GroundAlign ga, IUndoManager undo = null)
        {
            if (undo != null)
            {
                undo.RecordTransform("Align", ga.transform);
            }

            bool resetLayer = false;

            if (LayerMask.LayerToName(ga.gameObject.layer) == "Environment")
            {
                ga.gameObject.layer = LayerMask.NameToLayer("Default");
                resetLayer          = true;
            }

            RaycastHit?hit;

            if (ga.OnlyAlignToTerrain)
            {
                hit = TerrainManager.GetTerrainHitOnly(ga.transform.position + Vector3.up * 100, Vector3.down);
            }
            else
            {
                hit = TerrainManager.GetGroundHit(ga.transform.position);
            }


            if (hit.HasValue)
            {
                Vector3 fromv = GetTransfomAxis(ga.transform, ga.FromAxis, ga.InvertAxis);

                ga.transform.rotation = Quaternion.FromToRotation(fromv, hit.Value.normal) * ga.transform.rotation;
            }
            else
            {
            }

            if (resetLayer)
            {
                ga.gameObject.layer = LayerMask.NameToLayer("Environment");
            }
        }
예제 #5
0
        public static void AlignToGround(GroundAlign ga, IUndoManager undo = null)
        {
            if (undo != null)
            {
                undo.RecordTransform("Align", ga.transform);
            }

            bool resetLayer = false;

            if (LayerMask.LayerToName(ga.gameObject.layer) == "Environment")
            {
                ga.gameObject.layer = LayerMask.NameToLayer("Default");
                resetLayer          = true;
            }

            RaycastHit?hit;

            if (ga.OnlyAlignToTerrain)
            {
                hit = TerrainManager.GetTerrainHitOnly(ga.transform.position + Vector3.up * 100, Vector3.down);
            }
            else
            {
                hit = TerrainManager.GetGroundHit(ga.transform.position);
            }

            if (hit != null)
            {
                ga.transform.position = hit.Value.point + ga.Offset;
            }

            if (resetLayer)
            {
                ga.gameObject.layer = LayerMask.NameToLayer("Environment");
            }
        }
예제 #6
0
        public static string _MoldToMeshByTerrainPolygon(Terrain terrain, MeshCollider collider, bool MoldAdditive, float saftyMargin, float offset, bool doNotAddHeight = false)
        {
            if (collider == null)
            {
                return("error no collider");
            }

            Transform parent = collider.transform.parent;

            if (parent != null)
            {
                collider.transform.parent = null;
            }

            if (!terrain.GetComponent <Collider>().bounds.Intersects(collider.bounds))
            {
                return(".");
            }


            Vector3 terrainPos  = terrain.transform.position;
            Vector3 terrainSize = terrain.terrainData.size;
            Vector2 tmin        = Vector2.zero;
            Vector2 tmax        = Vector2.zero;

            tmin.x = (collider.bounds.min.x - terrainPos.x) / terrainSize.x;
            tmin.y = (collider.bounds.min.z - terrainPos.z) / terrainSize.z;
            tmax.x = (collider.bounds.max.x - terrainPos.x) / terrainSize.x;
            tmax.y = (collider.bounds.max.z - terrainPos.z) / terrainSize.z;

            int minIndexX = Mathf.FloorToInt(tmin.x * terrain.terrainData.heightmapWidth - saftyMargin);
            int minIndexY = Mathf.FloorToInt(tmin.y * terrain.terrainData.heightmapHeight - saftyMargin);
            int maxIndexX = Mathf.CeilToInt(tmax.x * terrain.terrainData.heightmapWidth + saftyMargin);
            int maxIndexY = Mathf.CeilToInt(tmax.y * terrain.terrainData.heightmapHeight + saftyMargin);

            //Make sure rectangle is inside terrain
            minIndexX = Mathf.Clamp(minIndexX, 0, terrain.terrainData.heightmapWidth - 1);
            minIndexY = Mathf.Clamp(minIndexY, 0, terrain.terrainData.heightmapHeight - 1);
            maxIndexX = Mathf.Clamp(maxIndexX, 0, terrain.terrainData.heightmapWidth - 1);
            maxIndexY = Mathf.Clamp(maxIndexY, 0, terrain.terrainData.heightmapHeight - 1);

            int mapWidth  = maxIndexX - minIndexX;
            int mapHeight = maxIndexY - minIndexY;

            float[,] heights = terrain.terrainData.GetHeights(minIndexX, minIndexY, mapWidth, mapHeight);

            for (int iz = 0; iz < mapHeight - 1; iz++)
            {
                for (int ix = 0; ix < mapWidth - 1; ix++)
                {
                    float[]   originalHeight   = new float[4];
                    float[]   targetHeight     = new float[4];
                    float     strength         = 1;
                    float[]   newHeight        = new float[4];
                    Vector3[] terrainPositions = new Vector3[4];

                    originalHeight[0] = heights[iz, ix];
                    originalHeight[1] = heights[iz, ix + 1];
                    originalHeight[2] = heights[iz + 1, ix + 1];
                    originalHeight[3] = heights[iz + 1, ix];

                    terrainPositions[0] = GetTerrainPos(terrain, minIndexX + ix, minIndexY + iz, originalHeight[0]);
                    terrainPositions[1] = GetTerrainPos(terrain, minIndexX + ix + 1, minIndexY + iz, originalHeight[1]);
                    terrainPositions[2] = GetTerrainPos(terrain, minIndexX + ix + 1, minIndexY + iz + 1, originalHeight[2]);
                    terrainPositions[3] = GetTerrainPos(terrain, minIndexX + ix, minIndexY + iz + 1, originalHeight[3]);

                    Vector3 rayOrigin = terrainPositions[0];
                    rayOrigin.y = terrain.transform.position.y + terrain.terrainData.size.y;
                    Ray        ray = new Ray(rayOrigin, Vector3.down);
                    RaycastHit hit;

                    for (int i = 0; i < 4; i++)
                    {
                        if (collider.Raycast(ray, out hit, terrain.terrainData.size.y * 10))
                        {
                            int[]   triangles = collider.sharedMesh.triangles;
                            float[] barys     = new float[3];
                            barys[0] = hit.barycentricCoordinate.x;
                            barys[1] = hit.barycentricCoordinate.y;
                            barys[2] = hit.barycentricCoordinate.z;

                            if (collider.sharedMesh.colors != null)
                            {
                                float tsmooth = 0;
                                for (int j = 0; j < 3; j++)
                                {
                                    tsmooth += collider.sharedMesh.colors[triangles[hit.triangleIndex * 3 + j]].a * barys[j];
                                }

                                strength = tsmooth;
                            }

                            newHeight[i] = hit.point.y - offset;
                        }
                        else
                        {
                            //newHeight = 1;
                        }
                    }

                    if (MoldAdditive)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            newHeight[i] = Mathf.Max(terrainPositions[i].y, newHeight[i]);
                        }
                    }

                    for (int i = 0; i < 4; i++)
                    {
                        targetHeight[i] = TerrainManager.GetHeightInTerrainSpace(newHeight[0], terrain);
                    }

                    if (doNotAddHeight)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            targetHeight[i] = Mathf.Min(originalHeight[i], targetHeight[i]);
                        }
                    }

                    heights[iz, ix]         = Mathf.Lerp(originalHeight[0], targetHeight[0], strength);
                    heights[iz, ix + 1]     = Mathf.Lerp(originalHeight[1], targetHeight[1], strength);
                    heights[iz + 1, ix + 1] = Mathf.Lerp(originalHeight[2], targetHeight[2], strength);
                    heights[iz + 1, ix]     = Mathf.Lerp(originalHeight[3], targetHeight[3], strength);
                }
            }

            terrain.terrainData.SetHeights(minIndexX, minIndexY, heights);
            collider.transform.parent = parent;
            return("ok");
        }
예제 #7
0
        public static string MoldToMesh(Terrain terrain, MeshCollider collider, bool MoldAdditive, float saftyMargin, float offset, bool strengthFromColor, bool doNotAddHeight = false, bool invertStrength = false)
        {
            if (collider == null)
            {
                return("error no collider");
            }

            Transform parent = collider.transform.parent;

            if (parent != null)
            {
                collider.transform.parent = null;
            }

            if (!terrain.GetComponent <Collider>().bounds.Intersects(collider.bounds))
            {
                return(".");
            }


            Vector3 terrainPos  = terrain.transform.position;
            Vector3 terrainSize = terrain.terrainData.size;
            Vector2 tmin        = Vector2.zero;
            Vector2 tmax        = Vector2.zero;

            tmin.x = (collider.bounds.min.x - terrainPos.x) / terrainSize.x;
            tmin.y = (collider.bounds.min.z - terrainPos.z) / terrainSize.z;
            tmax.x = (collider.bounds.max.x - terrainPos.x) / terrainSize.x;
            tmax.y = (collider.bounds.max.z - terrainPos.z) / terrainSize.z;

            int minIndexX = Mathf.FloorToInt(tmin.x * terrain.terrainData.heightmapWidth - saftyMargin);
            int minIndexY = Mathf.FloorToInt(tmin.y * terrain.terrainData.heightmapHeight - saftyMargin);
            int maxIndexX = Mathf.CeilToInt(tmax.x * terrain.terrainData.heightmapWidth + saftyMargin);
            int maxIndexY = Mathf.CeilToInt(tmax.y * terrain.terrainData.heightmapHeight + saftyMargin);

            //Make sure rectangle is inside terrain
            minIndexX = Mathf.Clamp(minIndexX, 0, terrain.terrainData.heightmapWidth - 1);
            minIndexY = Mathf.Clamp(minIndexY, 0, terrain.terrainData.heightmapHeight - 1);
            maxIndexX = Mathf.Clamp(maxIndexX, 0, terrain.terrainData.heightmapWidth - 1);
            maxIndexY = Mathf.Clamp(maxIndexY, 0, terrain.terrainData.heightmapHeight - 1);

            int mapWidth  = maxIndexX - minIndexX;
            int mapHeight = maxIndexY - minIndexY;

            float[,] heights = terrain.terrainData.GetHeights(minIndexX, minIndexY, mapWidth, mapHeight);
            Vector3 worldPos;

            for (int iz = 0; iz < mapHeight; iz++)
            {
                for (int ix = 0; ix < mapWidth; ix++)
                {
                    float originalHeight = heights[iz, ix];
                    float height         = terrainPos.y + originalHeight * terrain.terrainData.size.y;
                    worldPos = terrainPos;

                    worldPos.x += terrain.terrainData.size.x * ((float)(minIndexX + ix)) / ((float)(terrain.terrainData.heightmapWidth - 1));
                    worldPos.y += height;
                    worldPos.z += terrain.terrainData.size.z * ((float)(minIndexY + iz)) / ((float)(terrain.terrainData.heightmapHeight - 1));


                    float strength  = 1;
                    float newHeight = height;

                    Vector3 rayOrigin = worldPos;
                    rayOrigin.y = terrain.transform.position.y + terrain.terrainData.size.y;
                    Ray        ray = new Ray(rayOrigin, Vector3.down);
                    RaycastHit hit;

                    if (collider.Raycast(ray, out hit, terrain.terrainData.size.y * 10))
                    {
                        bool hasError = false;
                        try
                        {
                            if (strengthFromColor && collider.sharedMesh.colors != null && collider.sharedMesh.triangles.Length > hit.triangleIndex * 3 + 3)
                            {
                                int[]   triangles = collider.sharedMesh.triangles;
                                float[] barys     = new float[3];
                                barys[0] = hit.barycentricCoordinate.x;
                                barys[1] = hit.barycentricCoordinate.y;
                                barys[2] = hit.barycentricCoordinate.z;

                                float tsmooth = 0;
                                for (int i = 0; i < 3; i++)
                                {
                                    tsmooth += collider.sharedMesh.colors[triangles[hit.triangleIndex * 3 + i]].a * barys[i];
                                }

                                strength = tsmooth;
                            }
                            else
                            {
                                strength = 1;
                            }
                        }
                        catch
                        {
                            hasError = true;
                        }

                        if (hasError)
                        {
                            strength = 1;
                        }

                        if (invertStrength)
                        {
                            strength = 1 - strength;
                        }
                        newHeight = hit.point.y - offset * strength;
                    }
                    else
                    {
                        //newHeight = 1;
                    }

                    if (MoldAdditive)
                    {
                        newHeight = Mathf.Max(height, newHeight);
                    }
                    float targetHeight = TerrainManager.GetHeightInTerrainSpace(newHeight, terrain);

                    if (doNotAddHeight)
                    {
                        targetHeight = Mathf.Min(originalHeight, targetHeight);
                    }
                    heights[iz, ix] = Mathf.Lerp(originalHeight, targetHeight, strength);
                }
            }

            terrain.terrainData.SetHeights(minIndexX, minIndexY, heights);
            collider.transform.parent = parent;
            return("ok");
        }