/// <summary> /// Initializes a new instance of the <see cref="SurfaceGeometry"/> class. /// </summary> /// <param name="graphics">The graphics.</param> /// <param name="patchSegmentCount">The patch segment count.</param> public SurfaceGeometry(GraphicsDevice graphics, int patchSegmentCount, SurfaceTopology topology) { if (graphics == null) { throw new ArgumentNullException("graphics"); } if (patchSegmentCount < 1) { throw new ArgumentOutOfRangeException("Patch segment count must be at least 2."); } if (!IsPowerOfTwo(patchSegmentCount)) { throw new ArgumentOutOfRangeException("Patch segment count must be a power of two."); } this.graphics = graphics; this.topology = topology; this.patchSegmentCount = patchSegmentCount; this.MaxLevelOfDetail = LogBaseTowOf(patchSegmentCount); }
/// <summary> /// Gets a static instance of SurfaceGeometry. /// </summary> public static SurfaceGeometry GetInstance(GraphicsDevice graphics, int patchSegmentCount, SurfaceTopology topology) { SurfaceGeometry result = null; WeakReference <SurfaceGeometry> value; if (resourceDictionary.TryGetValue(new SurfaceGeometryKey(graphics, patchSegmentCount, topology), out value)) { if (value.TryGetTarget(out result)) { return(result); } resourceDictionary.Remove(new SurfaceGeometryKey(graphics, patchSegmentCount, topology)); } result = new SurfaceGeometry(graphics, patchSegmentCount, topology); value = new WeakReference <SurfaceGeometry>(result); resourceDictionary.Add(new SurfaceGeometryKey(graphics, patchSegmentCount, topology), value); return(result); }
public SurfaceGeometryKey(GraphicsDevice graphics, int patchSegmentCount, SurfaceTopology topology) { this.GraphicsDevice = graphics; this.PatchSegmentCount = patchSegmentCount; this.Topology = topology; }
protected override ActionResult PerformActionImplementation() { if (MeshSelection.selectedObjectCount < 1) { return(ActionResult.NoSelection); } UndoUtility.RecordSelection("Fill Hole"); ActionResult res = new ActionResult(ActionResult.Status.NoChange, "No Holes Found"); int filled = 0; bool wholePath = m_SelectEntirePath; foreach (ProBuilderMesh mesh in MeshSelection.topInternal) { bool selectAll = mesh.selectedIndexesInternal == null || mesh.selectedIndexesInternal.Length < 1; IEnumerable <int> indexes = selectAll ? mesh.facesInternal.SelectMany(x => x.indexes) : mesh.selectedIndexesInternal; mesh.ToMesh(); List <WingedEdge> wings = WingedEdge.GetWingedEdges(mesh); HashSet <int> common = mesh.GetSharedVertexHandles(indexes); List <List <WingedEdge> > holes = ElementSelection.FindHoles(wings, common); HashSet <Face> appendedFaces = new HashSet <Face>(); foreach (List <WingedEdge> hole in holes) { List <int> holeIndexes; Face face; if (wholePath) { // if selecting whole path and in edge mode, make sure the path contains // at least one complete edge from the selection. if (ProBuilderEditor.selectMode == SelectMode.Edge && !hole.Any(x => common.Contains(x.edge.common.a) && common.Contains(x.edge.common.b))) { continue; } holeIndexes = hole.Select(x => x.edge.local.a).ToList(); face = AppendElements.CreatePolygon(mesh, holeIndexes, false); } else { IEnumerable <WingedEdge> selected = hole.Where(x => common.Contains(x.edge.common.a)); holeIndexes = selected.Select(x => x.edge.local.a).ToList(); face = AppendElements.CreatePolygon(mesh, holeIndexes, true); } if (face != null) { filled++; appendedFaces.Add(face); } } mesh.SetSelectedFaces(appendedFaces); wings = WingedEdge.GetWingedEdges(mesh); // make sure the appended faces match the first adjacent face found // both in winding and face properties foreach (var appendedFace in appendedFaces) { var wing = wings.FirstOrDefault(x => x.face == appendedFace); if (wing == null) { continue; } using (var it = new WingedEdgeEnumerator(wing)) { while (it.MoveNext()) { if (it.Current == null) { continue; } var currentWing = it.Current; var oppositeFace = it.Current.opposite != null ? it.Current.opposite.face : null; if (oppositeFace != null && !appendedFaces.Contains(oppositeFace)) { currentWing.face.submeshIndex = oppositeFace.submeshIndex; currentWing.face.uv = new AutoUnwrapSettings(oppositeFace.uv); SurfaceTopology.ConformOppositeNormal(currentWing.opposite); break; } } } } mesh.ToMesh(); mesh.Refresh(); mesh.Optimize(); } ProBuilderEditor.Refresh(); if (filled > 0) { res = new ActionResult(ActionResult.Status.Success, filled > 1 ? string.Format("Filled {0} Holes", filled) : "Fill Hole"); } return(res); }