Example #1
0
        /// <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);
        }
Example #2
0
        /// <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);
        }
Example #3
0
 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);
        }