//does not check inside sphere float Unit::querySphereNoRecurse( const QVector &start, const QVector &end, float min_radius ) const { int i; double tmp; for (i = 0; i < nummesh(); i++) { if ( ( meshdata[i]->Position().Magnitude() > this->rSize() ) || ( meshdata[i]->rSize() > 30+this->rSize() ) ) continue; if (isUnit() == PLANETPTR && i > 0) break; double a, b, c; QVector st = start-Transform( cumulative_transformation_matrix, meshdata[i]->Position().Cast() ); QVector dir = end-start; //now start and end are based on mesh's position c = st.Dot( st ); double temp1 = ( min_radius+meshdata[i]->rSize() ); //if (st.MagnitudeSquared()<temp1*temp1) //UNCOMMENT if you want inside sphere to count...otherwise... //return 1.0e-6; if (min_radius != -FLT_MAX) c = c-temp1*temp1; else c = temp1; #ifdef VARIABLE_LENGTH_PQR c *= SizeScaleFactor*SizeScaleFactor; #endif b = 2.0f*( dir.Dot( st ) ); a = dir.Dot( dir ); //b^2-4ac if (min_radius != -FLT_MAX) c = b*b-4.0f*a*c; else c = FLT_MAX; if (c < 0 || a == 0) continue; a *= 2.0f; tmp = ( -b+sqrt( c ) )/a; c = ( -b-sqrt( c ) )/a; if (tmp > 0 && tmp <= 1) return (c > 0 && c < tmp) ? c : tmp; else if (c > 0 && c <= 1) return c; } return 0.0f; }
float globQueryShell( QVector st, QVector dir, float radius ) { float temp1 = radius; float a, b, c; c = st.Dot( st ); c = c-temp1*temp1; b = 2.0f*( dir.Dot( st ) ); a = dir.Dot( dir ); //b^2-4ac c = b*b-4.0f*a*c; if (c < 0 || a == 0) return 0.0f; a *= 2.0f; float tmp = ( -b+sqrt( c ) )/a; c = ( -b-sqrt( c ) )/a; if (tmp > 0 && tmp <= 1) return (c > 0 && c < tmp) ? c : tmp; else if (c > 0 && c <= 1) return c; return 0.0f; }
/** queries the bounding box, excluding a select edge * 0 = lx, 1=mx, 2=ly 3=my 4=lz 5=mz */ bool BoundingBox::OpenWithin (const QVector &query, float err, int excludeWhich) { err = -err; QVector tquery (query -lx); // now it's in coords with respect to the minimum x; QVector tmp (mx-lx); if (excludeWhich!=0){ if (tquery.Dot (tmp) <err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn mx-lx%f Exc %d\n",tquery.Dot(tmp),excludeWhich); return false; } } if (excludeWhich!=0) { tquery = query - mx; tmp = lx - mx; if (tquery.Dot(tmp)<err){ //VSFileSystem::Fprintf (stderr,"tqueryreturn lx-mx, %fExc %d\n",tquery.Dot(tmp),excludeWhich); return false; } } if (excludeWhich!=1) { tquery = query - ly; tmp = my - ly; if (tquery.Dot (tmp)<err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn my-ly%f Exc %d\n",tquery.Dot(tmp),excludeWhich); return false; } } if (excludeWhich!=1) { tquery = query - my; tmp = ly - my; if (tquery.Dot (tmp) <err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn ly-my%f Exc %d\n",tquery.Dot(tmp),excludeWhich); return false; } } if (excludeWhich!=2) { tquery = query - lz; tmp = mz - lz; if (tquery.Dot (tmp)<err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn mz-lz%f Exc%d\n",tquery.Dot(tmp),excludeWhich); return false; } } if (excludeWhich!=2) { tquery = query - mz; tmp = lz - mz; if (tquery.Dot (tmp) <err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn lz-mz%f Ignore%d\n",tquery.Dot(tmp),excludeWhich); return false; } } return true; //within bounding box; }
/** Queries the bounding box whether the query vector is within it*/ bool BoundingBox::Within (const QVector &query, float err) { err = -err; QVector tquery =query -lx; // now it's in coords with respect to the minimum x; QVector tmp = mx-lx; if (tquery.Dot (tmp) <err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn mx-lx%f",tquery.Dot(tmp)); return false; } tquery = query - mx; tmp = lx - mx; if (tquery.Dot(tmp)<err){ //VSFileSystem::Fprintf (stderr,"tqueryreturn lx-mx, %f",tquery.Dot(tmp)); return false; } tquery = query - ly; tmp = my - ly; if (tquery.Dot (tmp)<err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn my-ly%f",tquery.Dot(tmp)); return false; } tquery = query - my; tmp = ly - my; if (tquery.Dot (tmp) <err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn ly-my%f",tquery.Dot(tmp)); return false; } tquery = query - lz; tmp = mz - lz; if (tquery.Dot (tmp)<err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn mz-lz%f",tquery.Dot(tmp)); return false; } tquery = query - mz; tmp = lz - mz; if (tquery.Dot (tmp) <err) { //VSFileSystem::Fprintf (stderr,"tqueryreturn lz-mz%f",tquery.Dot(tmp)); return false; } return true; //within bounding box; }
/* Determines whether the ray intersects the box...returns -1 if the -ray does, 1 if * the ray itself does. 0 if the ray misses the box * To Compute the intersection of a ray from eye to pnt and a bounding box * solve for 'r' * (r* pnt.i+eye.i-PlaneAffine.i) *PlaneNorm.i + * (r* pnt.j+eye.j-PlaneAffine.j) *PlaneNorm.j + * (r* pnt.k+eye.k-PlaneAffine.k) *PlaneNorm.k ==0 * * r (pnt.i*PlaneNorm.i+pnt.j*PlaneNorm.j+pnt.k*PlaneNorm.k) == * (PlaneAffine.i-eye.i)*PlaneNorm.i +(PlaneAffine.j-eye.j)*PlaneNorm.j+(PlaneAffine.k-eye.k)*PlaneNorm.k * r = pnt.Dot (PlaneNorm)/PlaneNorm.Dot(PlaneAffine-eye) * xyz = r * pnt + eye; */ int BoundingBox::Intersect (const QVector &eye, const QVector &pnt,float err) { QVector IntersectXYZ (eye.i,eye.j,eye.k); QVector Normal (mx - lx); double divisor=pnt.Dot (Normal); if (divisor!=0) { IntersectXYZ+= (Normal.Dot(lx-eye)/divisor)*pnt;//point of intersection with lx plane //VSFileSystem::Fprintf (stderr,"Intersect::%f,%f,%f>\n",IntersectXYZ.i,IntersectXYZ.j,IntersectXYZ.k); if (OpenWithin (IntersectXYZ,err,0)) return Normal.Dot(lx-eye)*divisor>=0?1:-1; } Normal = -Normal; divisor=pnt.Dot(Normal); if (divisor!=0) { IntersectXYZ = eye+( Normal.Dot(mx-eye)/divisor)*pnt; //point of interscetion with mx plane //VSFileSystem::Fprintf (stderr,"Intersect::%f,%f,%f>\n",IntersectXYZ.i,IntersectXYZ.j,IntersectXYZ.k); if (OpenWithin (IntersectXYZ,err,0)) return Normal.Dot(mx-eye)*divisor>=0?1:-1; } Normal = my - ly; divisor = pnt.Dot(Normal); if (divisor!=0) { IntersectXYZ = eye + (Normal.Dot(ly-eye)/divisor)*pnt;//point of intersection with the ly plane //VSFileSystem::Fprintf (stderr,"Intersect::%f,%f,%f>\n",IntersectXYZ.i,IntersectXYZ.j,IntersectXYZ.k); if (OpenWithin (IntersectXYZ,err,1)) return Normal.Dot(ly-eye)*divisor>=0?1:-1; } Normal = -Normal; divisor = pnt.Dot(Normal); if (divisor!=0) { IntersectXYZ = eye + (Normal.Dot(my-eye)/divisor)*pnt;//point of intersection with my plane //VSFileSystem::Fprintf (stderr,"Intersect::%f,%f,%f>\n",IntersectXYZ.i,IntersectXYZ.j,IntersectXYZ.k); if (OpenWithin (IntersectXYZ,err,1)) return Normal.Dot(my-eye)*divisor>=0?1:-1; } Normal = (mz - lz); divisor = pnt.Dot(Normal); if (divisor!=0) { IntersectXYZ = eye + (Normal.Dot(lz-eye)/divisor)*pnt;//point of intersection with the ly plane //VSFileSystem::Fprintf (stderr,"Intersect::%f,%f,%f>\n",IntersectXYZ.i,IntersectXYZ.j,IntersectXYZ.k); if (OpenWithin (IntersectXYZ,err,2)) return Normal.Dot(lz-eye)*divisor>=0?1:-1; } Normal = -Normal; divisor = pnt.Dot(Normal); if (divisor!=0) { IntersectXYZ = eye + (Normal.Dot (mz-eye)/divisor)*pnt;//point of intersection with my plane //VSFileSystem::Fprintf (stderr,"Intersect::%f,%f,%f>\n",IntersectXYZ.i,IntersectXYZ.j,IntersectXYZ.k); if (OpenWithin (IntersectXYZ,err,2)) return Normal.Dot(mz-eye)*divisor>=0?1:-1; } return false; }