public void RemoveAlreadyDealtWithCornerCellMergePairsFrom <T>(CellPairCollection <T> .EdgeCombo edge) { if (edge.Outer.Count > 0) { MeshCell <T> firstCandidate = edge.Outer[0].cell; if (edge.Inner.Count > 1) { MeshCell <T> secondCandidate = edge.Outer[edge.Outer.Count - 1].cell; if (cornerCandidates.Contains(secondCandidate.ID)) { edge.Inner.RemoveAt(edge.Outer.Count - 1); edge.Outer.RemoveAt(edge.Outer.Count - 1); } else { cornerCandidates.Add(secondCandidate.ID); } } if (cornerCandidates.Contains(firstCandidate.ID)) { edge.Inner.RemoveAt(0); edge.Outer.RemoveAt(0); } else { cornerCandidates.Add(firstCandidate.ID); } } }
public IEnumerator <Edge <T> > GetFirstEnumerator(MeshCell <T> first) { AfterCutEdgeEnumerator enumerator = new AfterCutEdgeEnumerator(first.Edges, first.Edges[1]); enumerator.Reset(); return(enumerator); }
public IEnumerator <Edge <T> > GetNeighborFromEdgeNeighbor(Edge <T> edge) { MeshCell <T> newCell = MeshMethods.GetNeighbour(edge); AfterCutEdgeEnumerator ridgeEnum = new AfterCutEdgeEnumerator(newCell.Edges, edge); return(ridgeEnum); }
public void CloseMesh(List <BoundaryLine> lines, Edge <T> firstCutEdge, CyclicInterval boundaryCount) { MeshCell <T> cell = firstCutEdge.Cell; //Divide this cell //================================================================ //NewVertices Vertex[] verticesOfNewRidgeBoundary = new Vertex[lines.Count + 2]; verticesOfNewRidgeBoundary[0] = firstCutEdge.End; verticesOfNewRidgeBoundary[verticesOfNewRidgeBoundary.Length - 1] = mesh.Vertices[cell.IntersectionVertex]; //Add Vertices of lines for (int i = 1; i < verticesOfNewRidgeBoundary.Length - 1; ++i) { verticesOfNewRidgeBoundary[i] = lines[lines.Count - i].End; int ID = mesh.AddVertex(verticesOfNewRidgeBoundary[i]); } //New Edges MeshCell <T> newCell = new MeshCell <T>(); mesh.AddCell(newCell); MeshMethods.CreateBoundaryEdge( verticesOfNewRidgeBoundary, cell, newCell, out Edge <T>[] newEdges, out Edge <T>[] newNeighborEdges,
private void BuildCell(Canvas canvas, Rule rule, IGameObject terrainObject, MeshCell cell, RenderMode renderMode, string name) { var cellGameObject = _gameObjectFactory.CreateNew(name, terrainObject); var meshData = new TerrainMeshData(_objectPool); meshData.GameObject = cellGameObject; meshData.Index = renderMode == RenderMode.Scene ? new TerrainMeshIndex(16, 16, cell.Rectangle, meshData.Triangles) : (IMeshIndex)DummyMeshIndex.Default; // build canvas and extra layers BuildBackground(rule, meshData, cell.Background, renderMode); BuildWater(rule, meshData, cell, renderMode); BuildCarRoads(rule, meshData, cell, renderMode); BuildPedestrianLayers(rule, meshData, cell, renderMode); foreach (var surfaceRegion in cell.Surfaces) { BuildSurface(rule, meshData, surfaceRegion, renderMode); } Trace.Debug(LogTag, "Total triangles: {0}", meshData.Triangles.Count.ToString()); meshData.Index.Build(); BuildObject(cellGameObject, canvas, rule, meshData); }
private void BuildCarRoads(Rule rule, TerrainMeshData meshData, MeshCell cell, RenderMode renderMode) { var meshRegion = cell.CarRoads; var isScene = renderMode == RenderMode.Scene; float eleNoiseFreq = rule.GetCarLayerEleNoiseFreq(); float colorNoiseFreq = isScene ? rule.GetCarLayerColorNoiseFreq() : 0; float roadOffset = 0.3f; if (meshRegion.Mesh == null) { return; } var gradient = rule.GetCarLayerGradient(_customizationService); foreach (var triangle in meshRegion.Mesh.Triangles) { AddTriangle(rule, meshData, triangle, gradient, eleNoiseFreq, colorNoiseFreq, -roadOffset); } if (isScene) { BuildOffsetShape(meshData, meshRegion, rule.GetBackgroundLayerGradient(_customizationService), cell.Rectangle, colorNoiseFreq, roadOffset); } meshRegion.Dispose(); }
static CyclicArray <Edge <T> > PositiveEdgeRotationOfCellAfter(Edge <T> first, int offset) { MeshCell <T> cell = first.Cell; int firstEdgeIndice = FindIndiceOfEdgeInItsCell(cell.Edges, first); CyclicArray <Edge <T> > edges = new CyclicArray <Edge <T> >(cell.Edges, firstEdgeIndice + offset); return(edges); }
void TryToCloneAndTransform(MeshCell <T> cell, params Transformation[] trafos) { if (!visited.Contains(cell.ID)) { foreach (Transformation trafo in trafos) { CloneAndTransform(cell.Node, clones, trafo); } visited.Add(cell.ID); } }
IEnumerator <Edge <T> > FirstCellEdgeEnumerator() { IEnumerator <Edge <T> > ridgeEnum; boundaryLines.MoveNext(); MeshCell <T> first = greatDivider.GetFirst(boundaryLines.Current); ridgeEnum = meshIntersecter.GetFirstEnumerator(first); boundaryLines.Reset(); return(ridgeEnum); }
public static Edge <T> GetFirstEdgeOfBoundaryNegative(MeshCell <T> cornerCell) { foreach (var edge in new Convolution <Edge <T> >(cornerCell.Edges)) { if (!edge.Current.IsBoundary && edge.Previous.IsBoundary) { return(edge.Previous); } } throw new Exception("Cell does not have a boundary."); }
static bool IsBoundary(MeshCell <T> cell) { foreach (Edge <T> edge in cell.Edges) { if (edge.IsBoundary) { return(true); } } return(false); }
static Edge <T> FindFirstBoundaryEdge(MeshCell <T> cell) { foreach (Edge <T> edge in cell.Edges) { if (edge.IsBoundary) { return(edge); } } throw new Exception("Cell does not neighbor boundary."); }
public static IEnumerable <Edge <T> > FollowBoundaryEdges(MeshCell <T> cell) { Edge <T> firstEdge = FindFirstBoundaryEdge(cell); yield return(firstEdge); foreach (Edge <T> edge in FollowBoundaryEdges(firstEdge)) { yield return(edge); } }
public static CyclicArray <Edge <T> > PositiveEdgeRotationOfCellAfter(Edge <T> first, int offset) { MeshCell <T> cell = first.Cell; int firstEdgeIndice = FindIndiceOfEdgeInItsCell(cell.Edges, first); if (firstEdgeIndice != -1) { return(new CyclicArray <Edge <T> >(cell.Edges, firstEdgeIndice + offset)); } else { return(null); } }
public (Stack <Edge <T> >, Corner) FindEdges(MeshCell <T> cornerCell) { Edge <T> firstEdge = GetFirstEdgeOfBoundary(cornerCell); Crossing firstCrossing = FindFirstCrossing(firstEdge); Stack <Edge <T> > edges = default(Stack <Edge <T> >); Corner corner = default(Corner); bool stop = false; CrossingFinder first = new CrossingFinder(firstCrossing.First); CrossingFinder second = new CrossingFinder(firstCrossing.Second); CrossingFinder third = new CrossingFinder(firstCrossing.Third); while (!stop) { if (first.MoveForwardAndCheckForCrossing()) { stop = true; edges = first.Visited; corner = new Corner { FirstEdge = firstCrossing.Third.Twin.BoundaryEdgeNumber, SecondEdge = first.Crossing.First.BoundaryEdgeNumber }; } else if (second.MoveForwardAndCheckForCrossing()) { stop = true; edges = second.Visited; corner = new Corner { FirstEdge = firstCrossing.First.Twin.BoundaryEdgeNumber, SecondEdge = second.Crossing.First.BoundaryEdgeNumber }; } else if (third.MoveForwardAndCheckForCrossing()) { stop = true; edges = third.Visited; corner = new Corner { FirstEdge = firstCrossing.Second.Twin.BoundaryEdgeNumber, SecondEdge = third.Crossing.First.BoundaryEdgeNumber }; } } return(edges, corner); }
private void BuildPedestrianLayers(Rule rule, TerrainMeshData meshData, MeshCell cell, RenderMode renderMode) { var meshRegion = cell.WalkRoads; if (meshRegion.Mesh == null) { return; } var gradient = rule.GetPedestrianLayerGradient(_customizationService); float eleNoiseFreq = rule.GetPedestrianLayerEleNoiseFreq(); float colorNoiseFreq = renderMode == RenderMode.Scene ? rule.GetPedestrianLayerColorNoiseFreq() : 0; foreach (var triangle in meshRegion.Mesh.Triangles) { AddTriangle(rule, meshData, triangle, gradient, eleNoiseFreq, colorNoiseFreq); } meshRegion.Dispose(); }
static List <BoundaryFace> GetBoundaryFacesOfNegativeTriangle(MeshCell <T> cell, int iV0, int iV1, int iV2) { //Indices are debug magic. FML List <BoundaryFace> tags = new List <BoundaryFace>(3); int max = cell.Edges.Length; if (iV0 - 1 == iV1 || iV1 - max + 1 == iV0) { IfIsBoundaryAddEdge2Tags(cell.Edges[iV1], 0, tags); } if (iV1 - 1 == iV2 || iV2 - max + 1 == iV1) { IfIsBoundaryAddEdge2Tags(cell.Edges[iV2], 1, tags); } if (iV2 - 1 == iV0 || iV0 - max + 1 == iV2) { IfIsBoundaryAddEdge2Tags(cell.Edges[iV0], 2, tags); } return(tags); }
public Edge <T> Subdivide(Edge <T> edge, List <BoundaryLine> lines, double alpha, CyclicInterval boundaryCount) { MeshCell <T> cell = edge.Cell; //Divide Ridge and update Ridge Arrays //------------------------------------- Vertex newVertex = DivideEdge(edge, alpha, out Edge <T> newRidge); edge.Twin.Cell.IntersectionVertex = newVertex.ID; //cell.IntersectionVertex = newVertex.ID; //Divide this cell //================================================================ //NewVertices Vertex[] verticesOfNewRidgeBoundary = new Vertex[lines.Count + 2]; verticesOfNewRidgeBoundary[0] = newVertex; verticesOfNewRidgeBoundary[verticesOfNewRidgeBoundary.Length - 1] = mesh.Vertices[cell.IntersectionVertex]; //Add Vertices of lines for (int i = 1; i < verticesOfNewRidgeBoundary.Length - 1; ++i) { verticesOfNewRidgeBoundary[verticesOfNewRidgeBoundary.Length - 1 - i] = lines[i - 1].End; int ID = mesh.AddVertex(verticesOfNewRidgeBoundary[verticesOfNewRidgeBoundary.Length - 1 - i]); } //New Ridges Edge <T>[] newEdges; Edge <T>[] newNeighborEdges; MeshCell <T> newCell = new MeshCell <T> { Node = new T() }; newCell.Node.Position = cell.Node.Position; mesh.AddCell(newCell); MeshMethods.CreateBoundaryEdge(verticesOfNewRidgeBoundary, cell, newCell, out newEdges, out newNeighborEdges, boundaryCount); //Link Ridges to old neighbors MeshMethods.InsertEdgesAndVertices(newEdges, newNeighborEdges); //dOnE, DoNe! return(edge); }
public static void InsertEdgesAndVertices <T>(params Edge <T>[] additionalEdges) { MeshCell <T> cell = additionalEdges[0].Cell; int countAdditionalRidges = additionalEdges.Length; Edge <T>[] newRidges = new Edge <T> [cell.Edges.Length + countAdditionalRidges]; bool notInsertedYet = true; for (int i = 0; i < cell.Edges.Length; ++i) { if (notInsertedYet) { newRidges[i] = cell.Edges[i]; } else { newRidges[i + countAdditionalRidges] = cell.Edges[i]; } if (notInsertedYet && (additionalEdges[0].Start.ID == cell.Edges[i].End.ID)) { for (int k = 0; k < countAdditionalRidges; ++k) { newRidges[i + k + 1] = additionalEdges[k]; } notInsertedYet = false; } } cell.Edges = newRidges; Vertex[] newVertices = new Vertex[cell.Vertices.Length + countAdditionalRidges]; for (int i = 0; i < cell.Edges.Length; ++i) { newVertices[i] = newRidges[i].Start; } cell.Vertices = newVertices; }
public static void CreateBoundaryEdge <T>( Vertex[] vertices, MeshCell <T> cell, MeshCell <T> neighborCell, out Edge <T>[] ridges, out Edge <T>[] twinEdges, CyclicInterval boundaryCount) { int count = vertices.Length - 1; ridges = new Edge <T> [count]; twinEdges = new Edge <T> [count]; for (int i = 0; i < count; ++i) { Edge <T> ridge = new Edge <T> { Start = vertices[i], End = vertices[i + 1], Cell = cell, IsBoundary = true, BoundaryEdgeNumber = boundaryCount.Current(), }; Edge <T> twinRidge = new Edge <T> { Start = vertices[i + 1], End = vertices[i], Twin = ridge, Cell = neighborCell, IsBoundary = true, BoundaryEdgeNumber = boundaryCount.Current(), }; ridge.Twin = twinRidge; ridges[i] = ridge; twinEdges[count - 1 - i] = twinRidge; boundaryCount.Previous(); } }
public static void InsertEdgesAndVertices <T>(Edge <T>[] newEdge, Edge <T>[] newNeighborEdges) { MeshCell <T> cell = newEdge[0].Cell; MeshCell <T> emptyNeighCell = newNeighborEdges[0].Cell; Edge <T>[] oldRidges = cell.Edges; List <Edge <T> > cellRidges = null; List <Edge <T> > emptyNeighCellRidges = null; List <Edge <T> > workerA = new List <Edge <T> >(newEdge.Length); List <Edge <T> > workerB = new List <Edge <T> >(newEdge.Length); bool workerAIsActive = true; List <Edge <T> > tmp = workerA; //Add new Ridges for (int i = 0; i < oldRidges.Length; ++i) { Edge <T> activeR = oldRidges[i]; if (activeR.Start.ID == newEdge[0].Start.ID) { cellRidges = tmp; for (int j = 0; j < newEdge.Length; ++j) { cellRidges.Add(newEdge[j]); } tmp = workerAIsActive ? workerB : workerA; workerAIsActive = !workerAIsActive; } if (activeR.Start.ID == newNeighborEdges[0].Start.ID) { emptyNeighCellRidges = tmp; for (int j = 0; j < newNeighborEdges.Length; ++j) { emptyNeighCellRidges.Add(newNeighborEdges[j]); } tmp = workerAIsActive ? workerB : workerA; workerAIsActive = !workerAIsActive; } tmp.Add(activeR); } cell.Edges = cellRidges.ToArray(); emptyNeighCell.Edges = emptyNeighCellRidges.ToArray(); //Update AllRidges for (int i = 0; i < cell.Edges.Length; ++i) { cell.Edges[i].Cell = cell; } for (int i = 0; i < emptyNeighCell.Edges.Length; ++i) { emptyNeighCell.Edges[i].Cell = emptyNeighCell; } //Vertices Vertex[] newVertices = new Vertex[cell.Edges.Length]; for (int i = 0; i < cell.Edges.Length; ++i) { newVertices[i] = cell.Edges[i].Start; } cell.Vertices = newVertices; Vertex[] newNeighVertices = new Vertex[emptyNeighCell.Edges.Length]; for (int i = 0; i < emptyNeighCell.Edges.Length; ++i) { newNeighVertices[i] = emptyNeighCell.Edges[i].Start; } emptyNeighCell.Vertices = newNeighVertices; }
private void BuildWater(Rule rule, TerrainMeshData meshData, MeshCell cell, RenderMode renderMode) { var meshRegion = cell.Water; if (meshRegion.Mesh == null) { return; } float colorNoiseFreq = renderMode == RenderMode.Scene ? rule.GetWaterLayerColorNoiseFreq() : 0; float eleNoiseFreq = rule.GetWaterLayerEleNoiseFreq(); var meshTriangles = meshData.Triangles; var bottomGradient = rule.GetBackgroundLayerGradient(_customizationService); var waterSurfaceGradient = rule.GetWaterLayerGradient(_customizationService); var waterBottomLevelOffset = rule.GetWaterLayerBottomLevel(); var waterSurfaceLevelOffset = rule.GetWaterLayerSurfaceLevel(); var elevationOffset = waterBottomLevelOffset - waterSurfaceLevelOffset; var surfaceOffset = renderMode == RenderMode.Scene ? -waterBottomLevelOffset : 0; // NOTE: substitute gradient in overview mode if (renderMode == RenderMode.Overview) { bottomGradient = waterSurfaceGradient; } int index = 0; var vertexCount = meshRegion.Mesh.Triangles.Count * 3; var waterVertices = new Vector3[vertexCount]; var waterTriangles = new int[vertexCount]; var waterColors = new Color[vertexCount]; foreach (var triangle in meshRegion.Mesh.Triangles) { // bottom surface AddTriangle(rule, meshData, triangle, bottomGradient, eleNoiseFreq, colorNoiseFreq, surfaceOffset); // NOTE: build offset shape only in case of Scene mode if (renderMode == RenderMode.Overview) { continue; } var meshTriangle = meshTriangles[meshTriangles.Count - 1]; var p0 = meshTriangle.Vertex0; var p1 = meshTriangle.Vertex1; var p2 = meshTriangle.Vertex2; // reuse just added vertices waterVertices[index] = new Vector3(p0.x, p0.y + elevationOffset, p0.z); waterVertices[index + 1] = new Vector3(p1.x, p1.y + elevationOffset, p1.z); waterVertices[index + 2] = new Vector3(p2.x, p2.y + elevationOffset, p2.z); var color = GradientUtils.GetColor(waterSurfaceGradient, waterVertices[index], colorNoiseFreq); waterColors[index] = color; waterColors[index + 1] = color; waterColors[index + 2] = color; waterTriangles[index] = index; waterTriangles[index + 1] = index + 2; waterTriangles[index + 2] = index + 1; index += 3; } // finalizing offset shape if (renderMode == RenderMode.Scene) { BuildOffsetShape(meshData, meshRegion, rule.GetBackgroundLayerGradient(_customizationService), cell.Rectangle, colorNoiseFreq, waterBottomLevelOffset); Observable.Start(() => BuildWaterObject(rule, meshData, waterVertices, waterTriangles, waterColors), Scheduler.MainThread); } }
public static void SeveToMeshCell() { Transform[] transforms = Selection.transforms; foreach (Transform transform in transforms) { EditorUtility.DisplayProgressBar("Generate...", "Heightmap", 0f); Terrain terrain = transform.GetComponent <Terrain>(); Vector3 size = terrain.terrainData.size; int w = terrain.terrainData.heightmapWidth; int h = terrain.terrainData.heightmapHeight; int resolution = terrain.terrainData.heightmapResolution; float[,] heightmap = terrain.terrainData.GetHeights(0, 0, w, h); EditorUtility.DisplayProgressBar("Generate...", "Cutting", 0.1f); /* * int meshx = 32; * int meshz = 32; * * Mesh mesh = CodeMesh.GetCellXZRect(meshx, meshz); * CodeMesh.SetHeight(terrain, mesh, meshx, meshz); */ List <MeshCell> list = new List <MeshCell>(); //地图块密度 int cellxNum = 8; int cellzNum = 8; CodeMesh.Cutting(terrain, cellxNum, cellzNum, list); EditorUtility.DisplayProgressBar("Generate...", "TerrainMeshCell", 0.7f); GameObject terrainMeshCellRoot = new GameObject("TerrainMeshCellRoot"); if (terrain.gameObject.transform.parent != null) { terrainMeshCellRoot.transform.parent = terrain.gameObject.transform.parent; } terrainMeshCellRoot.transform.position = terrain.gameObject.transform.position; for (int i = 0; i < list.Count; i++) { MeshCell meshCell = list[i]; Mesh mesh = meshCell.mesh; //修改完高度以后重新运算法线 //mesh.RecalculateNormals(); //修改完高度以后重新运算切线 //mesh.RecalculateTangents(); //修改完高度以后重新运算包围盒子 //mesh.RecalculateBounds(); GameObject terrainMeshCell = new GameObject("TerrainMeshCell_" + mesh.name); terrainMeshCell.transform.parent = terrainMeshCellRoot.transform; terrainMeshCell.transform.localPosition = new Vector3(meshCell.xIndex * size.x / cellxNum, 0, meshCell.zIndex * size.z / cellzNum); MeshFilter meshFilter = terrainMeshCell.AddComponent <MeshFilter>(); meshFilter.sharedMesh = mesh; terrainMeshCell.AddComponent <MeshRenderer>(); terrainMeshCell.AddComponent <MeshCollider>(); //AssetDatabase.CreateAsset(mesh, "Assets/T4MOBJ/" + terrain.name +"_"+ mesh.name + ".asset"); //AssetDatabase.Refresh(); } if (true) { Vector3 terrainSize = terrain.terrainData.size; int meshx = (int)terrainSize.x; int meshz = (int)terrainSize.z; Mesh terrainMesh = CodeMesh.GetCellXZRect(meshx, meshz); CodeMesh.SetHeight(terrain, terrainMesh, meshx, meshz); //修改完高度以后重新运算法线 terrainMesh.RecalculateNormals(); //修改完高度以后重新运算切线 terrainMesh.RecalculateTangents(); //修改完高度以后重新运算包围盒子 terrainMesh.RecalculateBounds(); GameObject terrainMeshCell = new GameObject("TerrainMesh"); terrainMeshCell.transform.parent = terrainMeshCellRoot.transform; terrainMeshCell.transform.localPosition = new Vector3(0, 0, 0); MeshFilter meshFilter = terrainMeshCell.AddComponent <MeshFilter>(); meshFilter.sharedMesh = terrainMesh; MeshRenderer meshRenderer = terrainMeshCell.AddComponent <MeshRenderer>(); } } EditorUtility.ClearProgressBar(); }
static T CloneAndTransFormAssociatedNodeOf(Edge <T> edge, Transformation transformation) { MeshCell <T> cell = edge.Cell; return(CloneAndTransform(cell.Node, transformation)); }
public IEnumerable <Edge <T> > CycleEdges() { MeshCell <T> firstCell = cells.GetFirstCell(); return(FollowBoundaryEdges(firstCell)); }