POLY poly, POLY plane;
for(i++<poly.numVerts) {
Vec direction = poly - poly[(i+1)%poly.numVerts];
float linelength = D3DXVec3Dot(&direction, &plane.normal);
Vec L1 = plane[0] - poly;
float dist_from_plane = D3DXVec3Dot(&L1, &plane.normal);
float percentage = dist_from_plane / linelength;
Vec intersection = poly + (direction * percentage);
}
Everything works correctly except for when poly and poly[i+1] forms a diagnoal line. [Edited by - Sfpiano on October 18, 2005 10:03:37 PM]
🔒 Locked
BSP Splitting errors
Advertisement
Original Post
I've tried about 4 different versions from unique sources, and all of them give me the same error when trying to split a polygon with a plane. I have the plane and polygon intersecting perpendicularly. The way all of the algorithms work is that they compare the current vertex to the one before it and find the distance between them where that lien crosses the plane. The problem is that the point where they cross is not where the vertex of the new polygon should be. If I have a plane that spans along the X-axis and I have a line that spans the Z-axis and runs through it, the point of intersection will be something like (0, .67, 0); however the point where the polygon's vertex should be in that situation is (0, 0, 0) - the x and z values remain the same, but the y value needs to be lowered in this case. Here's the code I have now from codesampler.com:
for(i=0; i<poly.numPoints; i++) { int m = (i + 1)%poly.numPoints; bool bIgnore = false; switch(classPos) { case INFRONT: { front.ppVertices.push_back(poly.ppVertices); front.numPoints++; break; case BEHIND: back.ppVertices.push_back(poly.ppVertices); back.numPoints++; break; case COINCIDING: front.ppVertices.push_back(poly.ppVertices); back.ppVertices.push_back(poly.ppVertices); front.numPoints++; back.numPoints++; continue; }if( classPos == COINCIDING && classPos[m] != COINCIDING ) { bIgnore = true;}else if( classPos[m] == COINCIDING && classPos != COINCIDING ) { bIgnore = true;}if( !bIgnore && (classPos != classPos[m]) ) {getIntersect(poly.ppVertices->vPos, poly.ppVertices[m]->vPos, divider.ppVertices[0]->vPos, divider.vNormal, IntersectPoint, percent);}///////////////////////////////////////////////////////////////////bool getIntersect( D3DXVECTOR3 linestart, D3DXVECTOR3 lineend, D3DXVECTOR3 vertex, D3DXVECTOR3 normal, D3DXVECTOR3 &intersection, float &percentage ){ D3DXVECTOR3 direction; D3DXVECTOR3 L1; float linelength; float dist_from_plane; direction = lineend - linestart; linelength = D3DXVec3Dot(&direction, &normal); if( fabsf( linelength ) < EPSILON ) return false; L1 = vertex - linestart; dist_from_plane = D3DXVec3Dot(&L1, &normal); percentage = dist_from_plane / linelength; intersection = linestart + (direction * percentage); return true;}
It would take a little work to go through that code, so I'm just going to punt and post some of my own:
I think I moved some brackets around since the last time I tested this code, so I suppose I could have screwed something up there (nothing you couldn't fix though). Other than that, I think it's been tested successfully and works as advertised. You can use it as is, or use it as a reference for fixing your own code.
Oh, and one more thing. You mentioned in your first post that you'd tried several different versions and gotten the same results each time. If you try the above code and get the same results, it may be that something is wrong with your input.
void SplitPolygon( const std::vector<Vector3>& p, // Input polygon std::vector<Vector3>& pf, // Front poly after split std::vector<Vector3>& pb, // Back poly after split const Vector3& n, // Plane normal float d, // Plane distance (p.n = d) float epsilon) // Tolerance for point-on-plane{ if (p.empty()) { return; } std::vector<float> dist(p.size()); std::vector<int> side(p.size()); int numFront = 0; int numBack = 0; enum {ON, FRONT, BACK, SPANNING}; for (int i = 0; i < p.size(); ++i) { dist = p.Dot(n) - d; if (dist > epsilon) { side = FRONT; ++numFront; } else if (dist < -epsilon) { side = BACK; ++numBack; } else { side = ON; } } pf.clear(); pb.clear(); if (!numBack) { pf = p; } else if (!numFront) { pb = p; } else { for (int i = 0; i < p.size(); ++i) { if (!(side & BACK)) { pf.push_back(p); } if (!(side & FRONT)) { pb.push_back(p); } int j = (i + 1) % p.size(); if ((side | side[j]) == SPANNING) { float t = dist / (dist - dist[j]); Vector3 v = (1.0f - t) * p + t * p[j]; pf.push_back(v); pb.push_back(v); } } }}I think I moved some brackets around since the last time I tested this code, so I suppose I could have screwed something up there (nothing you couldn't fix though). Other than that, I think it's been tested successfully and works as advertised. You can use it as is, or use it as a reference for fixing your own code.
Oh, and one more thing. You mentioned in your first post that you'd tried several different versions and gotten the same results each time. If you try the above code and get the same results, it may be that something is wrong with your input.
Here is the problem as I understand it:

That black dot (0,1,0) is the actual intersection between the diagonal line and the other plane. However, that is not where the vertex of the split plane should be. There should be two on that line - one above the point at (0,2,0) and the other below at (0,0,0).
[Edited by - Sfpiano on October 27, 2005 9:08:05 PM]
That black dot (0,1,0) is the actual intersection between the diagonal line and the other plane. However, that is not where the vertex of the split plane should be. There should be two on that line - one above the point at (0,2,0) and the other below at (0,0,0).
[Edited by - Sfpiano on October 27, 2005 9:08:05 PM]
Let's ignore my code and look at jyk's because it's more consise and I get better results. (You were right, that INFRONT { was a copying error, and I do store the split vertex, but I left that part out)
Anyway, how can I not include the diagonal line if I iterate through all of the vertices of the input polygon? The vertices are arranged as so:
So when i=1 and i+1=2, the line that will be compared with the plane will be the diagonal from vertex 1 to vertex 2.
When I run the function, here are the vertices I get for the back split:
As you can see, they're not in order, there's too many of them, and the (0,1,0) should be (0,0,0)
Anyway, how can I not include the diagonal line if I iterate through all of the vertices of the input polygon? The vertices are arranged as so:
1/4-------5| || || |0-------2/3So when i=1 and i+1=2, the line that will be compared with the plane will be the diagonal from vertex 1 to vertex 2.
When I run the function, here are the vertices I get for the back split:
{ x=0 y=2 z=2 }{ x=0 y=2 z=0 }{ x=0 y=1 z=0 }{ x=0 y=0 z=2 }{ x=0 y=0 z=2 }{ x=0 y=1 z=0 }{ x=0 y=1 z=0 }As you can see, they're not in order, there's too many of them, and the (0,1,0) should be (0,0,0)
I'm still confused about the problem. If you're splitting, say, a polygon with 4 sides, you shouldn't be considering the diagonal at all. There are four edges; you split each of them to the plane and use the results to create the resulting front and back polygons (which is what my code does).
Ok, looking at your diagrams, it looks like you're considering the quad as 2 triangles, i.e. 6 verts (or 4 if the verts are shared) and 6 edges? The algorithm isn't set up to process the polygon in that form. It should just be a sequence of vertices, wound either clockwise or counterclockwise around the polygon, that implicitly defines the edges of the polygon. For a quad, that would be 4 verts only.
Anyway, I may be confused about what you're doing, but maybe the above will get you moving in the right direction...
Ok, looking at your diagrams, it looks like you're considering the quad as 2 triangles, i.e. 6 verts (or 4 if the verts are shared) and 6 edges? The algorithm isn't set up to process the polygon in that form. It should just be a sequence of vertices, wound either clockwise or counterclockwise around the polygon, that implicitly defines the edges of the polygon. For a quad, that would be 4 verts only.
Anyway, I may be confused about what you're doing, but maybe the above will get you moving in the right direction...
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement