bool IntrLine3Box3<Real>::DoClipping ( Real t0, Real t1, const Vector3<Real>& origin, const Vector3<Real>& direction, const Box3<Real>& box, bool solid, int& quantity, Vector3<Real> point[2], int& intrType ) { // Convert linear component to box coordinates. Vector3<Real> diff = origin - box.Center; Vector3<Real> BOrigin( diff.Dot( box.Axis[0] ), diff.Dot( box.Axis[1] ), diff.Dot( box.Axis[2] ) ); Vector3<Real> BDirection( direction.Dot( box.Axis[0] ), direction.Dot( box.Axis[1] ), direction.Dot( box.Axis[2] ) ); Real saveT0 = t0, saveT1 = t1; bool notAllClipped = Clip( +BDirection.X(), -BOrigin.X() - box.Extent[0], t0, t1 ) && Clip( -BDirection.X(), +BOrigin.X() - box.Extent[0], t0, t1 ) && Clip( +BDirection.Y(), -BOrigin.Y() - box.Extent[1], t0, t1 ) && Clip( -BDirection.Y(), +BOrigin.Y() - box.Extent[1], t0, t1 ) && Clip( +BDirection.Z(), -BOrigin.Z() - box.Extent[2], t0, t1 ) && Clip( -BDirection.Z(), +BOrigin.Z() - box.Extent[2], t0, t1 ); if ( notAllClipped && ( solid || t0 != saveT0 || t1 != saveT1 ) ) { if ( t1 > t0 ) { intrType = IT_SEGMENT; quantity = 2; point[0] = origin + t0 * direction; point[1] = origin + t1 * direction; } else { intrType = IT_POINT; quantity = 1; point[0] = origin + t0 * direction; } } else { quantity = 0; intrType = IT_EMPTY; } return intrType != IT_EMPTY; }
Bool HawkLine3D::Intersect(const HawkOBB& oBox,Vec3IntrResult* pResult) const { const HawkVector3D* Axis = oBox.GetAxis(); HawkVector3D diff = Point - oBox.Center; HawkVector3D BOrigin( diff.DotProduct(Axis[0]), diff.DotProduct(Axis[1]), diff.DotProduct(Axis[2]) ); HawkVector3D BDirection( Direction.DotProduct(Axis[0]), Direction.DotProduct(Axis[1]), Direction.DotProduct(Axis[2]) ); Float t0 = -FLT_MAX,t1 = FLT_MAX; bool notAllClipped = geoClip(+BDirection.X, -BOrigin.X-oBox.Extent[0], t0, t1) && geoClip(-BDirection.X, +BOrigin.X-oBox.Extent[0], t0, t1) && geoClip(+BDirection.Y, -BOrigin.Y-oBox.Extent[1], t0, t1) && geoClip(-BDirection.Y, +BOrigin.Y-oBox.Extent[1], t0, t1) && geoClip(+BDirection.Z, -BOrigin.Z-oBox.Extent[2], t0, t1) && geoClip(-BDirection.Z, +BOrigin.Z-oBox.Extent[2], t0, t1); if (notAllClipped) { //2交点 if (t1 > t0) { if (pResult) { pResult->Factor = HawkMath::Abs<Float>(t0) < HawkMath::Abs<Float>(t1)? t0 : t1; pResult->Point = Point + Direction * pResult->Factor; } return true; } //1交点 else { if (pResult) { pResult->Factor = t0; pResult->Point = Point + Direction * pResult->Factor; } return true; } } return false; }
/** * @brief intersect a geometric object. * @param ray_ the ray * @param p_diff_geom_ the result of the intersection * @return true if the ray intersects the geometry. Modifies the ray_.max_t() value, intersect only if the intersection * is before ray_.max_t() * @todo Factorize code shared by Box3D::clip() * * Adapted from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrLine3Box3.cpp */ bool intersect (Ray& ray_, Diff_Geom * p_diff_geom_) const { float t0 = -ray_.ray_epsilon(); float t1 = ray_.max_t(); // 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 ( (t0 > ray_.ray_epsilon() ) && (t0 < ray_.max_t()) ){ Vector3D normal = m_axis[nt0/2]; if (nt0%2) normal = -normal; p_diff_geom_->set_pos(ray_.at(t0)); p_diff_geom_->set_normal(normal); p_diff_geom_->set_t(t0); ray_.set_max_t(t0); return true; } else if ( (t1 > ray_.ray_epsilon()) && (t1 < ray_.max_t()) ){ Vector3D normal = m_axis[nt1/2]; if (nt1%2) normal = -normal; p_diff_geom_->set_pos(ray_.at(t1)); p_diff_geom_->set_normal(normal); p_diff_geom_->set_t(t1); ray_.set_max_t(t1); return true; } else return false; } 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; } }