Пример #1
0
    public static void Extrude_Face_MultipleTimes_CreatesValidGeometry([ValueSource("shapeTypes")] ShapeType shape)
    {
        var mesh = ShapeGenerator.CreateShape(shape);

        try
        {
            int initialVertexCount           = mesh.vertexCount;
            UnityEngine.ProBuilder.Face face = mesh.facesInternal[m_Random.Next(0, mesh.facesInternal.Length)];
            mesh.Extrude(new UnityEngine.ProBuilder.Face[] { face }, ExtrudeMethod.FaceNormal, 1f);
            mesh.ToMesh();
            mesh.Refresh();
            LogAssert.NoUnexpectedReceived();
            TestUtility.AssertMeshAttributesValid(mesh.mesh);
            Assert.AreEqual(initialVertexCount + face.edgesInternal.Length * 4, mesh.vertexCount);

            initialVertexCount = mesh.vertexCount;
            mesh.Extrude(new UnityEngine.ProBuilder.Face[] { face }, ExtrudeMethod.VertexNormal, 1f);
            mesh.ToMesh();
            mesh.Refresh();
            LogAssert.NoUnexpectedReceived();
            TestUtility.AssertMeshAttributesValid(mesh.mesh);
            Assert.AreEqual(initialVertexCount + face.edgesInternal.Length * 4, mesh.vertexCount);

            initialVertexCount = mesh.vertexCount;
            mesh.Extrude(new UnityEngine.ProBuilder.Face[] { face }, ExtrudeMethod.IndividualFaces, 1f);
            mesh.ToMesh();
            mesh.Refresh();
            LogAssert.NoUnexpectedReceived();
            TestUtility.AssertMeshAttributesValid(mesh.mesh);
            Assert.AreEqual(initialVertexCount + face.edgesInternal.Length * 4, mesh.vertexCount);
        }
        catch (Exception e)
        {
            Debug.LogError(e.ToString());
        }
        finally
        {
            if (mesh != null)
            {
                Object.DestroyImmediate(mesh.gameObject);
            }
        }
    }
Пример #2
0
 /// <summary>
 /// Deep copy constructor.
 /// </summary>
 /// <param name="other">The Face from which to copy properties.</param>
 public Face(Face other)
 {
     CopyFrom(other);
 }
 public void SetSingleFace(Face face)
 {
     faces.Clear();
     faces.Add(face);
 }
 internal static void Unwrap(ProBuilderMesh mesh, Face face, Vector3 projection = default)
 {
     Projection.PlanarProject(mesh, face, projection != Vector3.zero ? projection : Vector3.zero);
     ApplyUVSettings(mesh.texturesInternal, face.distinctIndexesInternal, face.uv);
 }
        /// <summary>
        /// Pick faces contained within rect.
        /// </summary>
        /// <param name="cam"></param>
        /// <param name="rect">Rect is in GUI space, where 0,0 is top left of screen, width = cam.pixelWidth / pointsPerPixel.</param>
        /// <param name="selectable"></param>
        /// <param name="options"></param>
        /// <param name="pixelsPerPoint">Scale the render texture to match rect coordinates. Generally you'll just pass in EditorGUIUtility.pixelsPerPoint.</param>
        /// <returns></returns>
        public static Dictionary <ProBuilderMesh, HashSet <Face> > PickFacesInRect(
            Camera cam,
            Rect rect,
            IList <ProBuilderMesh> selectable,
            PickerOptions options,
            float pixelsPerPoint = 1f)
        {
            if (options.depthTest && options.rectSelectMode == RectSelectMode.Partial)
            {
                return(SelectionPickerRenderer.PickFacesInRect(
                           cam,
                           rect,
                           selectable,
                           (int)(cam.pixelWidth / pixelsPerPoint),
                           (int)(cam.pixelHeight / pixelsPerPoint)));
            }

            var selected = new Dictionary <ProBuilderMesh, HashSet <Face> >();

            foreach (var pb in selectable)
            {
                if (!pb.selectable)
                {
                    continue;
                }

                HashSet <Face> selectedFaces = new HashSet <Face>();
                Transform      trs           = pb.transform;
                Vector3[]      positions     = pb.positionsInternal;
                Vector3[]      screenPoints  = new Vector3[pb.vertexCount];

                for (int nn = 0; nn < pb.vertexCount; nn++)
                {
                    screenPoints[nn] = cam.ScreenToGuiPoint(cam.WorldToScreenPoint(trs.TransformPoint(positions[nn])), pixelsPerPoint);
                }

                for (int n = 0; n < pb.facesInternal.Length; n++)
                {
                    Face face = pb.facesInternal[n];

                    // rect select = complete
                    if (options.rectSelectMode == RectSelectMode.Complete)
                    {
                        // face is behind the camera
                        if (screenPoints[face.indexesInternal[0]].z < cam.nearClipPlane)
                        {
                            continue;
                        }

                        // only check the first index per quad, and if it checks out, then check every other point
                        if (rect.Contains(screenPoints[face.indexesInternal[0]]))
                        {
                            bool nope = false;

                            for (int q = 1; q < face.distinctIndexesInternal.Length; q++)
                            {
                                int index = face.distinctIndexesInternal[q];

                                if (screenPoints[index].z < cam.nearClipPlane || !rect.Contains(screenPoints[index]))
                                {
                                    nope = true;
                                    break;
                                }
                            }

                            if (!nope)
                            {
                                if (!options.depthTest ||
                                    !HandleUtility.PointIsOccluded(cam, pb, trs.TransformPoint(Math.Average(positions, face.distinctIndexesInternal))))
                                {
                                    selectedFaces.Add(face);
                                }
                            }
                        }
                    }
                    // rect select = partial
                    else
                    {
                        Bounds2D poly     = new Bounds2D(screenPoints, face.edgesInternal);
                        bool     overlaps = false;

                        if (poly.Intersects(rect))
                        {
                            // if rect contains one point of polygon, it overlaps
                            for (int nn = 0; nn < face.distinctIndexesInternal.Length && !overlaps; nn++)
                            {
                                Vector3 p = screenPoints[face.distinctIndexesInternal[nn]];
                                overlaps = p.z > cam.nearClipPlane && rect.Contains(p);
                            }

                            // if polygon contains one point of rect, it overlaps. otherwise check for edge intersections
                            if (!overlaps)
                            {
                                Vector2 tl = new Vector2(rect.xMin, rect.yMax);
                                Vector2 tr = new Vector2(rect.xMax, rect.yMax);
                                Vector2 bl = new Vector2(rect.xMin, rect.yMin);
                                Vector2 br = new Vector2(rect.xMax, rect.yMin);

                                overlaps = Math.PointInPolygon(screenPoints, poly, face.edgesInternal, tl);
                                if (!overlaps)
                                {
                                    overlaps = Math.PointInPolygon(screenPoints, poly, face.edgesInternal, tr);
                                }
                                if (!overlaps)
                                {
                                    overlaps = Math.PointInPolygon(screenPoints, poly, face.edgesInternal, br);
                                }
                                if (!overlaps)
                                {
                                    overlaps = Math.PointInPolygon(screenPoints, poly, face.edgesInternal, bl);
                                }

                                // if any polygon edge intersects rect
                                for (int nn = 0; nn < face.edgesInternal.Length && !overlaps; nn++)
                                {
                                    if (Math.GetLineSegmentIntersect(tr, tl, screenPoints[face.edgesInternal[nn].a], screenPoints[face.edgesInternal[nn].b]))
                                    {
                                        overlaps = true;
                                    }
                                    else if (Math.GetLineSegmentIntersect(tl, bl, screenPoints[face.edgesInternal[nn].a], screenPoints[face.edgesInternal[nn].b]))
                                    {
                                        overlaps = true;
                                    }
                                    else if (Math.GetLineSegmentIntersect(bl, br, screenPoints[face.edgesInternal[nn].a], screenPoints[face.edgesInternal[nn].b]))
                                    {
                                        overlaps = true;
                                    }
                                    else if (Math.GetLineSegmentIntersect(br, tl, screenPoints[face.edgesInternal[nn].a], screenPoints[face.edgesInternal[nn].b]))
                                    {
                                        overlaps = true;
                                    }
                                }
                            }
                        }

                        // don't test occlusion since that case is handled special
                        if (overlaps)
                        {
                            selectedFaces.Add(face);
                        }
                    }
                }

                selected.Add(pb, selectedFaces);
            }

            return(selected);
        }