/**
	 *	This method assumes that the split selection edges share a common face and have already been sanity checked.  Will return 
	 *	the variables necessary to compose a new face from the split, or null if the split is invalid.
	 */
	private static bool SplitFace_Internal(SplitSelection splitSelection,
		out pb_Face[] splitFaces,
		out Vector3[][] splitVertices,
		out int[][] splitSharedIndices) 
	{
		splitFaces = null;
		splitVertices = null;
		splitSharedIndices = null;

		pb_Object pb = splitSelection.pb;	// we'll be using this a lot
		pb_Face face = splitSelection.face;	// likewise

		int[] indices = face.distinctIndices;
		pb_IntArray[] sharedIndices = pb.sharedIndices;
		int[] sharedIndex = new int[indices.Length];
		for(int i = 0; i < indices.Length; i++)
			sharedIndex[i] = sharedIndices.IndexOf(indices[i]);

		// First order of business is to translate the face to 2D plane.
		Vector3[] verts = pb.GetVertices(face.distinctIndices);

		Vector3 projAxis = pb_Math.GetProjectionAxis( pb_Math.Normal(pb.GetVertices(face.indices))).ToVector3();
		Vector2[] plane = pb_Math.VerticesTo2DPoints(verts, projAxis);

		// Split points
 		Vector3 splitPointA_3d = splitSelection.pointA;
 		Vector3 splitPointB_3d = splitSelection.pointB;

		Vector2 splitPointA_2d = pb_Math.VerticesTo2DPoints( new Vector3[1] { splitPointA_3d }, projAxis )[0];
		Vector2 splitPointB_2d = pb_Math.VerticesTo2DPoints( new Vector3[1] { splitPointB_3d }, projAxis )[0];

		List<Vector3> v_polyA = new List<Vector3>();	// point in object space
		List<Vector2> v_polyA_2d = new List<Vector2>();	// point in 2d space - used to triangulate
		List<Vector3> v_polyB = new List<Vector3>();	// point in object space
		List<Vector2> v_polyB_2d = new List<Vector2>();	// point in 2d space - used to triangulate
		List<int> i_polyA = new List<int>();			// sharedIndices array index
		List<int> i_polyB = new List<int>();			// sharedIndices array index

		List<int> nedgeA = new List<int>();
		List<int> nedgeB = new List<int>();

		// Sort points into two separate polygons
		for(int i = 0; i < indices.Length; i++)
		{
			// is this point (a) a vertex to split or (b) on the negative or positive side of this split line
			if( (splitSelection.aIsVertex && splitSelection.indexA == indices[i]) ||  (splitSelection.bIsVertex && splitSelection.indexB == indices[i]) )
			{
				v_polyA.Add( verts[i] );
				v_polyB.Add( verts[i] );

				v_polyA_2d.Add( plane[i] );
				v_polyB_2d.Add( plane[i] );

				i_polyA.Add( sharedIndex[i] );
				i_polyB.Add( sharedIndex[i] );
			}
			else
			{
				// split points across the division line
				Vector2 perp = pb_Math.Perpendicular(splitPointB_2d, splitPointA_2d);
				Vector2 origin = (splitPointA_2d + splitPointB_2d) / 2f;
				
				if( Vector2.Dot(perp, plane[i]-origin) > 0 )
				{
					v_polyA.Add(verts[i]);
					v_polyA_2d.Add(plane[i]);
					i_polyA.Add(sharedIndex[i]);
				}
				else
				{
					v_polyB.Add(verts[i]);
					v_polyB_2d.Add(plane[i]);
					i_polyB.Add(sharedIndex[i]);
				}
			}
		}

		if(!splitSelection.aIsVertex)
		{
			v_polyA.Add( splitPointA_3d );
			v_polyA_2d.Add( splitPointA_2d );
			v_polyB.Add( splitPointA_3d );
			v_polyB_2d.Add( splitPointA_2d );
			i_polyA.Add(-1);
			i_polyB.Add(-1);	//	neg 1 because it's a new vertex point

			nedgeA.Add(v_polyA.Count);
			nedgeB.Add(v_polyB.Count);
		}

		if(!splitSelection.bIsVertex)
		{
			v_polyA.Add( splitPointB_3d );
			v_polyA_2d.Add( splitPointB_2d );
			v_polyB.Add( splitPointB_3d );
			v_polyB_2d.Add( splitPointB_2d );
			i_polyA.Add(-1);
			i_polyB.Add(-1);	//	neg 1 because it's a new vertex point
		
			nedgeA.Add(v_polyA.Count);
			nedgeB.Add(v_polyB.Count);
		}

		if(v_polyA_2d.Count < 3 || v_polyB_2d.Count < 3)
		{
			splitFaces = null;
			splitVertices = null;
			splitSharedIndices = null;
			return false;
		}

		// triangulate new polygons
		int[] t_polyA = Delauney.Triangulate(v_polyA_2d).ToIntArray();
		int[] t_polyB = Delauney.Triangulate(v_polyB_2d).ToIntArray();

		if(t_polyA.Length < 3 || t_polyB.Length < 3)
			return false;

		// figure out the face normals for the new faces and check to make sure they match the original face
		Vector2[] pln = pb_Math.VerticesTo2DPoints( pb.GetVertices(face.indices), projAxis );
		Vector3 nrm = Vector3.Cross( pln[2] - pln[0], pln[1] - pln[0]);
		Vector3 nrmA = Vector3.Cross( v_polyA_2d[ t_polyA[2] ]-v_polyA_2d[ t_polyA[0] ], v_polyA_2d[ t_polyA[1] ]-v_polyA_2d[ t_polyA[0] ] );
		Vector3 nrmB = Vector3.Cross( v_polyB_2d[ t_polyB[2] ]-v_polyB_2d[ t_polyB[0] ], v_polyB_2d[ t_polyB[1] ]-v_polyB_2d[ t_polyB[0] ] );

		if(Vector3.Dot(nrm, nrmA) < 0) System.Array.Reverse(t_polyA);
		if(Vector3.Dot(nrm, nrmB) < 0) System.Array.Reverse(t_polyB);

		// triangles, material, pb_UV, smoothing group, shared index
		pb_Face faceA = new pb_Face( t_polyA, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.color);
		pb_Face faceB = new pb_Face( t_polyB, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.color);

		splitFaces = new pb_Face[2] { faceA, faceB };
		splitVertices = new Vector3[2][] { v_polyA.ToArray(), v_polyB.ToArray() };
		splitSharedIndices = new int[2][] { i_polyA.ToArray(), i_polyB.ToArray() };

		return true;
	}
示例#2
0
        /**
         *	This method assumes that the split selection edges share a common face and have already been sanity checked.  Will return
         *	the variables necessary to compose a new face from the split, or null if the split is invalid.
         */
        private static bool SplitFace_Internal(SplitSelection splitSelection,
                                               out pb_Face[] splitFaces,
                                               out Vector3[][] splitVertices,
                                               out Color[][] splitColors,
                                               out Vector2[][] splitUVs,
                                               out int[][] splitSharedIndices)
        {
            splitFaces         = null;
            splitVertices      = null;
            splitColors        = null;
            splitUVs           = null;
            splitSharedIndices = null;

            pb_Object pb   = splitSelection.pb;         // we'll be using this a lot
            pb_Face   face = splitSelection.face;       // likewise

            int[]         indices       = face.distinctIndices;
            pb_IntArray[] sharedIndices = pb.sharedIndices;
            int[]         sharedIndex   = new int[indices.Length];
            for (int i = 0; i < indices.Length; i++)
            {
                sharedIndex[i] = sharedIndices.IndexOf(indices[i]);
            }

            // First order of business is to translate the face to 2D plane.
            Vector3[] verts  = pb.GetVertices(face.distinctIndices);
            Color[]   colors = pbUtil.ValuesWithIndices(pb.colors, face.distinctIndices);
            Vector2[] uvs    = pb.GetUVs(face.distinctIndices);

            Vector3 projAxis = pb_Math.ProjectionAxisToVector(pb_Math.VectorToProjectionAxis(pb_Math.Normal(pb, face)));

            Vector2[] plane = pb_Math.PlanarProject(verts, projAxis);

            // Split points
            Vector3 splitPointA_3d = splitSelection.pointA;
            Vector3 splitPointB_3d = splitSelection.pointB;

            Vector2 splitPointA_uv = splitSelection.aIsVertex ? pb.uv[splitSelection.indexA[0]] : (pb.uv[splitSelection.indexA[0]] + pb.uv[splitSelection.indexA[1]]) / 2f;
            Vector2 splitPointB_uv = splitSelection.bIsVertex ? pb.uv[splitSelection.indexB[0]] : (pb.uv[splitSelection.indexB[0]] + pb.uv[splitSelection.indexB[1]]) / 2f;

            Vector2 splitPointA_2d = pb_Math.PlanarProject(new Vector3[1] {
                splitPointA_3d
            }, projAxis)[0];
            Vector2 splitPointB_2d = pb_Math.PlanarProject(new Vector3[1] {
                splitPointB_3d
            }, projAxis)[0];

            List <Vector3> v_polyA = new List <Vector3>();      // point in object space
            List <Vector3> v_polyB = new List <Vector3>();      // point in object space

            List <Color> c_polyA = new List <Color>();
            List <Color> c_polyB = new List <Color>();

            List <Vector2> v_polyB_2d = new List <Vector2>();   // point in 2d space - used to triangulate
            List <Vector2> v_polyA_2d = new List <Vector2>();   // point in 2d space - used to triangulate

            List <Vector2> u_polyA = new List <Vector2>();
            List <Vector2> u_polyB = new List <Vector2>();

            List <int> i_polyA = new List <int>();                      // sharedIndices array index
            List <int> i_polyB = new List <int>();                      // sharedIndices array index

            List <int> nedgeA = new List <int>();
            List <int> nedgeB = new List <int>();

            // Sort points into two separate polygons
            for (int i = 0; i < indices.Length; i++)
            {
                // is this point (a) a vertex to split or (b) on the negative or positive side of this split line
                if ((splitSelection.aIsVertex && splitSelection.indexA[0] == indices[i]) || (splitSelection.bIsVertex && splitSelection.indexB[0] == indices[i]))
                {
                    v_polyA.Add(verts[i]);
                    v_polyB.Add(verts[i]);

                    u_polyA.Add(uvs[i]);
                    u_polyB.Add(uvs[i]);

                    v_polyA_2d.Add(plane[i]);
                    v_polyB_2d.Add(plane[i]);

                    i_polyA.Add(sharedIndex[i]);
                    i_polyB.Add(sharedIndex[i]);

                    c_polyA.Add(colors[i]);
                    c_polyB.Add(colors[i]);
                }
                else
                {
                    // split points across the division line
                    Vector2 perp   = pb_Math.Perpendicular(splitPointB_2d, splitPointA_2d);
                    Vector2 origin = (splitPointA_2d + splitPointB_2d) / 2f;

                    if (Vector2.Dot(perp, plane[i] - origin) > 0)
                    {
                        v_polyA.Add(verts[i]);
                        v_polyA_2d.Add(plane[i]);
                        u_polyA.Add(uvs[i]);
                        i_polyA.Add(sharedIndex[i]);
                        c_polyA.Add(colors[i]);
                    }
                    else
                    {
                        v_polyB.Add(verts[i]);
                        v_polyB_2d.Add(plane[i]);
                        u_polyB.Add(uvs[i]);
                        i_polyB.Add(sharedIndex[i]);
                        c_polyB.Add(colors[i]);
                    }
                }
            }

            if (!splitSelection.aIsVertex)
            {
                v_polyA.Add(splitPointA_3d);
                v_polyA_2d.Add(splitPointA_2d);
                u_polyA.Add(splitPointA_uv);
                i_polyA.Add(-1);
                c_polyA.Add(splitSelection.colorA);

                v_polyB.Add(splitPointA_3d);
                v_polyB_2d.Add(splitPointA_2d);
                u_polyB.Add(splitPointA_uv);
                i_polyB.Add(-1);                //	neg 1 because it's a new vertex point
                c_polyB.Add(splitSelection.colorA);

                nedgeA.Add(v_polyA.Count);
                nedgeB.Add(v_polyB.Count);
            }

            // PLACE
            if (!splitSelection.bIsVertex)
            {
                v_polyA.Add(splitPointB_3d);
                v_polyA_2d.Add(splitPointB_2d);
                u_polyA.Add(splitPointB_uv);
                i_polyA.Add(-1);
                c_polyB.Add(splitSelection.colorB);

                v_polyB.Add(splitPointB_3d);
                v_polyB_2d.Add(splitPointB_2d);
                u_polyB.Add(splitPointB_uv);
                i_polyB.Add(-1);                //	neg 1 because it's a new vertex point
                c_polyB.Add(splitSelection.colorB);

                nedgeA.Add(v_polyA.Count);
                nedgeB.Add(v_polyB.Count);
            }

            if (v_polyA_2d.Count < 3 || v_polyB_2d.Count < 3)
            {
                splitFaces         = null;
                splitVertices      = null;
                splitSharedIndices = null;
                return(false);
            }

            // triangulate new polygons
            int[] t_polyA = Delaunay.Triangulate(v_polyA_2d).ToIntArray();
            int[] t_polyB = Delaunay.Triangulate(v_polyB_2d).ToIntArray();

            if (t_polyA.Length < 3 || t_polyB.Length < 3)
            {
                return(false);
            }

            // figure out the face normals for the new faces and check to make sure they match the original face
            Vector2[] pln = pb_Math.PlanarProject(pb.GetVertices(face.indices), projAxis);

            Vector3 nrm  = Vector3.Cross(pln[2] - pln[0], pln[1] - pln[0]);
            Vector3 nrmA = Vector3.Cross(v_polyA_2d[t_polyA[2]] - v_polyA_2d[t_polyA[0]], v_polyA_2d[t_polyA[1]] - v_polyA_2d[t_polyA[0]]);
            Vector3 nrmB = Vector3.Cross(v_polyB_2d[t_polyB[2]] - v_polyB_2d[t_polyB[0]], v_polyB_2d[t_polyB[1]] - v_polyB_2d[t_polyB[0]]);

            if (Vector3.Dot(nrm, nrmA) < 0)
            {
                System.Array.Reverse(t_polyA);
            }
            if (Vector3.Dot(nrm, nrmB) < 0)
            {
                System.Array.Reverse(t_polyB);
            }

            // triangles, material, pb_UV, smoothing group, shared index
            pb_Face faceA = new pb_Face(t_polyA, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.manualUV);
            pb_Face faceB = new pb_Face(t_polyB, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.manualUV);

            splitFaces = new pb_Face[2] {
                faceA, faceB
            };
            splitVertices      = new Vector3[2][] { v_polyA.ToArray(), v_polyB.ToArray() };
            splitColors        = new Color[2][] { c_polyA.ToArray(), c_polyB.ToArray() };
            splitUVs           = new Vector2[2][] { u_polyA.ToArray(), u_polyB.ToArray() };
            splitSharedIndices = new int[2][] { i_polyA.ToArray(), i_polyB.ToArray() };

            return(true);
        }