void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation) { orientation = !orientation; ViewEdge::vertex_iterator v; ViewEdge::vertex_iterator vend; ViewEdge::vertex_iterator vfirst; Vec3r previous, current; if (true == orientation) { v = iViewEdge->vertices_begin(); vfirst = v; vend = iViewEdge->vertices_end(); } else { v = iViewEdge->vertices_last(); vfirst = v; vend = iViewEdge->vertices_end(); } if (!_Vertices.empty()) { previous = _Vertices.front()->point2d(); if (orientation) ++v; else --v; // Ensure the continuity of underlying FEdges CurvePoint *cp = _Vertices.front(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f); SVertex *sv_last = cp->A(); SVertex *sv_curr = (*v); FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB(); FEdge *fe2 = fe->duplicate(); fe2->setVertexA(sv_curr); fe2->setVertexB(sv_last); sv_last->AddFEdge(fe2); sv_curr->AddFEdge(fe2); sv_curr->shape()->AddEdge(fe2); } else { previous = (*v)->point2d(); } do { current = (*v)->point2d(); Curve::push_vertex_front((*v)); //_Length += (current - previous).norm(); previous = current; if (orientation) ++v; else --v; } while ((v != vend) && (v != vfirst)); if (v == vfirst) { //Add last one: current = (*v)->point2d(); Curve::push_vertex_front(*v); //_Length += (current - previous).norm(); } if (!_fedgeB) _fedgeB = (orientation) ? iViewEdge->fedgeB() : iViewEdge->fedgeA(); }
Vec2f Orientation2DF1D::operator()(Interface1D& inter) { FEdge * fe = dynamic_cast<FEdge*>(&inter); if(fe){ Vec3r res = fe->orientation2d(); return Vec2f(res[0], res[1]); } return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); }
void ViewEdge::UpdateFEdges() { FEdge *currentEdge = _FEdgeA; do { currentEdge->setViewEdge(this); currentEdge = currentEdge->nextEdge(); } while ((currentEdge != NULL) && (currentEdge != _FEdgeB)); // last one _FEdgeB->setViewEdge(this); }
int QuantitativeInvisibilityF1D::operator()(Interface1D &inter) { ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); if (ve) { result = ve->qi(); return 0; } FEdge *fe = dynamic_cast<FEdge *>(&inter); if (fe) { result = fe->qi(); return 0; } result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; }
const ViewEdge *ViewMap::getClosestViewEdge(real x, real y) const { // find the closest of this candidates: real minDist = DBL_MAX; FEdge *winner = NULL; for (fedges_container::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend; fe++) { Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]); Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]); real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x, y), A, B); if (dist < minDist) { minDist = dist; winner = (*fe); } } if (!winner) return NULL; return winner->viewedge(); }
void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch) { // Cull view edges by marking them as non-displayable. // This avoids the complications of trying to delete edges from the ViewMap. // Non-displayable view edges will be skipped over during visibility calculation. // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border, // or some such). // Get proscenium boundary for culling real viewProscenium[4]; GridHelpers::getDefaultViewProscenium(viewProscenium); real prosceniumOrigin[2]; prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; if (G.debug & G_DEBUG_FREESTYLE) { cout << "Proscenium culling:" << endl; cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << ", " << viewProscenium[3] << "]"<< endl; cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl; } // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and // expanding as necessary so that it encompasses the center point of at least one feature edge in each // retained view edge. // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid. // The occluder proscenium starts out the same size as the view proscenium GridHelpers::getDefaultViewProscenium(occluderProscenium); // XXX Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator. // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container // throughout the code. // For each view edge ViewMap::viewedges_container::iterator ve, veend; for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { // Overview: // Search for a visible feature edge // If none: mark view edge as non-displayable // Otherwise: // Find a feature edge with center point inside occluder proscenium. // If none exists, find the feature edge with center point closest to viewport origin. // Expand occluder proscenium to enclose center point. // For each feature edge, while bestOccluderTarget not found and view edge not visibile bool bestOccluderTargetFound = false; FEdge *bestOccluderTarget = NULL; real bestOccluderDistance = 0.0; FEdge *festart = (*ve)->fedgeA(); FEdge *fe = festart; // All ViewEdges start culled (*ve)->setIsInImage(false); // For simple visibility calculation: mark a feature edge that is known to have a center point inside // the occluder proscenium. Cull all other feature edges. do { // All FEdges start culled fe->setIsInImage(false); // Look for the visible edge that can most easily be included in the occluder proscenium. if (!bestOccluderTargetFound) { // If center point is inside occluder proscenium, if (insideProscenium(occluderProscenium, fe->center2d())) { // Use this feature edge for visibility deterimination fe->setIsInImage(true); expandGridSpaceOccluderProscenium(fe); // Mark bestOccluderTarget as found bestOccluderTargetFound = true; bestOccluderTarget = fe; } else { real d = distance2D(fe->center2d(), prosceniumOrigin); // If center point is closer to viewport origin than current target if (bestOccluderTarget == NULL || d < bestOccluderDistance) { // Then store as bestOccluderTarget bestOccluderDistance = d; bestOccluderTarget = fe; } } } // If feature edge crosses the view proscenium if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) { // Then the view edge will be included in the image (*ve)->setIsInImage(true); } fe = fe->nextEdge(); } while (fe != NULL && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage())); // Either we have run out of FEdges, or we already have the one edge we need to determine visibility // Cull all remaining edges. while (fe != NULL && fe != festart) { fe->setIsInImage(false); fe = fe->nextEdge(); } // If bestOccluderTarget was not found inside the occluder proscenium, // we need to expand the occluder proscenium to include it. if ((*ve)->isInImage() && bestOccluderTarget != NULL && ! bestOccluderTargetFound) { // Expand occluder proscenium to enclose bestOccluderTarget Vec3r point = bestOccluderTarget->center2d(); if (point[0] < occluderProscenium[0]) { occluderProscenium[0] = point[0]; } else if (point[0] > occluderProscenium[1]) { occluderProscenium[1] = point[0]; } if (point[1] < occluderProscenium[2]) { occluderProscenium[2] = point[1]; } else if (point[1] > occluderProscenium[3]) { occluderProscenium[3] = point[1]; } // Use bestOccluderTarget for visibility determination bestOccluderTarget->setIsInImage(true); } } // We are done calculating the occluder proscenium. // Expand the occluder proscenium by an epsilon to avoid rounding errors. const real epsilon = 1.0e-6; occluderProscenium[0] -= epsilon; occluderProscenium[1] += epsilon; occluderProscenium[2] -= epsilon; occluderProscenium[3] += epsilon; // For "Normal" or "Fast" style visibility computation only: // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges // with center points inside the final occluder proscenium. All of these feature edges can be considered during // visibility calculation. // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation // want to consider many FEdges for each ViewEdge. // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become // usable because the occluder proscenium has been expanded since the edge was visited on the first pass. if (extensiveFEdgeSearch) { // For each view edge, for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { if (!(*ve)->isInImage()) { continue; } // For each feature edge, FEdge *festart = (*ve)->fedgeA(); FEdge *fe = festart; do { // If not (already) visible and center point inside occluder proscenium, if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) { // Use the feature edge for visibility determination fe->setIsInImage(true); expandGridSpaceOccluderProscenium(fe); } fe = fe->nextEdge(); } while (fe != NULL && fe != festart); } } // Up until now, all calculations have been done in camera space. // However, the occluder source's iteration and the grid that consumes the occluders both work in gridspace, // so we need a version of the occluder proscenium in gridspace. // Set the gridspace occlude proscenium }
ViewEdge *ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge) { // Start a new sharp chain edges ViewEdge *newVEdge = new ViewEdge; newVEdge->setId(_currentViewId); ++_currentViewId; unsigned size = 0; _pCurrentVShape->AddEdge(newVEdge); // Find first edge: OWXEdge firstWEdge = iWEdge; /* OWXEdge previousWEdge = firstWEdge; */ /* UNUSED */ OWXEdge currentWEdge = firstWEdge; list<OWXEdge> edgesChain; #if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */ // bidirectional chaining // first direction: while (!stopSharpViewEdge(currentWEdge.e)) { edgesChain.push_back(currentWEdge); ++size; currentWEdge.e->userdata = (void *)1; // processed // Find the next edge! currentWEdge = FindNextWEdge(currentWEdge); } OWXEdge endWEdge = edgesChain.back(); // second direction currentWEdge = FindPreviousWEdge(firstWEdge); while (!stopSharpViewEdge(currentWEdge.e)) { edgesChain.push_front(currentWEdge); ++size; currentWEdge.e->userdata = (void *)1; // processed // Find the previous edge! currentWEdge = FindPreviousWEdge(currentWEdge); } #else edgesChain.push_back(currentWEdge); ++size; currentWEdge.e->userdata = (void *)1; // processed OWXEdge endWEdge = edgesChain.back(); #endif firstWEdge = edgesChain.front(); // build FEdges FEdge *feprevious = NULL; FEdge *fefirst = NULL; FEdge *fe = NULL; for (list<OWXEdge>::iterator we = edgesChain.begin(), weend = edgesChain.end(); we != weend; ++we) { fe = BuildSharpFEdge(feprevious, (*we)); fe->setViewEdge(newVEdge); if (!fefirst) fefirst = fe; feprevious = fe; } // Store the chain starting edge: _pCurrentSShape->AddChain(fefirst); newVEdge->setNature(iWEdge.e->nature()); newVEdge->setFEdgeA(fefirst); newVEdge->setFEdgeB(fe); // is it a closed loop ? if ((firstWEdge == endWEdge) && (size != 1)) { fefirst->setPreviousEdge(fe); fe->setNextEdge(fefirst); newVEdge->setA(0); newVEdge->setB(0); } else { ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); ViewVertex *vvb = MakeViewVertex(fe->vertexB()); ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge); ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge); newVEdge->setA(vva); newVEdge->setB(vvb); } return newVEdge; }
ViewEdge *ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer) { // Find first edge: OWXFaceLayer first = iFaceLayer; OWXFaceLayer currentFace = first; // bidirectional chaining. // first direction list<OWXFaceLayer> facesChain; unsigned size = 0; while (!stopSmoothViewEdge(currentFace.fl)) { facesChain.push_back(currentFace); ++size; currentFace.fl->userdata = (void *)1; // processed // Find the next edge! currentFace = FindNextFaceLayer(currentFace); } OWXFaceLayer end = facesChain.back(); // second direction currentFace = FindPreviousFaceLayer(first); while (!stopSmoothViewEdge(currentFace.fl)) { facesChain.push_front(currentFace); ++size; currentFace.fl->userdata = (void *)1; // processed // Find the previous edge! currentFace = FindPreviousFaceLayer(currentFace); } first = facesChain.front(); if (iFaceLayer.fl->nature() & Nature::RIDGE) { if (size < 4) { return 0; } } // Start a new chain edges ViewEdge *newVEdge = new ViewEdge; newVEdge->setId(_currentViewId); ++_currentViewId; _pCurrentVShape->AddEdge(newVEdge); // build FEdges FEdge *feprevious = NULL; FEdge *fefirst = NULL; FEdge *fe = NULL; for (list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend = facesChain.end(); fl != flend; ++fl) { fe = BuildSmoothFEdge(feprevious, (*fl)); if (feprevious && fe == feprevious) continue; fe->setViewEdge(newVEdge); if (!fefirst) fefirst = fe; feprevious = fe; } // Store the chain starting edge: _pCurrentSShape->AddChain(fefirst); newVEdge->setNature(iFaceLayer.fl->nature()); newVEdge->setFEdgeA(fefirst); newVEdge->setFEdgeB(fe); // is it a closed loop ? if ((first == end) && (size != 1)) { fefirst->setPreviousEdge(fe); fe->setNextEdge(fefirst); newVEdge->setA(0); newVEdge->setB(0); } else { ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); ViewVertex *vvb = MakeViewVertex(fe->vertexB()); ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge); ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge); newVEdge->setA(vva); newVEdge->setB(vvb); } return newVEdge; }
/* splits an edge into 2 edges. The new vertex and edge are added * to the sshape list of vertices and edges * a new chain is also created. * returns the new edge. * ioEdge * The edge that gets splitted * newpoint * x,y,z coordinates of the new point. */ FEdge* SShape::SplitEdgeIn2(FEdge* ioEdge, SVertex * ioNewVertex) { SVertex *A = ioEdge->vertexA(); SVertex *B = ioEdge->vertexB(); // We split edge AB into AA' and A'B. A' and A'B are created. // AB becomes (address speaking) AA'. B is updated. //-------------------------------------------------- // a new edge, A'B is created. FEdge *newEdge; if (ioEdge->getNature() & Nature::ALL_INTERSECTION) { newEdge = new FEdgeIntersection(ioNewVertex, B); FEdgeIntersection * se = dynamic_cast<FEdgeIntersection*>(newEdge); FEdgeIntersection * fes = dynamic_cast<FEdgeIntersection*>(ioEdge); se->SetMaterialIndex(fes->materialIndex()); se->SetFaces(fes->getFace1(), fes->getFace2()); #ifdef DEBUG_INTERSECTION void debugFES(FEdgeIntersection * newEdge); debugFES(se); debugFES(fes); #endif }else if(ioEdge->isSmooth()){ newEdge = new FEdgeSmooth(ioNewVertex, B); FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge); FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(ioEdge); se->SetMaterialIndex(fes->materialIndex()); se->SetFace(fes->face()); }else{ newEdge = new FEdgeSharp(ioNewVertex, B); FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge); FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(ioEdge); se->SetaMaterialIndex(fes->aMaterialIndex()); se->SetbMaterialIndex(fes->bMaterialIndex()); se->SetEdge(fes->edge()); } newEdge->SetNature(ioEdge->getNature()); if(ioEdge->nextEdge() != 0) ioEdge->nextEdge()->SetPreviousEdge(newEdge); // update edge A'B for the next pointing edge newEdge->SetNextEdge(ioEdge->nextEdge()); // update edge A'B for the previous pointing edge newEdge->SetPreviousEdge(0); // because it is now a ViewVertex Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1); newEdge->SetId(ioEdge->getId()); ioEdge->SetId(id); // update edge AA' for the next pointing edge ioEdge->SetNextEdge(0); // because it is now a TVertex // update vertex pointing edges list: // -- vertex B -- B->Replace(ioEdge, newEdge); // -- vertex A' -- ioNewVertex->AddFEdge(ioEdge); ioNewVertex->AddFEdge(newEdge); // to build a new chain: AddChain(newEdge); AddEdge(newEdge); // FIXME ?? // The edge AB becomes edge AA'. ioEdge->SetVertexB(ioNewVertex); // added by Aaron (looks redundant now, can probably be deleted) newEdge->SetVertexA(ioNewVertex); newEdge->SetVertexB(B); // if(ioEdge->isSmooth()){ // ((FEdgeSmooth*)newEdge)->SetFace(((FEdgeSmooth*)ioEdge)->face()); //} return newEdge; }
/* splits an edge into several edges. * The edge's vertices are passed rather than * the edge itself. This way, all feature edges (SILHOUETTE, * CREASE, BORDER) are splitted in the same time. * The processed edges are flagged as done (using the userdata * flag).One single new vertex is created whereas * several splitted edges might created for the different * kinds of edges. These new elements are added to the lists * maintained by the shape. * new chains are also created. * ioA * The first vertex for the edge that gets splitted * ioB * The second vertex for the edge that gets splitted * iParameters * A vector containing 2D real vectors indicating the parameters * giving the intersections coordinates in 3D and in 2D. * These intersections points must be sorted from B to A. * Each parameter defines the intersection point I as I=A+T*AB. * T<0 and T>1 are then incorrect insofar as they give intersections * points that lie outside the segment. * ioNewEdges * The edges that are newly created (the initial edges are not * included) are added to this list. */ void SShape::SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges) { SVertex *ioA = fe->vertexA(); SVertex *ioB = fe->vertexB(); Vec3r A = ioA->point3D(); Vec3r B = ioB->point3D(); Vec3r a = ioA->point2D(); Vec3r b = ioB->point2D(); SVertex *svA, *svB; Vec3r newpoint3d,newpoint2d; vector<SVertex*> intersections; real t,T; for(vector<Vec2r>::const_iterator p=iParameters.begin(),pend=iParameters.end(); p!=pend; p++) { T=(*p)[0]; t=(*p)[1]; if((t < 0) || (t > 1)) cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl; // compute the 3D and 2D coordinates for the intersections points: newpoint3d = Vec3r(A + T*(B-A)); newpoint2d = Vec3r(a + t*(b-a)); // create new SVertex: // (we keep B's id) SVertex* newVertex = new SVertex(newpoint3d, ioB->getId()); newVertex->SetPoint2D(newpoint2d); // Add this vertex to the intersections list: intersections.push_back(newVertex); // Add this vertex to this sshape: AddNewVertex(newVertex); } for(vector<SVertex*>::iterator sv=intersections.begin(),svend=intersections.end(); sv!=svend; sv++) { svA = fe->vertexA(); svB = fe->vertexB(); // We split edge AB into AA' and A'B. A' and A'B are created. // AB becomes (address speaking) AA'. B is updated. //-------------------------------------------------- // The edge AB becomes edge AA'. (fe)->SetVertexB((*sv)); // a new edge, A'B is created. FEdge *newEdge; if (fe->getNature() & Nature::ALL_INTERSECTION) { newEdge = new FEdgeIntersection((*sv), svB); FEdgeIntersection * se = dynamic_cast<FEdgeIntersection*>(newEdge); FEdgeIntersection * fes = dynamic_cast<FEdgeIntersection*>(fe); se->SetMaterialIndex(fes->materialIndex()); se->SetFaces(fes->getFace1(), fes->getFace2()); #ifdef DEBUG_INTERSECTION void debugFES(FEdgeIntersection * newEdge); debugFES(se); debugFES(fes); #endif } else if(fe->isSmooth()){ newEdge = new FEdgeSmooth((*sv), svB); FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge); FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe); se->SetMaterialIndex(fes->materialIndex()); }else{ newEdge = new FEdgeSharp((*sv), svB); FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge); FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(fe); se->SetaMaterialIndex(fes->aMaterialIndex()); se->SetbMaterialIndex(fes->bMaterialIndex()); se->SetEdge(fes->edge()); } newEdge->SetNature((fe)->getNature()); // to build a new chain: AddChain(newEdge); // add the new edge to the sshape edges list. AddEdge(newEdge); // add new edge to the list of new edges passed as argument: ioNewEdges.push_back(newEdge); // update edge A'B for the next pointing edge newEdge->SetNextEdge((fe)->nextEdge()); fe->nextEdge()->SetPreviousEdge(newEdge); Id id(fe->getId().getFirst(), fe->getId().getSecond()+1); newEdge->SetId(fe->getId()); fe->SetId(id); // update edge AA' for the next pointing edge //ioEdge->SetNextEdge(newEdge); (fe)->SetNextEdge(NULL); // update vertex pointing edges list: // -- vertex B -- svB->Replace((fe), newEdge); // -- vertex A' -- (*sv)->AddFEdge((fe)); (*sv)->AddFEdge(newEdge); } }
bool FEdge::intersectParametric(FEdge & fe2, Vec3r viewpoint, real t3D, real u3D) { Vec3r A1 = vertexA()->getPoint3D(); Vec3r B1 = vertexB()->getPoint3D(); Vec3r A2 = fe2.vertexA()->getPoint3D(); Vec3r B2 = fe2.vertexB()->getPoint3D(); if (sameSide(A1,B1,viewpoint, A2, B2) || sameSide(A2, B2, viewpoint, A1, B1)) return false; // now, there *must* be an intersection. // for each edge, the normal of the plane containing the edge and the viewpoint Vec3r N1 = (A1-viewpoint) ^ (B1-viewpoint); Vec3r N2 = (A2-viewpoint) ^ (B2-viewpoint); // direction vector of the intersection of the two planes. Vec3r V = N1 ^ N2; // check if the planes coincide (i.e., source edges are colinear) assert(V.norm() > 0); // ----- compute t parameter ------ // form a plane for line 1, normal to the plane containing the viewpoint Vec3r BA1 = B1 - A1; Vec3r hsNormal1 = N1 ^ BA1; // intersect ray in direction of V through the plane real w1; GeomUtils::intersection_test res1 = GeomUtils::intersectLinePlanePN(viewpoint, V, hsNormal1, A1, w1); if (res1 != GeomUtils::DO_INTERSECT) { printf("res1 = %d\n", res1); printf("viewpoint = [%f %f %f]\n", viewpoint[0], viewpoint[1], viewpoint[2]); printf("A1 = [%f %f %f]\n", A1[0], A1[1], A1[2]); printf("B1 = [%f %f %f]\n", B1[0], B1[1], B1[2]); printf("A2 = [%f %f %f]\n", A2[0], A2[1], A2[2]); printf("B2 = [%f %f %f]\n", B2[0], B2[1], B2[2]); printf("N1 = [%f %f %f]\n", N1[0], N1[1], N1[2]); printf("N2 = [%f %f %f]\n", N2[0], N2[1], N2[2]); printf("V = [%f %f %f]\n", V[0], V[1], V[2]); printf("hsNormal1 = [%f %f %f]\n", hsNormal1[0], hsNormal1[1], hsNormal1[2]); } assert(res1 == GeomUtils::DO_INTERSECT); Vec3r pt1 = viewpoint + w1 * V; t3D = ((pt1 - A1) * BA1) / (BA1*BA1); assert(t3D >=0 && t3D <= 1); // if (t3D < 0 || t3D > 1) // return false; // ----- compute u parameter ------ // form a half-space plane for line 2 Vec3r BA2 = B2 - A2; Vec3r hsNormal2 = N2 ^ BA2; real w2; GeomUtils::intersection_test res2 = GeomUtils::intersectLinePlanePN(viewpoint, V, hsNormal2, A2, w2); if (res2 != GeomUtils::DO_INTERSECT) { printf("res1 = %d\n", res1); printf("viewpoint = [%f %f %f]\n", viewpoint[0], viewpoint[1], viewpoint[2]); printf("A1 = [%f %f %f]\n", A1[0], A1[1], A1[2]); printf("B1 = [%f %f %f]\n", B1[0], B1[1], B1[2]); printf("A2 = [%f %f %f]\n", A2[0], A2[1], A2[2]); printf("B2 = [%f %f %f]\n", B2[0], B2[1], B2[2]); printf("N1 = [%f %f %f]\n", N1[0], N1[1], N1[2]); printf("N2 = [%f %f %f]\n", N2[0], N2[1], N2[2]); printf("V = [%f %f %f]\n", V[0], V[1], V[2]); printf("hsNormal2 = [%f %f %f]\n", hsNormal2[0], hsNormal2[1], hsNormal2[2]); } assert(res2 == GeomUtils::DO_INTERSECT); Vec3r pt2 = viewpoint + w2 * V; u3D = ((pt2 - A2) * BA2) / (BA2*BA2); assert( u3D >=0 && u3D <=1); // if (u3D < 0 || u3D > 1) // return false; return true; }