/** * @brief clip a ray by a Cone. * @param ray_ the ray to clip * @param bounds ray sorted bounds of the resulting clipping segment. * @return true if ray was clipped. bounds parameter is filld by this method * * For simple convex objects, there is two values in bounds that represent in and out events. * An in event is whe the ray enters the geometry, an out is when the ray leaves the geometry. * * Adapted from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrLine3Cone3.cpp * */ bool clip(Ray& ray_, IntervalSet &bounds) const { Diff_Geom ipoints[2]; float t[2]; int numintersection = get_clip_points(ray_, ipoints, t); if (numintersection == 0) return false; else if (numintersection == 2) { Diff_Geom *in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), t[0]); Diff_Geom *out = new Diff_Geom(ipoints[1].pos(), ipoints[1].normal(), t[1]); bounds.add(in, out); return true; } else { Diff_Geom *in, *out; IntervalSet capset; // check with cap plane Plane cap(m_vertex + m_axis * m_height, m_axis); if (cap.clip(ray_, capset) ) { /* Beuark mais ca facilite la gestion mémoire ... */ Diff_Geom *tmp =capset.bounds()[0].data; in = new Diff_Geom(*tmp); if (in->t()< t[0]) { out = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), t[0]); } else { out = in; in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), t[0]); } bounds.add(in, out); return true; } else { return false; } } }
IntervalSet IntervalSet::And(const IntervalSet &other) const { IntervalSet intersection; size_t i = 0; size_t j = 0; // iterate down both interval lists looking for nondisjoint intervals while (i < _intervals.size() && j < other._intervals.size()) { Interval mine = _intervals[i]; Interval theirs = other._intervals[j]; if (mine.startsBeforeDisjoint(theirs)) { // move this iterator looking for interval that might overlap i++; } else if (theirs.startsBeforeDisjoint(mine)) { // move other iterator looking for interval that might overlap j++; } else if (mine.properlyContains(theirs)) { // overlap, add intersection, get next theirs intersection.add(mine.intersection(theirs)); j++; } else if (theirs.properlyContains(mine)) { // overlap, add intersection, get next mine intersection.add(mine.intersection(theirs)); i++; } else if (!mine.disjoint(theirs)) { // overlap, add intersection intersection.add(mine.intersection(theirs)); // Move the iterator of lower range [a..b], but not // the upper range as it may contain elements that will collide // with the next iterator. So, if mine=[0..115] and // theirs=[115..200], then intersection is 115 and move mine // but not theirs as theirs may collide with the next range // in thisIter. // move both iterators to next ranges if (mine.startsAfterNonDisjoint(theirs)) { j++; } else if (theirs.startsAfterNonDisjoint(mine)) { i++; } } } return intersection; }
bool clip(Ray& ray_, IntervalSet &bounds) const { Diff_Geom ipoints[2]; float t[2]; int numintersection = get_clip_points(ray_, ipoints, t); if (numintersection == 0) return false; else if (numintersection == 2) { Diff_Geom *in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), ipoints[0].dNdx(), ipoints[0].dNdy(), t[0], ipoints[0].dPdx(), ipoints[0].dPdy(), ipoints[0].dDdx(), ipoints[0].dDdy(), ipoints[0].u(), ipoints[0].v(), ipoints[0].dTdx(), ipoints[0].dTdy(), true); Diff_Geom *out = new Diff_Geom(ipoints[1].pos(), ipoints[1].normal(), ipoints[1].dNdx(), ipoints[1].dNdy(), t[1], ipoints[1].dPdx(), ipoints[1].dPdy(), ipoints[1].dDdx(), ipoints[1].dDdy(), ipoints[1].u(), ipoints[1].v(), ipoints[1].dTdx(), ipoints[1].dTdy(), false); bounds.add(in, out); return true; } else { Diff_Geom *in, *out; IntervalSet capset; // check with cap plane Plane cap(m_vertex + m_axis * m_height, m_axis); if (cap.clip(ray_, capset) ) { in = capset.bounds()[0].data; in->set_u(in->u()/(PSCALE*m_radius)); in->set_v(in->v()/(PSCALE*m_radius)); in->set_dTdx(in->dTdx()* (1.f/(PSCALE*m_radius))); in->set_dTdy(in->dTdy()* (1.f/(PSCALE*m_radius))); if (in->t()< t[0]) { //if (p_diff_geom_in_->t() < t[0]) { out = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), ipoints[0].dNdx(), ipoints[0].dNdy(), t[0], ipoints[0].dPdx(), ipoints[0].dPdy(), ipoints[0].dDdx(), ipoints[0].dDdy(), ipoints[0].u(), ipoints[0].v(), ipoints[0].dTdx(), ipoints[0].dTdy(), false); } else { out = in; out->set_in(false); in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), ipoints[0].dNdx(), ipoints[0].dNdy(), t[0], ipoints[0].dPdx(), ipoints[0].dPdy(), ipoints[0].dDdx(), ipoints[0].dDdy(), ipoints[0].u(), ipoints[0].v(), ipoints[0].dTdx(), ipoints[0].dTdy(), true); } delete (capset.bounds()[1].data); bounds.add(in, out); return true; } else { return false; } } }
/** * @brief clip a ray by a Box3D. * @param ray_ the ray to clip * @param bounds ray sorted bounds of the resulting clipping segment. * @return true if ray was clipped. bounds parameter is filld by this method * * For simple convex objects, there is two values in bounds that represent in and out events. * An in event is whe the ray enters the geometry, an out is when the ray leaves the geometry. * * @todo Factorize code shared by Box3D::intersect() * * Adapted from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrLine3Box3.cpp * */ bool clip(Ray& ray_, IntervalSet &bounds) const { float t0 = std::numeric_limits<float>::min(); float t1 = std::numeric_limits<float>::max(); // Convert linear component to box coordinates. Vector3D diff = ray_.ori() - m_center; Vector3D BOrigin( diff.dot(m_axis[0]), diff.dot(m_axis[1]), diff.dot(m_axis[2]) ); Vector3D BDirection( ray_.dir().dot(m_axis[0]), ray_.dir().dot(m_axis[1]), ray_.dir().dot(m_axis[2]) ); float saveT0 = t0, saveT1 = t1; bool notAllClipped; unsigned char updated; int nt0, nt1; notAllClipped = clip(+BDirection.x(), -BOrigin.x()-m_extent[0], t0, t1, updated); if (updated == 1) nt0 = 0; else if (updated == 2) nt1 = 0; notAllClipped = notAllClipped && clip(-BDirection.x(), +BOrigin.x()-m_extent[0], t0, t1, updated); if (updated == 1) nt0 = 1; else if (updated == 2) nt1 = 1; notAllClipped = notAllClipped && clip(+BDirection.y(), -BOrigin.y()-m_extent[1], t0, t1, updated); if (updated == 1) nt0 = 2; else if (updated == 2) nt1 = 2; notAllClipped = notAllClipped && clip(-BDirection.y(), +BOrigin.y()-m_extent[1], t0, t1, updated); if (updated == 1) nt0 = 3; else if (updated == 2) nt1 = 3; notAllClipped = notAllClipped && clip(+BDirection.z(), -BOrigin.z()-m_extent[2], t0, t1, updated); if (updated == 1) nt0 = 4; else if (updated == 2) nt1 = 4; notAllClipped = notAllClipped && clip(-BDirection.z(), +BOrigin.z()-m_extent[2], t0, t1, updated); if (updated == 1) nt0 = 5; else if (updated == 2) nt1 = 5; if (notAllClipped && (t0 != saveT0 || t1 != saveT1)) { if (t1 > t0) { Vector3D normal = m_axis[nt0/2]; if (nt0%2) normal = -normal; Diff_Geom *in = new Diff_Geom(ray_.at(t0), normal, t0); normal = m_axis[nt1/2]; if (nt1%2) normal = -normal; Diff_Geom *out = new Diff_Geom(ray_.at(t1), normal, t1); bounds.add(in, out); return true; } else { return false; } } else { return false; } }