YSRESULT YsClipInfiniteLine3 (YsVec3 &c1,YsVec3 &c2, const YsVec3 &org,const YsVec3 &vec,const YsVec3 &range1,const YsVec3 &range2) { YsBoundingBoxMaker3 bbx; YsVec3 r[2]; YsVec3 t1,t2; bbx.Begin(range1); bbx.Add(range2); bbx.Get(r[0],r[1]); if(YsClipInfiniteLine3_FindFirstIntersection(t1,org,vec,r)==YSOK && YsClipInfiniteLine3_FindSecondIntersection(t2,t1,vec,r)==YSOK) { if((t2-t1)*vec>=0.0) { c1=t1; c2=t2; } else { c1=t2; c2=t1; } return YSOK; } return YSERR; }
/* static */ void FsLazyWindowApplication::GetBoundingBox(YsVec3 &min,YsVec3 &max,const std::vector <float> &vtx) { auto nVtx=vtx.size()/3; if(0==nVtx) { min=YsVec3::Origin(); max=YsVec3::Origin(); } else { YsBoundingBoxMaker3 mkBbx; for(decltype(nVtx) i=0; i<nVtx; ++i) { YsVec3 pos(vtx[i*3],vtx[i*3+1],vtx[i*3+2]); mkBbx.Add(pos); } mkBbx.Get(min,max); } }
void YsCollisionOfPolygon::SetPolygon2(YSSIZE_T nv2,const YsVec3 v2[],const YsVec3 &nom2) { if(nv2>0) { np2=nv2; p2=v2; YsBoundingBoxMaker3 bbx; bbx.Make(nv2,v2); bbx.Get(p2min,p2max); YsVec3 nom; nom=nom2; if(nom.IsNormalized()!=YSTRUE) { nom.Normalize(); } pln2.Set(v2[0],nom); } }
void YsCollisionOfPolygon::SetPolygon1(YSSIZE_T nv1,const YsVec3 v1[],const YsVec3 &nom1) { if(nv1>0) { np1=nv1; p1=v1; YsBoundingBoxMaker3 bbx; bbx.Make(nv1,v1); bbx.Get(p1min,p1max); YsVec3 nom; nom=nom1; if(nom.IsNormalized()!=YSTRUE) { nom.Normalize(); } pln1.Set(v1[0],nom); p1Prj.Set(0,NULL); } }
YSBOOL YsCollisionOfPolygon::CheckIntersectionBetweenPolygon1AndLineSegment(YsVec3 &crs,const YsVec3 &x1,const YsVec3 &x2) const { YsVec3 bbx1,bbx2; YsBoundingBoxMaker3 bbx; YSSIDE is; bbx.Begin(x1); bbx.Add(x2); bbx.Get(bbx1,bbx2); if(YsCheckBoundingBoxCollision3(p1min,p1max,bbx1,bbx2)==YSTRUE) { if(pln1.GetPenetration(crs,x1,x2)==YSOK) { is=CheckInsideOfPolygon1(crs); // is=YsCheckInsidePolygon3(crs,np1,p1); if(is==YSINSIDE || is==YSBOUNDARY) { return YSTRUE; } } } return YSFALSE; }
YSRESULT YsClipLineSeg3 (YsVec3 &newP1,YsVec3 &newP2,const YsVec3 &p1,const YsVec3 &p2,const YsVec3 &range1,const YsVec3 &range2) { int j,nInComp; YsVec3 min,max; YsBoundingBoxMaker3 bbx; bbx.Begin(range1); bbx.Add(range2); bbx.Get(min,max); nInComp=0; for(j=0; j<3; j++) { if(min.GetValue()[j]<=p1.GetValue()[j] && p1.GetValue()[j]<=max.GetValue()[j] && min.GetValue()[j]<=p2.GetValue()[j] && p2.GetValue()[j]<=max.GetValue()[j]) { nInComp++; } if(p1.GetValue()[j]<min.GetValue()[j] && p2.GetValue()[j]<min.GetValue()[j]) { return YSERR; } if(p1.GetValue()[j]>max.GetValue()[j] && p2.GetValue()[j]>max.GetValue()[j]) { return YSERR; } } if(nInComp==3) { newP1=p1; newP2=p2; return YSOK; } YsVec3 c1,c2; if(YsClipInfiniteLine3(c1,c2,p1,p2-p1,min,max)==YSOK) { if(YsCheckInBetween3(c1,p1,p2)==YSTRUE && YsCheckInBetween3(c2,p1,p2)==YSTRUE) { newP1=c1; newP2=c2; return YSOK; } else if(YsCheckInBetween3(c1,p1,p2)==YSTRUE) { // p1-c1 or c1-p2 if(YsCheckInBetween3(p1,c1,c2)==YSTRUE) { newP1=p1; newP2=c1; } else { newP1=c1; newP2=p2; } return YSOK; } else if(YsCheckInBetween3(c2,p1,p2)==YSTRUE) { // p1-c2 or c2-p2 if(YsCheckInBetween3(p1,c1,c2)==YSTRUE) { newP1=p1; newP2=c2; } else { newP1=c2; newP2=p2; } return YSOK; } else { return YSERR; } } else { return YSERR; } }
YSRESULT YsClipPolygon3 (int &newNp,YsVec3 newp[],int bufLen,int np,const YsVec3 p[],const YsVec3 &range1,const YsVec3 &range2) { YsVec3 min,max; YsBoundingBoxMaker3 bbx; int i,j,nIn,nOut[6]; bbx.Begin(range1); bbx.Add(range2); bbx.Get(min,max); nIn=0; nOut[0]=0; nOut[1]=0; nOut[2]=0; nOut[3]=0; nOut[4]=0; nOut[5]=0; for(i=0; i<np; i++) { if(min.x()<=p[i].x() && p[i].x()<=max.x() && min.y()<=p[i].y() && p[i].y()<=max.y() && min.z()<=p[i].z() && p[i].z()<=max.z()) { nIn++; } else { for(j=0; j<3; j++) { if(p[i].GetValue()[j]<min.GetValue()[j]) { nOut[j*2 ]++; } else if(p[i].GetValue()[j]>max.GetValue()[j]) { nOut[j*2+1]++; } } } } if(nIn==np) { if(bufLen>=np) { newNp=np; for(i=0; i<np; i++) { newp[i]=p[i]; } return YSOK; } else { return YSERR; } } if(nOut[0]==np || nOut[1]==np || nOut[2]==np || nOut[3]==np || nOut[4]==np || nOut[5]==np) { newNp=0; return YSOK; } YsOneMemoryBlock <YsVec3,1024> memblk1; YsOneMemoryBlock <YsVec3,1024> memblk2; YsOneMemoryBlock <YsVec3,1024> memblk3; YsOneMemoryBlock <YsVec3,1024> memblk4; YsOneMemoryBlock <YsVec3,1024> memblk5; YsVec3 *plg1,*plg2,*plg3,*plg4,*plg5; int nplg1,nplg2,nplg3,nplg4,nplg5; plg1=memblk1.GetMemoryBlock(bufLen); plg2=memblk2.GetMemoryBlock(bufLen); plg3=memblk3.GetMemoryBlock(bufLen); plg4=memblk4.GetMemoryBlock(bufLen); plg5=memblk5.GetMemoryBlock(bufLen); if(YsClipPolygon3_ByOnePlane(nplg1,plg1,bufLen,np ,p ,min,0,YSFALSE)==YSOK && YsClipPolygon3_ByOnePlane(nplg2,plg2,bufLen,nplg1,plg1,min,1,YSFALSE)==YSOK && YsClipPolygon3_ByOnePlane(nplg3,plg3,bufLen,nplg2,plg2,min,2,YSFALSE)==YSOK && YsClipPolygon3_ByOnePlane(nplg4,plg4,bufLen,nplg3,plg3,max,0,YSTRUE)==YSOK && YsClipPolygon3_ByOnePlane(nplg5,plg5,bufLen,nplg4,plg4,max,1,YSTRUE)==YSOK && YsClipPolygon3_ByOnePlane(newNp,newp,bufLen,nplg5,plg5,max,2,YSTRUE)==YSOK) { return YSOK; } return YSERR; // Buffer overflow }
YSBOOL YsCollisionOfPolygon::CheckIntersectionBetweenPolygon1AndBlock(const YsVec3 &corner1,const YsVec3 &corner2) const { int i; YsVec3 is,cube[8]; // YsVec3 face[4]; // int cubeFaceIdx[6][4]= // { // {0,1,2,3}, // {4,5,6,7}, // {0,1,5,4}, // {1,2,6,5}, // {2,3,7,6}, // {3,0,4,7} // }; static const int cubeEdgeIdx[12][2]= { {0,1},{1,2},{2,3},{3,0}, {4,5},{5,6},{6,7},{7,4}, {0,4},{1,5},{2,6},{3,7} }; int np; const YsVec3 *p; YsBoundingBoxMaker3 bbx; YsVec3 min,max; np=GetNumVertexOfPolygon1(); p=GetVertexListOfPolygon1(); // Constrain min and max bbx.Begin(corner1); bbx.Add(corner2); bbx.Get(min,max); if(YsCheckBoundingBoxCollision3(p1min,p1max,min,max)!=YSTRUE) { return YSFALSE; } cube[0].Set(min.x(),min.y(),min.z()); cube[1].Set(max.x(),min.y(),min.z()); cube[2].Set(max.x(),max.y(),min.z()); cube[3].Set(min.x(),max.y(),min.z()); cube[4].Set(min.x(),min.y(),max.z()); cube[5].Set(max.x(),min.y(),max.z()); cube[6].Set(max.x(),max.y(),max.z()); cube[7].Set(min.x(),max.y(),max.z()); // If all corners are one side of the plane, no intersection int nSide[3]; nSide[0]=0; nSide[1]=0; nSide[2]=0; for(i=0; i<8; i++) { // Old Implementation (modified 10/24/2001) // nSide[pln1.GetSideOfPlane(cube[i])+1]++; // Modified 10/24/2001; int side; side=pln1.GetSideOfPlane(cube[i]); nSide[side+1]++; if(side==0) { YSSIDE sideOfPolygon; sideOfPolygon=CheckInsideOfPolygon1(cube[i]); // sideOfPolygon=YsCheckInsidePolygon3(cube[i],np1,p1); if(sideOfPolygon==YSINSIDE || sideOfPolygon==YSBOUNDARY) { return YSTRUE; } } } if((nSide[0]==0 && nSide[1]==0 && nSide[2]>0) || (nSide[0]>0 && nSide[1]==0 && nSide[2]==0)) { return YSFALSE; } // One of the point is contained inside the region for(i=0; i<np; i++) { if(YsCheckInsideBoundingBox3(p[i],min,max)==YSTRUE) { return YSTRUE; } } // One of the edges of the block intersect with the polygon for(i=0; i<12; i++) { if(CheckIntersectionBetweenPolygon1AndLineSegment(cube[cubeEdgeIdx[i][0]],cube[cubeEdgeIdx[i][1]])==YSTRUE) { return YSTRUE; } } // One of the face of the box intersect with the polygon (kind of corner cutting) const int xComp=0,yComp=1,zComp=2; static const int componentTable[3][3]= { {xComp,yComp,zComp}, // Left,Right face : Normal in xComp direction, region in yComp,zComp plane {yComp,xComp,zComp}, // Top,Bottom face : Normal in yComp direction, region in xComp,zComp plane {zComp,xComp,yComp} // Front,Back face : Normal in zComp direction, region in xComp,yComp plane }; static const double dirTable[3][3]= { {1.0,0.0,0.0}, // Normal for Left/Right face {0.0,1.0,0.0}, // Normal for Top/Bottom face {0.0,0.0,1.0} // Normal for Front/Back face }; for(i=0; i<3; i++) { int j,k; YsVec2 plnRegion1,plnRegion2; int nomComp,plnComp1,plnComp2; YsVec3 nom; nomComp=componentTable[i][0]; plnComp1=componentTable[i][1]; plnComp2=componentTable[i][2]; plnRegion1.Set(min.GetValue()[plnComp1]-YsTolerance,min.GetValue()[plnComp2]-YsTolerance); plnRegion2.Set(max.GetValue()[plnComp1]+YsTolerance,max.GetValue()[plnComp2]+YsTolerance); nom.Set(dirTable[nomComp][0],dirTable[nomComp][1],dirTable[nomComp][2]); for(j=0; j<2; j++) { YsPlane pln; YsVec3 org; org=(j==0 ? min : max); pln.Set(org,nom); for(k=0; k<np1; k++) { YsVec3 x1,x2; YsVec2 ref; x1=p1[k]; x2=p1[(k+1)%np1]; if(pln.GetPenetration(is,x1,x2)==YSOK) { ref.Set(is.GetValue()[plnComp1],is.GetValue()[plnComp2]); if(YsCheckInsideBoundingBox2(ref,plnRegion1,plnRegion2)==YSTRUE) { return YSTRUE; } } } } } return YSFALSE; }