// Split this Face with given Plane public bool Split(Plane inPlane, out CSGFace outFront, out CSGFace outBack) { outFront = new CSGFace(); outBack = new CSGFace(); float[] distance = new float[vertices.Length + 1]; EPlaneSide[] side = new EPlaneSide[vertices.Length + 1]; for (int i = 0; i < vertices.Length; ++i) { distance[i] = inPlane.GetDistanceToPoint(vertices[i]); side[i] = Side(inPlane, vertices[i]); } distance[vertices.Length] = distance[0]; side[vertices.Length] = side[0]; for (int i = 0; i < vertices.Length; ++i) { // if we lie on plane, add them to both if (side[i] == EPlaneSide.Side_Planar) { outFront.AddVertex(vertices[i], uv[i]); outBack.AddVertex(vertices[i], uv[i]); // nothing todo with this vertex continue; } // if we are on the front, add it to front face if (side[i] == EPlaneSide.Side_Front) { outFront.AddVertex(vertices[i], uv[i]); } // if we are on the back, add it to the back side else if (side[i] == EPlaneSide.Side_Back) { outBack.AddVertex(vertices[i], uv[i]); } // check if the next vertex is planar or on the same side, then we do not split if (side[i + 1] == EPlaneSide.Side_Planar || side[i] == side[i + 1]) { continue; } // create split point Vector3 nextVector = vertices[(i + 1) % vertices.Length]; Vector2 nextUV = uv[(i + 1) % uv.Length]; Vector3 newVector, newUV; // if we were on the front if (side[i] == EPlaneSide.Side_Front) { float t = distance[i] / (distance[i] - distance[i + 1]); newVector = vertices[i] + t * (nextVector - vertices[i]); newUV = uv[i] + t * (nextUV - uv[i]); } else // back side... { float t = distance[i + 1] / (distance[i + 1] - distance[i]); newVector = nextVector + t * (vertices[i] - nextVector); newUV = nextUV + t * (uv[i] - nextUV); } // split points are added // add to front outFront.AddVertex(newVector, newUV); // add to back outBack.AddVertex(newVector, newUV); } // Debugging checks if (outFront.vertices.Length < 3 || outBack.vertices.Length < 3) { Debug.Log("Degenerate Faces"); } // todo... outFront.material = material; // outBack.material = material; return(true); }
/// <summary> /// Splits the face in a back and front part. /// </summary> /// <param name="face"></param> /// <param name="splittingPlane"></param> /// <returns></returns> private EPlaneSide splitFaceByPlane( Face face , Plane splittingPlane , out Face frontFace_, out Face backFace_ , float epsilon = 1e-3f//CLIP_EPSILON ) { var numVertices = face.vertices.Count; var dists = new float[numVertices + 1]; var sides = new EPlaneSide[numVertices + 1]; // First, classify all points. This allows us to avoid any bisection if possible var counts = new int[3]; // 'on', 'back' and 'front' var faceStatus = (int)EPlaneSide.On; // determine sides for each point for (int i = 0; i < numVertices; i++) { var vertex = face.vertices[i]; var d = splittingPlane.GetDistanceToPoint(vertex); dists[i] = d; var side = (d > +epsilon) ? EPlaneSide.Front : (d < -epsilon) ? EPlaneSide.Back : EPlaneSide.On; sides[i] = side; faceStatus |= (int)side; counts[(int)side]++; } sides[numVertices] = sides[0]; dists[numVertices] = dists[0]; // if (faceStatus != (int)EPlaneSide.Split) { backFace_ = face; frontFace_ = face; return((EPlaneSide)faceStatus); } Debug.DebugBreak();//AAA // Straddles the splitting plane - we must clip. //mxBIBREF("'float-Time Collision Detection' by Christer Ericson (2005), 8.3.4 Splitting Polygons Against a Plane, PP.369-373"); var MAX_VERTS = 32; var backVerts = new Vector3[MAX_VERTS]; var frontVerts = new Vector3[MAX_VERTS]; var numFront = 0; var numBack = 0; // Test all edges (a, b) starting with edge from last to first Vector3 Vector3 vA = face.vertices[numVertices - 1]; float distA = dists[numVertices - 1]; EPlaneSide sideA = sides[numVertices - 1]; // Loop over all edges given by Vector3 pair (n - 1, n) for (int i = 0; i < numVertices; i++) { Vector3 vB = face.vertices[i]; float distB = dists[i]; EPlaneSide sideB = sides[i]; if (sideB == EPlaneSide.Front) { if (sideA == EPlaneSide.Back) { // Edge (a, b) straddles, output intersection point to both sides // always calculate the split going from the same side or minor epsilon issues can happen Vector3 v = getIntersectionPoint(vB, vA, distB, distA); Debug.Assert(classifyPoint(v, splittingPlane, epsilon) == EPlaneSide.On); frontVerts[numFront++] = backVerts[numBack++] = v; } // In all three cases, output b to the front side frontVerts[numFront++] = vB; } else if (sideB == EPlaneSide.Back) { if (sideA == EPlaneSide.Front) { // Edge (a, b) straddles plane, output intersection point Vector3 v = getIntersectionPoint(vA, vB, distA, distB); Debug.Assert(classifyPoint(v, splittingPlane, epsilon) == EPlaneSide.On); frontVerts[numFront++] = backVerts[numBack++] = v; } else if (sideA == EPlaneSide.On) { // Output a when edge (a, b) goes from ‘on’ to ‘behind’ plane backVerts[numBack++] = vA; } // In all three cases, output b to the back side backVerts[numBack++] = vB; } else { // b is on the plane. In all three cases output b to the front side frontVerts[numFront++] = vB; // In one case, also output b to back side if (sideA == EPlaneSide.Back) { backVerts[numBack++] = vB; } } // Keep b as the starting point of the next edge vA = vB; distA = distB; sideA = sideB; } // frontFace_ = new Face(); frontFace_.vertices = frontVerts.ToList(); backFace_ = new Face(); backFace_.vertices = backVerts.ToList(); Debug.Assert(faceStatus == (int)EPlaneSide.Split); return(EPlaneSide.Split); }
// Split this Face with given Plane public bool Split( Plane inPlane, out Face outFront, out Face outBack ) { outFront = new Face(); outBack = new Face(); float[] distance = new float[vertices.Length + 1]; EPlaneSide[] side = new EPlaneSide[vertices.Length + 1]; for( int i = 0; i < vertices.Length; ++i ) { distance[i] = inPlane.GetDistanceToPoint( vertices[i] ); side[i] = Side( inPlane, vertices[i] ); } distance[vertices.Length] = distance[0]; side[vertices.Length] = side[0]; for( int i = 0; i < vertices.Length; ++i ) { // if we lie on plane, add them to both if( side[i] == EPlaneSide.Side_Planar ) { outFront.AddVertex( vertices[i], uv[i] ); outBack.AddVertex( vertices[i], uv[i] ); // nothing todo with this vertex continue; } // if we are on the front, add it to front face if( side[i] == EPlaneSide.Side_Front ) { outFront.AddVertex( vertices[i], uv[i] ); } // if we are on the back, add it to the back side else if( side[i] == EPlaneSide.Side_Back ) { outBack.AddVertex( vertices[i], uv[i] ); } // check if the next vertex is planar or on the same side, then we do not split if( side[i+1] == EPlaneSide.Side_Planar || side[i] == side[i+1] ) continue; // create split point Vector3 nextVector = vertices[ (i+1) % vertices.Length]; Vector2 nextUV = uv[ (i+1) % uv.Length]; Vector3 newVector, newUV; // if we were on the front if( side[i] == EPlaneSide.Side_Front ) { float t = distance[i] / (distance[i] - distance[i+1]); newVector = vertices[i] + t * (nextVector - vertices[i]); newUV = uv[i] + t * (nextUV - uv[i]); } else // back side... { float t = distance[i+1] / (distance[i+1] - distance[i]); newVector = nextVector + t * (vertices[i] - nextVector); newUV = nextUV + t * (uv[i] - nextUV); } // split points are added // add to front outFront.AddVertex( newVector, newUV ); // add to back outBack.AddVertex( newVector, newUV ); } // Debugging checks if( outFront.vertices.Length < 3 || outBack.vertices.Length < 3 ) Debug.Log("Degenerate Faces"); // todo... outFront.material = material; // outBack.material = material; return true; }