private void StitchSeamLOD(GSubDivisionTree tree, HashSet <Vector2> seamVertices) { Stack <GSubDivisionTree.Node> dirtyNode = new Stack <GSubDivisionTree.Node>(); tree.ForEachLeaf(n => { dirtyNode.Push(n); }); HashSet <Vector2> newVertices = new HashSet <Vector2>(); while (dirtyNode.Count > 0) { GSubDivisionTree.Node n = dirtyNode.Pop(); if (!seamVertices.Contains(n.V01) && !seamVertices.Contains(n.V12) && !seamVertices.Contains(n.V20)) { continue; } n.Split(); newVertices.Add(n.V12); dirtyNode.Push(n.LeftNode); dirtyNode.Push(n.RightNode); } dirtyNode.Clear(); tree.ForEachLeaf(n => { dirtyNode.Push(n); }); while (dirtyNode.Count > 0) { GSubDivisionTree.Node n = dirtyNode.Pop(); if (!newVertices.Contains(n.V01) && !newVertices.Contains(n.V12) && !newVertices.Contains(n.V20)) { continue; } n.Split(); dirtyNode.Push(n.LeftNode); dirtyNode.Push(n.RightNode); } }
private bool StitchGeometrySeamsOnSubDivTree(HashSet <Vector2> vertexPool, GSubDivisionTree tree) { #if UNITY_EDITOR //canRunStitchSeamInBackground = true; #endif bool isNewVertexCreated = false; Stack <GSubDivisionTree.Node> nodes = new Stack <GSubDivisionTree.Node>(); int baseResolution = Terrain.TerrainData.Geometry.MeshBaseResolution; int resolution = Terrain.TerrainData.Geometry.MeshResolution; int maxLevel = baseResolution + Mathf.Min(Mathf.FloorToInt(1f / GCommon.SUB_DIV_STEP), resolution - baseResolution); //Stitching triangle between tiles tree.ForEachLeaf(n => { if (n.Level >= maxLevel) { return; } nodes.Push(n); }); while (nodes.Count > 0) { GSubDivisionTree.Node n = nodes.Pop(); bool validV01 = vertexPool.Contains(n.V01); // && GUtilities.IsRectContainPointExclusive(uvRange, n.V01); bool validV12 = vertexPool.Contains(n.V12); // && GUtilities.IsRectContainPointExclusive(uvRange, n.V12); bool validV20 = vertexPool.Contains(n.V20); // && GUtilities.IsRectContainPointExclusive(uvRange, n.V20); if (!validV01 && !validV12 && !validV20) { continue; } n.Split(); if (!vertexPool.Contains(n.V12)) { vertexPool.Add(n.V12); isNewVertexCreated = true; } nodes.Push(n.LeftNode); nodes.Push(n.RightNode); } //Sub division for triangle connectivity HashSet <Vector2> verts = new HashSet <Vector2>(); nodes.Clear(); tree.ForEachLeaf(n => { verts.Add(n.V0); verts.Add(n.V1); verts.Add(n.V2); if (n.Level < maxLevel) { nodes.Push(n); } }); while (nodes.Count > 0) { GSubDivisionTree.Node n = nodes.Pop(); if (!verts.Contains(n.V01) && !verts.Contains(n.V12) && !verts.Contains(n.V20)) { continue; } n.Split(); if (!verts.Contains(n.V12)) { verts.Add(n.V12); isNewVertexCreated = true; } nodes.Push(n.LeftNode); nodes.Push(n.RightNode); } return(isNewVertexCreated); }
internal void Internal_CreateSubDivTree() { Rect uvRange = GetUvRange(); subDivTree = GSubDivisionTree.Rect(uvRange); int firstPassResolution = Terrain.TerrainData.Geometry.PolygonDistribution == GPolygonDistributionMode.Dynamic ? Terrain.TerrainData.Geometry.MeshBaseResolution : Terrain.TerrainData.Geometry.MeshResolution; //Subdiv for base resolution for (int i = 0; i < firstPassResolution; ++i) { subDivTree.ForEachLeaf(n => { n.Split(); }); } if (Terrain.TerrainData.Geometry.PolygonDistribution != GPolygonDistributionMode.Dynamic) { return; } Texture2D subdivMap = null; if (GCommon.IsMainThread) { subdivMap = Terrain.TerrainData.Geometry.Internal_SubDivisionMap; } GGeometryGenerationContext context = null; if (!GCommon.IsMainThread) { context = Terrain.GenerationContext; } Stack <GSubDivisionTree.Node> nodes0 = new Stack <GSubDivisionTree.Node>(); Stack <GSubDivisionTree.Node> nodes1; subDivTree.ForEachLeaf(n => { nodes0.Push(n); }); //Additional sub division based on the sub div map int baseResolution = Terrain.TerrainData.Geometry.MeshBaseResolution; int resolution = Terrain.TerrainData.Geometry.MeshResolution; int maxLevel = baseResolution + Mathf.Min(Mathf.FloorToInt(1f / GCommon.SUB_DIV_STEP), resolution - baseResolution); float r0 = 0; float r1 = 0; float r2 = 0; float rc = 0; float rMax = 0; float subDivLevel; for (int i = baseResolution; i <= resolution; ++i) { nodes1 = new Stack <GSubDivisionTree.Node>(); while (nodes0.Count > 0) { GSubDivisionTree.Node n = nodes0.Pop(); if (n.Level >= maxLevel) { continue; } if (GCommon.IsMainThread) { r0 = subdivMap.GetPixelBilinear(n.V0.x, n.V0.y).r; r1 = subdivMap.GetPixelBilinear(n.V1.x, n.V1.y).r; r2 = subdivMap.GetPixelBilinear(n.V2.x, n.V2.y).r; rc = subdivMap.GetPixelBilinear(n.VC.x, n.VC.y).r; } else { r0 = context.GetSubdivData(n.V0).r; r1 = context.GetSubdivData(n.V1).r; r2 = context.GetSubdivData(n.V2).r; rc = context.GetSubdivData(n.VC).r; } rMax = Mathf.Max(r0, r1, r2, rc); subDivLevel = baseResolution + (int)(rMax / GCommon.SUB_DIV_STEP); if (subDivLevel <= n.Level) { continue; } n.Split(); nodes1.Push(n.LeftNode); nodes1.Push(n.RightNode); } nodes0 = nodes1; } }