BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32 *face_hitp, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { if (!lineSegmentBoundingBox(start, end)) { return FALSE; } LLVector4a da; da.setSub(end, start); LLVector3 delta(da.getF32ptr()); LLVector3 pdelta = delta; pdelta.mV[2] = 0; F32 plength = pdelta.length(); F32 tdelta = 1.f/plength; LLVector3 v_start(start.getF32ptr()); LLVector3 origin = v_start - mRegionp->getOriginAgent(); if (mRegionp->getLandHeightRegion(origin) > origin.mV[2]) { //origin is under ground, treat as no intersection return FALSE; } //step one meter at a time until intersection point found //VECTORIZE THIS const LLVector4a* exta = mDrawable->getSpatialExtents(); LLVector3 ext[2]; ext[0].set(exta[0].getF32ptr()); ext[1].set(exta[1].getF32ptr()); F32 rad = (delta*tdelta).magVecSquared(); F32 t = 0.f; while ( t <= 1.f) { LLVector3 sample = origin + delta*t; if (AABBSphereIntersectR2(ext[0], ext[1], sample+mRegionp->getOriginAgent(), rad)) { F32 height = mRegionp->getLandHeightRegion(sample); if (height > sample.mV[2]) { //ray went below ground, positive intersection //quick and dirty binary search to get impact point tdelta = -tdelta*0.5f; F32 err_dist = 0.001f; F32 dist = fabsf(sample.mV[2] - height); while (dist > err_dist && tdelta*tdelta > 0.0f) { t += tdelta; sample = origin+delta*t; height = mRegionp->getLandHeightRegion(sample); if ((tdelta < 0 && height < sample.mV[2]) || (height > sample.mV[2] && tdelta > 0)) { //jumped over intersection point, go back tdelta = -tdelta; } tdelta *= 0.5f; dist = fabsf(sample.mV[2] - height); } if (intersection) { F32 height = mRegionp->getLandHeightRegion(sample); if (fabsf(sample.mV[2]-height) < delta.length()*tdelta) { sample.mV[2] = mRegionp->getLandHeightRegion(sample); } intersection->load3((sample + mRegionp->getOriginAgent()).mV); } if (normal) { normal->load3((mRegionp->getLand().resolveNormalGlobal(mRegionp->getPosGlobalFromRegion(sample))).mV); } return TRUE; } } t += tdelta; if (t > 1 && t < 1.f+tdelta*0.99f) { //make sure end point is checked (saves vertical lines coming up negative) t = 1.f; } } return FALSE; }
bool set_conditions(const std::vector<rib_data_type> &rbs, const std::vector<index_type> &maxd, bool cl=false) { index_type i, j, nsegs(static_cast<index_type>(maxd.size())), nribs(rbs.size()); // ensure input vectors are correct size if (!cl && (nribs!=(nsegs+1))) return false; if (cl && (nribs!=nsegs)) return false; // check to make sure have valid end conditions if (!cl) { if (rbs[0].use_left_fp() || rbs[0].use_left_fpp() || rbs[0].get_continuity()!=rib_data_type::C0) { return false; } if (rbs[nsegs].use_right_fp() || rbs[nsegs].use_right_fpp() || rbs[nsegs].get_continuity()!=rib_data_type::C0) { return false; } } // make sure ribs are in valid state data_type v_start(rbs[0].get_t0()), v_end(rbs[0].get_tmax()); tolerance_type tol; for (i=0; i<nribs; ++i) { if (!rbs[i].check_state()) return false; if (!tol.approximately_equal(rbs[i].get_t0(), v_start) || !tol.approximately_equal(rbs[i].get_tmax(), v_end)) return false; } // find all unique v-coordinates on joints for each rib auto comp = [&tol](const data_type &x1, const data_type &x2)->bool { return tol.approximately_less_than(x1, x2); }; std::vector<data_type> joints; data_type t0(rbs[0].get_t0()), tmax(rbs[0].get_tmax()); rbs[0].get_joints(std::back_inserter(joints)); for (i=1; i<nribs; ++i) { // test to make sure this rib's parameterization matches rest if (!tol.approximately_equal(rbs[i].get_t0(), t0) || !tol.approximately_equal(rbs[i].get_tmax(), tmax)) { return false; } // get the joints on the current rib std::vector<data_type> rjoints, jts_out; rbs[i].get_joints(std::back_inserter(rjoints)); // merge these joints with current list of joints std::set_union(joints.begin(), joints.end(), rjoints.begin(), rjoints.end(), std::back_inserter(jts_out), comp); std::swap(joints, jts_out); } // record where the joints need to be for create() index_type njoints(static_cast<index_type>(joints.size())); // set the v-parameterization this->set_number_v_segments(njoints-1); this->set_initial_v(joints[0]); for (j=0; j<(njoints-1); ++j) { this->set_dv(joints[j+1]-joints[j], j); } // reset the number of u-segments this->set_number_u_segments(nsegs); ribs=rbs; max_degree=maxd; closed=cl; return true; }