static void FaceEdgeSplicer(Face & face,int vi0,BSPNode *n) { // the face's edge starting from vertex vi0 is sliced by any incident hypeplane in the bsp if(n->isleaf) return; int vi1 = (vi0+1)%face.vertex.size(); float3 v0 = face.vertex[vi0]; float3 v1 = face.vertex[vi1]; assert(magnitude(v0-v1) > QUANTIZEDCHECK ); int f0 = PlaneTest(float4(n->xyz(), n->w), v0); int f1 = PlaneTest(float4(n->xyz(), n->w), v1); if(f0==COPLANAR && f1== COPLANAR) { // have to pass down both sides, but we have to make sure we do all subsegments generated by the first side int count = face.vertex.size(); FaceEdgeSplicer(face,vi0,n->under.get()); int k=vi0 + (face.vertex.size()-count); while(k>=vi0) { FaceEdgeSplicer(face,k,n->over.get()); k--; } } else if((f0|f1) == UNDER) { FaceEdgeSplicer(face,vi0,n->under.get()); } else if((f0|f1) == OVER) { FaceEdgeSplicer(face,vi0,n->over.get()); } else { edgesplitcount++; assert(magnitude(v0-v1) > QUANTIZEDCHECK); assert((f0|f1) == SPLIT); float3 vmid = PlaneLineIntersection(*n,v0,v1); assert(magnitude(vmid-v1) > QUANTIZEDCHECK); assert(magnitude(v0-vmid) > QUANTIZEDCHECK); int fmid = PlaneTest(float4(n->xyz(), n->w), vmid); assert(fmid==0); face.vertex.insert(face.vertex.begin() + vi0 + 1, vmid); // Insert(face.vertex, vmid, vi0 + 1); if(f0==UNDER) { FaceEdgeSplicer(face,vi0+1,n->over.get()); FaceEdgeSplicer(face,vi0 ,n->under.get()); } else { assert(f0==OVER); FaceEdgeSplicer(face,vi0+1,n->under.get()); FaceEdgeSplicer(face,vi0 ,n->over.get()); } } }
btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint) { static btVector3 cp; cp = cross(udir,vdir).normalized(); btScalar distu = -dot(cp,ustart); btScalar distv = -dot(cp,vstart); btScalar dist = (btScalar)fabs(distu-distv); if(upoint) { btPlane plane; plane.normal = cross(vdir,cp).normalized(); plane.dist = -dot(plane.normal,vstart); *upoint = PlaneLineIntersection(plane,ustart,ustart+udir); } if(vpoint) { btPlane plane; plane.normal = cross(udir,cp).normalized(); plane.dist = -dot(plane.normal,ustart); *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir); } return dist; }
void FaceSlice(Face & face,const float4 &clip) { int count=0; for(unsigned int i=0;i<face.vertex.size();i++) { unsigned int i2=(i+1)%face.vertex.size(); int vf0 = PlaneTest(clip, face.vertex[i]); int vf2 = PlaneTest(clip, face.vertex[i2]); if((vf0==OVER && vf2==UNDER)|| (vf0==UNDER && vf2==OVER ) ) { float3 vmid; vmid = PlaneLineIntersection(clip,face.vertex[i],face.vertex[i2]); assert(!PlaneTest(clip, vmid)); face.vertex.insert(face.vertex.begin() + i2, vmid); // Insert(face.vertex, vmid, i2); i=0; assert(count<2); count++; } } }
static void BSPClipFace(BSPNode *n,Face && face,const float3 &position,std::vector<Face> &under,std::vector<Face> &over) { if(n->isleaf==UNDER) { under.push_back(face); return; } if(n->isleaf==OVER) { over.push_back(face); return; } float4 plane(n->xyz(), n->w + dot(position, n->xyz())); int flag = FaceSplitTest(face, plane); if(flag == UNDER) { return BSPClipFace(n->under.get(),std::move(face),position,under,over); } if(flag == OVER) { return BSPClipFace(n->over.get(),std::move(face),position,under,over); } if(flag==COPLANAR) { return BSPClipFace(dot(n->xyz(), face.xyz()) > 0 ? n->under.get() : n->over.get(), std::move(face), position, under, over); } assert(flag==SPLIT); Face funder, fover; fover.xyz() = funder.xyz() = face.xyz(); fover.w = funder.w = face.w; fover.gu = funder.gu = face.gu; fover.gv = funder.gv = face.gv; fover.ot = funder.ot = face.ot; fover.matid= funder.matid= face.matid; for(unsigned int i=0;i<face.vertex.size();i++){ float3& vi = face.vertex[i]; float3& vi1= face.vertex[(i+1)%face.vertex.size()]; int vf = PlaneTest(float4(plane.xyz(), plane.w), vi); int vf1 = PlaneTest(float4(plane.xyz(), plane.w), vi1); if(vf==COPLANAR) { funder.vertex.push_back(vi); fover.vertex.push_back(vi); continue; // possible loop optimization } else if(vf==UNDER) { funder.vertex.push_back(vi); } else { assert(vf==OVER); fover.vertex.push_back(vi); } if(vf != vf1 && vf !=COPLANAR && vf1 != COPLANAR) { float3 vmid = PlaneLineIntersection(plane.xyz(), plane.w, vi, vi1); funder.vertex.push_back(vmid); fover.vertex.push_back(vmid); } } BSPClipFace(n->under.get(),std::move(funder),position,under,over); BSPClipFace(n->over.get() ,std::move(fover) ,position,under,over); }