예제 #1
0
        private void UpdateMesh(Mesh m, GSubDivisionTree tree)
        {
            CreatePolygons(tree);
            m.Clear();
            m.SetVertices(GeneratedVertices);
            m.SetTriangles(GeneratedTriangles, 0);
            m.SetUVs(0, GeneratedUv);
            m.SetColors(GeneratedVertexColors);
            m.RecalculateBounds();
            m.RecalculateNormals();
            RecalculateTangentIfNeeded(m);

            GeneratedVertices.Clear();
            GeneratedTriangles.Clear();
            GeneratedVertexColors.Clear();
            GeneratedUv.Clear();

            SetLastUpdatedTimeNow();
        }
예제 #2
0
        private void CreatePolygons(GSubDivisionTree tree)
        {
            int       dispSeed = Terrain.TerrainData.Geometry.DisplacementSeed;
            float     dispStrength = Terrain.TerrainData.Geometry.DisplacementStrength;
            Texture2D subdivMap = Terrain.TerrainData.Geometry.Internal_SubDivisionMap;
            Vector2   uv0, uv1, uv2;
            Vector3   v0, v1, v2;
            float     r;
            Rand      rand;
            double    radius;

            int    baseResolution = Terrain.TerrainData.Geometry.MeshBaseResolution;
            int    resolution     = Terrain.TerrainData.Geometry.MeshResolution;
            int    level;
            double triangleBaseLength = 1f / Terrain.TerrainData.Geometry.ChunkGridSize;

            IGPolygonProcessor pp      = Terrain.TerrainData.Geometry.PolygonProcessor;
            GPolygon           polygon = new GPolygon();

            GeneratedUv.Clear();
            GeneratedVertices.Clear();
            GeneratedVertexColors.Clear();
            GeneratedTriangles.Clear();

            Vector3 terrainSize = new Vector3(
                Terrain.TerrainData.Geometry.Width,
                Terrain.TerrainData.Geometry.Height,
                Terrain.TerrainData.Geometry.Length);

            v0 = Vector3.zero;
            v1 = Vector3.zero;
            v2 = Vector3.zero;

            tree.ForEachLeaf((n) =>
            {
                uv0 = n.V0;
                uv1 = n.V1;
                uv2 = n.V2;
                if (dispStrength > 0)
                {
                    if (uv0.x != 0 && uv0.x != 1 && uv0.y != 0 && uv0.y != 1)
                    {
                        r      = subdivMap.GetPixelBilinear(uv0.x, uv0.y).r;
                        level  = baseResolution + Mathf.Min(Mathf.FloorToInt(r / GCommon.SUB_DIV_STEP), resolution - baseResolution);
                        rand   = new Rand(dispSeed + (int)(uv0.x * 1000 + uv0.y * 1000));
                        radius = 0.35 * dispStrength * triangleBaseLength * TriangleEdgeLength[level];
                        uv0.x  = Mathf.Clamp01(uv0.x + (float)((rand.NextDouble() - 0.5) * radius));
                        uv0.y  = Mathf.Clamp01(uv0.y + (float)((rand.NextDouble() - 0.5) * radius));
                    }

                    if (uv1.x != 0 && uv1.x != 1 && uv1.y != 0 && uv1.y != 1)
                    {
                        r      = subdivMap.GetPixelBilinear(uv1.x, uv1.y).r;
                        level  = baseResolution + Mathf.Min(Mathf.FloorToInt(r / GCommon.SUB_DIV_STEP), resolution - baseResolution);
                        rand   = new Rand(dispSeed + (int)(uv1.x * 1000 + uv1.y * 1000));
                        radius = 0.35 * dispStrength * triangleBaseLength * TriangleEdgeLength[level];
                        uv1.x  = Mathf.Clamp01(uv1.x + (float)((rand.NextDouble() - 0.5) * radius));
                        uv1.y  = Mathf.Clamp01(uv1.y + (float)((rand.NextDouble() - 0.5) * radius));
                    }

                    if (uv2.x != 0 && uv2.x != 1 && uv2.y != 0 && uv2.y != 1)
                    {
                        r      = subdivMap.GetPixelBilinear(uv2.x, uv2.y).r;
                        level  = baseResolution + Mathf.Min(Mathf.FloorToInt(r / GCommon.SUB_DIV_STEP), resolution - baseResolution);
                        rand   = new Rand(dispSeed + (int)(uv2.x * 1000 + uv2.y * 1000));
                        radius = 0.35 * dispStrength * triangleBaseLength * TriangleEdgeLength[level];
                        uv2.x  = Mathf.Clamp01(uv2.x + (float)((rand.NextDouble() - 0.5) * radius));
                        uv2.y  = Mathf.Clamp01(uv2.y + (float)((rand.NextDouble() - 0.5) * radius));
                    }
                }

                Vector4 h0 = Terrain.GetInterpolatedHeightMapSample(uv0);
                Vector4 h1 = Terrain.GetInterpolatedHeightMapSample(uv1);
                Vector4 h2 = Terrain.GetInterpolatedHeightMapSample(uv2);
                if (h0.w >= 0.5f || h1.w >= 0.5f || h2.w >= 0.5f) //alpha channel for visibility
                {
                    return;
                }

                if (pp != null)
                {
                    polygon.Clear();
                    v0.Set(uv0.x * terrainSize.x, h0.x * terrainSize.y, uv0.y * terrainSize.z);
                    v1.Set(uv1.x * terrainSize.x, h1.x * terrainSize.y, uv1.y * terrainSize.z);
                    v2.Set(uv2.x * terrainSize.x, h2.x * terrainSize.y, uv2.y * terrainSize.z);
                    polygon.Vertices.Add(v0);
                    polygon.Vertices.Add(v1);
                    polygon.Vertices.Add(v2);
                    polygon.Uvs.Add(uv0);
                    polygon.Uvs.Add(uv1);
                    polygon.Uvs.Add(uv2);
                    polygon.Triangles.Add(0);
                    polygon.Triangles.Add(1);
                    polygon.Triangles.Add(2);
                    pp.Process(this, ref polygon);

                    int currentTrisIndex = GeneratedVertices.Count;
                    for (int i = 0; i < polygon.Triangles.Count; ++i)
                    {
                        GeneratedTriangles.Add(currentTrisIndex + polygon.Triangles[i]);
                    }

                    for (int i = 0; i < polygon.Vertices.Count; ++i)
                    {
                        GeneratedVertices.Add(polygon.Vertices[i]);
                    }

                    for (int i = 0; i < polygon.Uvs.Count; ++i)
                    {
                        GeneratedUv.Add(polygon.Uvs[i]);
                    }

                    if (polygon.VertexColors != null && polygon.VertexColors.Count > 0)
                    {
                        for (int i = 0; i < polygon.VertexColors.Count; ++i)
                        {
                            GeneratedVertexColors.Add(polygon.VertexColors[i]);
                        }
                    }
                }
                else
                {
                    int currentTrisIndex = GeneratedVertices.Count;
                    GeneratedTriangles.Add(currentTrisIndex + 0);
                    GeneratedTriangles.Add(currentTrisIndex + 1);
                    GeneratedTriangles.Add(currentTrisIndex + 2);
                    v0.Set(uv0.x * terrainSize.x, h0.x * terrainSize.y, uv0.y * terrainSize.z);
                    v1.Set(uv1.x * terrainSize.x, h1.x * terrainSize.y, uv1.y * terrainSize.z);
                    v2.Set(uv2.x * terrainSize.x, h2.x * terrainSize.y, uv2.y * terrainSize.z);
                    GeneratedVertices.Add(v0);
                    GeneratedVertices.Add(v1);
                    GeneratedVertices.Add(v2);
                    GeneratedUv.Add(uv0);
                    GeneratedUv.Add(uv1);
                    GeneratedUv.Add(uv2);
                }
            });

            //Convert vertices terrain local space to chunk local space.
            //This way we can place the chunk pivot/origin point at the center of its region instead of the terrain pivot.
            //Chunk position is set by the terrain component.
            //This step is very important for other task such as level streaming and occlusion culling, etc.
            //Special thank to Aleš Stupka for the contribution.
            Matrix4x4 vertexTransformMatrix = Terrain.transform.localToWorldMatrix * transform.worldToLocalMatrix;

            for (int i = 0; i < GeneratedVertices.Count; ++i)
            {
                GeneratedVertices[i] = vertexTransformMatrix.MultiplyPoint(GeneratedVertices[i]);
            }
        }