eRETURN_TYPE DoIntersect(const cTRIANGLE3 &triangle, const cSEGMENT3 &lseg, BOOL doDebug) { if(DoIntersect(triangle.ComputeBbox(), lseg.ComputeBbox()) == FAILURE) return FAILURE; cPLANE3 supportingPlane = triangle.SupportingPlane(); cSEGMENT3 resultingSegment; cPOINT3 resultingPoint; if (doDebug){ printf("supportingPlane: "); supportingPlane.Print(); } if(DoIntersect(supportingPlane, lseg) != SUCCESS) return FAILURE; eRETURN_TYPE result = Intersection(supportingPlane, lseg, resultingPoint, resultingSegment); eCOORD maxCoord = supportingPlane.Normal().AbsMaxCoord(); cTRIANGLE2 transformedTriangle(triangle.Vertex(0).DropCoord(maxCoord), triangle.Vertex(1).DropCoord(maxCoord), triangle.Vertex(2).DropCoord(maxCoord)); if(result == RT_POINT3) { //Intersection is a point. cPOINT2 transformedPoint = resultingPoint.DropCoord(maxCoord); if(transformedTriangle.IsPointInside(transformedPoint)) return SUCCESS; else return FAILURE; } else { //Intersection is a line segment. //The segment is on the triangle plane. //Check for actual intersection. //Transform the problem to 2-D problem and try to compute the result. cSEGMENT2 transformedSegment(lseg.Source().DropCoord(maxCoord), lseg.Target().DropCoord(maxCoord)); if(DoIntersect(transformedTriangle, transformedSegment) == SUCCESS) return SUCCESS; return FAILURE; } ASSERT(0); //Should be decided even before it gets here. return FAILURE; }
eRETURN_TYPE DoIntersect(const cTRIANGLE3 &triangle1, const cTRIANGLE3 &triangle2) { for(INT i = 0; i < 3; i ++) if( DoIntersect(triangle2, triangle1.Segment(i)) == SUCCESS ) return SUCCESS; for(INT i = 0; i < 3; i ++) if( DoIntersect(triangle1, triangle2.Segment(i)) == SUCCESS ) return SUCCESS; return FAILURE; }
eRETURN_TYPE DoIntersect(const cTRIANGLE2 &triangle, const cSEGMENT2 &segment) { if(DoIntersect(triangle.ComputeBbox(), segment.ComputeBbox()) == FAILURE) return FAILURE; if(triangle.IsPointInside(segment.Source())) return SUCCESS; if(triangle.IsPointInside(segment.Target())) return SUCCESS; for(INT i = 0; i < 3 ; i++){ if(DoIntersect(triangle.Edge(i), segment) == SUCCESS) return SUCCESS; } return FAILURE; }
eRETURN_TYPE DoIntersect(const cSEGMENT2 &segment1, const cSEGMENT2 &segment2) { if(DoIntersect(segment1.ComputeBbox(), segment2.ComputeBbox()) == FAILURE) return FAILURE; REAL distance[4]; //segment1 cLINE2 segment2Line = segment2.SupportingLine(); distance[0] = segment2Line.SignedDistance(segment1.Source()); if(fabs(distance[0]) < cLIMITS::Tolerance()) distance[0] = 0.0; distance[1] = segment2Line.SignedDistance(segment1.Target()); if(fabs(distance[1]) < cLIMITS::Tolerance()) distance[1] = 0.0; REAL seg1Distance = distance[0]*distance[1]; if(seg1Distance > 0.0) return FAILURE; //segment2 cLINE2 segment1Line = segment1.SupportingLine(); distance[2] = segment1Line.SignedDistance(segment2.Source()); if(fabs(distance[2]) < cLIMITS::Tolerance()) distance[2] = 0.0; distance[3] = segment1Line.SignedDistance(segment2.Target()); if(fabs(distance[3]) < cLIMITS::Tolerance()) distance[3] = 0.0; REAL seg2Distance = distance[2]*distance[3]; if(seg2Distance > 0.0) return FAILURE; if(seg1Distance < 0.0 && seg2Distance < 0.0) return SUCCESS; //Deciding degenerate cases. if(distance[0] == 0.0) if(segment2.IsOnSegment(segment1.Source())) return SUCCESS; if(distance[1] == 0.0) if(segment2.IsOnSegment(segment1.Target())) return SUCCESS; if(distance[2] == 0.0) if(segment1.IsOnSegment(segment2.Source())) return SUCCESS; if(distance[3] == 0.0) if(segment1.IsOnSegment(segment2.Target())) return SUCCESS; return FAILURE; }
void SWrapMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { SWrapObject *obj = (SWrapObject *)GetWSMObject(t); INode *pnode; TriObject *towrapOb=NULL;Object *pobj=NULL; if (obj) pnode=obj->custnode; if (obj && nodeRef && pnode) { Interval valid = FOREVER; if (!obj->cmValid.InInterval(t)) { pobj = pnode->EvalWorldState(t).obj; obj->cmValid=pobj->ObjectValidity(t); Matrix3 tm=pnode->GetObjectTM(t,&(obj->cmValid)); TriObject *wrapOb=IsUseable(pobj,t); if (wrapOb) { if (obj->cmesh) delete obj->cmesh; obj->cmesh=new Mesh; obj->cmesh->DeepCopy(&wrapOb->GetMesh(), PART_GEOM|SELECT_CHANNEL|PART_SUBSEL_TYPE|PART_TOPO|TM_CHANNEL); for (int ic=0;ic<obj->cmesh->getNumVerts();ic++) obj->cmesh->verts[ic]=obj->cmesh->verts[ic]*tm; GetVFLst(obj->cmesh,&obj->vnorms,&obj->fnorms); if (wrapOb!=pobj) wrapOb->DeleteThis(); } } if (!obj->cmesh) return; if ((obj->cmesh->getNumVerts()==0)||(obj->cmesh->getNumFaces()==0)) return; // Matrix3 invtm=Inverse(obj->tm); valid=obj->cmValid; Matrix3 ctm; ctm = nodeRef->GetNodeTM(t,&valid); Ray ray; Point3 v=-ctm.GetRow(2); // Matrix3 nooff=invtm;nooff.NoTrans(); ray.dir=v;//*nooff; int selverts; float kdef,standoff; obj->pblock->GetValue(PB_USESELVERTS,t,selverts,valid); obj->pblock->GetValue(PB_KIDEFAULT,t,kdef,valid); obj->pblock->GetValue(PB_STANDOFF,t,standoff,valid); BezierShape stowrapOb; int found=0; Matrix3 towtm(1); if (os->GetTM()) towtm=*(os->GetTM()); Matrix3 invtowtm=Inverse(towtm); Point3 vert; Class_ID cid=os->obj->ClassID(),es=EDITABLE_SURF_CLASS_ID,efp=FITPOINT_PLANE_CLASS_ID,ecv=EDITABLE_CVCURVE_CLASS_ID,ecfp=EDITABLE_FPCURVE_CLASS_ID; if (((cid==EDITABLE_SURF_CLASS_ID)||(cid==FITPOINT_PLANE_CLASS_ID))||((cid==EDITABLE_CVCURVE_CLASS_ID)||(cid==EDITABLE_FPCURVE_CLASS_ID))) { Object* nurbobj=os->obj; int num=nurbobj->NumPoints(); for (int i=0;i<num;i++) { vert=DoIntersect(nurbobj->GetPoint(i)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); nurbobj->SetPoint(i,(vert*invtowtm)); } } #ifndef NO_PATCHES else if (os->obj->IsSubClassOf(patchObjectClassID)) { PatchObject* patchob=(PatchObject *)os->obj; PatchMesh *pm=&(patchob->patch); int nv=pm->getNumVerts(); BitArray sel = pm->VertSel(); for (int i=0;i<nv;i++) { if (!selverts||sel[i]) { vert=DoIntersect(pm->getVert(i).p*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); vert=vert*invtowtm; pm->setVert(i,vert); } } /* pm->buildLinkages(); pm->computeInteriors(); pm->InvalidateGeomCache();*/ } #endif // NO_PATCHES else if (towrapOb=IsUseable(os->obj,t)) { Point3 tvector; float dist; float *vssel = NULL; if (selverts) vssel = towrapOb->GetMesh().getVSelectionWeights(); for (int i=0;i<towrapOb->GetMesh().getNumVerts();i++) { if ((!selverts)||(towrapOb->GetMesh().vertSel[i]) ||(vssel&&vssel[i])) { vert = DoIntersect(towrapOb->GetMesh().verts[i]*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); vert = vert*invtowtm; if (vssel&&vssel[i]) { tvector = vert - towrapOb->GetMesh().verts[i]; dist = Length(tvector); if ((float)fabs(dist) > EPSILON) tvector = tvector/dist; else tvector = Zero; vert = towrapOb->GetMesh().verts[i] + dist*vssel[i]*tvector; } towrapOb->GetMesh().verts[i] = vert; } } if (towrapOb!=os->obj) towrapOb->DeleteThis(); } else if((os->obj->IsSubClassOf(splineShapeClassID))||(os->obj->CanConvertToType(splineShapeClassID))) { SplineShape *attSplShape = (SplineShape *)os->obj->ConvertToType(t,splineShapeClassID); if (attSplShape) { stowrapOb=attSplShape->shape; for (int poly=0; poly<stowrapOb.splineCount; ++poly) { Spline3D *spline = stowrapOb.GetSpline(poly); int verts = spline->Verts(); int knots = spline->KnotCount(); BitArray sel = stowrapOb.VertexTempSel(poly); Point3 cknot,cknot2; { for(int k=0; k<knots; ++k) { int vert = k * 3 + 1; if (!selverts||sel[vert]) { cknot=DoIntersect(spline->GetKnotPoint(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); attSplShape->shape.SetVert(poly,vert,cknot*invtowtm); if (found) { int knotType = spline->GetKnotType(k); if(knotType & KTYPE_BEZIER) { cknot2= DoIntersect(spline->GetInVec(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); attSplShape->shape.SetVert(poly,vert-1,(found?cknot2:cknot)*invtowtm); cknot2= DoIntersect(spline->GetOutVec(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); attSplShape->shape.SetVert(poly,vert+1,(found?cknot2:cknot)*invtowtm); } } } } } } if (attSplShape!=os->obj) attSplShape->DeleteThis(); } } // os->obj->PointsWereChanged(); os->obj->UpdateValidity(GEOM_CHAN_NUM,valid); // NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); } }