/** Checks how the box intersects with the sphere. */ Intersection intersect( const Sphere &one, const AxisAlignedBox &two ) { // Null box? if (two.isNull()) return OUTSIDE; if (two.isInfinite()) return INTERSECT; float sradius = one.getRadius(); sradius *= sradius; Vector3 scenter = one.getCenter(); const Vector3& twoMin = two.getMinimum(); const Vector3& twoMax = two.getMaximum(); float s, d = 0; Vector3 mndistance = ( twoMin - scenter ); Vector3 mxdistance = ( twoMax - scenter ); if ( mndistance.squaredLength() < sradius && mxdistance.squaredLength() < sradius ) { return INSIDE; } //find the square of the distance //from the sphere to the box for ( int i = 0 ; i < 3 ; i++ ) { if ( scenter[ i ] < twoMin[ i ] ) { s = scenter[ i ] - twoMin[ i ]; d += s * s; } else if ( scenter[ i ] > twoMax[ i ] ) { s = scenter[ i ] - twoMax[ i ]; d += s * s; } } bool partial = ( d <= sradius ); if ( !partial ) { return OUTSIDE; } else { return INTERSECT; } }
void ArcballTestApp::draw() { CameraPersp &cam = ( mUsingCameraUi ) ? mDebugCam : mCam; gl::clear( Color( 0, 0.0f, 0.15f ) ); gl::setMatrices( cam ); // draw the earth gl::enableDepthRead(); gl::enableDepthWrite(); gl::translate( mEarthSphere.getCenter() ); gl::rotate( mArcball.getQuat() ); mEarthTex->bind(); mEarth->draw(); // draw constraint axis if( mArcball.isUsingConstraint() ) { gl::setMatrices( cam ); gl::color( 1, 1, 0 ); gl::translate( mEarthSphere.getCenter() ); gl::rotate( glm::rotation( vec3( 0, 1, 0 ), mArcball.getConstraintAxis() ) ); mConstraintAxis->draw(); } gl::disableDepthRead(); // draw from vector marker gl::setMatrices( cam ); gl::color( 0, 1, 0.25f ); gl::translate( mEarthSphere.getCenter() + mArcball.getFromVector() * mEarthSphere.getRadius() ); mMarker->draw(); // draw to vector marker gl::setMatrices( cam ); gl::color( 1, 0.5f, 0.25f ); gl::translate( mEarthSphere.getCenter() + mArcball.getToVector() * mEarthSphere.getRadius() ); mMarker->draw(); // draw the elliptical axes gl::setMatricesWindow( getWindowSize() ); gl::color( 1, 0, 0 ); vec2 center, axisA, axisB; mCam.calcScreenProjection( mEarthSphere, getWindowSize(), ¢er, &axisA, &axisB ); gl::drawLine( center - axisA, center + axisA ); gl::drawLine( center - axisB, center + axisB ); }
ContainmentResult TestPointSphere ( Vector const & V, Sphere const & S ) { real radiusSquared = S.getRadius() * S.getRadius(); real distanceSquared = (V-S.getCenter()).magnitudeSquared(); return Containment1d::TestFloatLess(distanceSquared,radiusSquared); }
AxialBox EncloseABox ( Sphere const & sphere ) { float r = sphere.getRadius(); Vector c = sphere.getCenter(); Vector d(r,r,r); return AxialBox( c + d, c - d ); }
ContainmentResult TestSphereOBox ( Sphere const & S, OrientedBox const & B ) { if(Test(S.getCenter(),B) == CR_Inside) { return CR_Overlap; } else { Vector closest = Distance3d::ClosestPointOBox( S.getCenter(), B ); if(TestPointSphere(closest,S) == CR_Inside) { return CR_Overlap; } else { return CR_Outside; } } }
Sphere EncloseSphere ( Sphere const & A, Sphere const & B ) { if( Containment::isContainment(TestSphereSphere(A,B)) ) return B; if( Containment::isContainment(TestSphereSphere(B,A)) ) return A; // ---------- Vector normal = B.getCenter() - A.getCenter(); IGNORE_RETURN( normal.normalize() ); Vector pointA = A.getCenter() - normal * A.getRadius(); Vector pointB = B.getCenter() + normal * B.getRadius(); Vector center = Vector::midpoint(pointA,pointB); real radius = (pointB - pointA).magnitude() / 2.0f; return Sphere(center,radius); }
static void View(Camera* camera, const AxisAlignedBox& aabb, const Sphere& sphere) { float nearClip = (sphere.getRadius() > 1)? 1 : 0.05; float farClip = sphere.getRadius()*10000.0f; camera->setNearClipDistance(nearClip); camera->setFarClipDistance(farClip); // tan (fov/2.0) = r/d => d = r/tan(fov/2.0) float distance = sphere.getRadius()/Math::Tan(camera->getFOVy()/2.0f); camera->setPosition(sphere.getCenter() - (camera->getDirection().normalisedCopy()*distance)); }
CameraPersp CameraPersp::getFrameSphere( const Sphere &worldSpaceSphere, int maxIterations ) const { CameraPersp result = *this; result.setEyePoint( worldSpaceSphere.getCenter() - result.mViewDirection * getCenterOfInterest() ); float minDistance = 0.01f, maxDistance = 100000.0f; float curDistance = getCenterOfInterest(); for( int i = 0; i < maxIterations; ++i ) { float curRadius = result.getScreenRadius( worldSpaceSphere, 2.0f, 2.0f ); if( curRadius < 1.0f ) { // we should get closer maxDistance = curDistance; curDistance = ( curDistance + minDistance ) * 0.5f; } else { // we should get farther minDistance = curDistance; curDistance = ( curDistance + maxDistance ) * 0.5f; } result.setEyePoint( worldSpaceSphere.getCenter() - result.mViewDirection * curDistance ); } result.setCenterOfInterest( result.getEyePoint().distance( worldSpaceSphere.getCenter() ) ); return result; }
bool Math::intersected(const Plane& plane, const Sphere& sphere) { Vector3 point = sphere.getCenter(); Real dis = plane.getDistance(point); if(dis < sphere.getRadius()) { return true; } else { return false; } }
void ParticleObject::add(const Sphere<float>& sphere, const float diameter, const float charge) { const auto bb = sphere.getBoundingBox(); for (auto x = bb.getMinX(); x <= bb.getMaxX(); x+= diameter) { for (auto y = bb.getMinY(); y <= bb.getMaxY(); y += diameter) { for (auto z = bb.getMinZ(); z <= bb.getMaxZ(); z+= diameter) { const Vector3d<float> pos(x, y, z); if (sphere.isInner(pos)) { const auto density = (sphere.getRadius() - sphere.getCenter().getDistance(pos)) * charge; particles.push_back(new Particle(pos, density, diameter * 0.5f)); } } } } sort(); }
void Collide::pointSphereCollide(const Body * point_, const Body * sphere_) { Point *point = (Point*)point_; Sphere *sphere = (Sphere*)sphere_; float distance = 0.0f; distance = (point->getPoint() - sphere->getCenter()).Length(); setCollide(distance < sphere->getRadius()); setDistance(distance - sphere->getRadius()); // compute the response vectors Vector3 responseObject1 = point_->getCenter() - sphere_->getCenter(); Vector3 responseObject2 = sphere_->getCenter() - point_->getCenter(); setResponseObject1(responseObject1); setResponseObject2(responseObject2); }
bool Math::intersected(const Ray& ray, const Sphere& sphere) { Vector3 t = ray.getOrien(); Vector3 origin = ray.getOrigin(); Vector3 center = sphere.getCenter(); Vector3 s = center - origin; Real d = (s.crossProduct(t)).length(); if(d <= sphere.getRadius()) { return true; } else { return false; } }
void setShaderVariables(GLuint shaderProg) { GLfloat projMatrix[16]; GLfloat viewMatrix[16]; glGetFloatv(GL_PROJECTION_MATRIX, projMatrix); glGetFloatv(GL_MODELVIEW_MATRIX, viewMatrix); double *center = ball.getCenter(); if(GL20Support) { glUniform3f(glGetUniformLocation(shaderProg, "ballPos"),center[0], center[1], center[2]); } else { //glUniform3fvARB(glGetUniformLocationARB(shaderProg, "ballPos"), 3, (float*)ball.getCenter()); } }
//----------------------------------------------------------------------- std::pair<bool, Real> Math::intersects(const Ray& ray, const Sphere& sphere, bool discardInside) { const Vector3& raydir = ray.getDirection(); // Adjust ray origin relative to sphere center const Vector3& rayorig = ray.getOrigin() - sphere.getCenter(); Real radius = sphere.getRadius(); // Check origin inside first if (rayorig.squaredLength() <= radius*radius && discardInside) { return std::pair<bool, Real>(true, (Real)0); } // Mmm, quadratics // Build coeffs which can be used with std quadratic solver // ie t = (-b +/- sqrt(b*b + 4ac)) / 2a Real a = raydir.dotProduct(raydir); Real b = 2 * rayorig.dotProduct(raydir); Real c = rayorig.dotProduct(rayorig) - radius*radius; // Calc determinant Real d = (b*b) - (4 * a * c); if (d < 0) { // No intersection return std::pair<bool, Real>(false, (Real)0); } else { // BTW, if d=0 there is one intersection, if d > 0 there are 2 // But we only want the closest one, so that's ok, just use the // '-' version of the solver Real t = ( -b - Math::Sqrt(d) ) / (2 * a); if (t < 0) t = ( -b + Math::Sqrt(d) ) / (2 * a); return std::pair<bool, Real>(true, (Real)t); } }
void Collide::raySphereCollide(const Body * ray_, const Body * sphere_) { Ray *ray = (Ray*)ray_; Sphere *sphere = (Sphere*)sphere_; Vector3 vec = ray->getStart() - sphere->getCenter(); setCollide(true); setDistance(0.0f); float fB = vec.Dot(ray->getDir()); float fC = vec.Dot(vec) - sphere->getRadius()*sphere->getRadius(); if (fC > 0.0f && fB > 0.0f) setCollide(false); float fDisc = fB*fB - fC; if (fDisc < 0.0f) setCollide(false); // compute the response vectors Vector3 responseObject1 = ray_->getCenter()- sphere_->getCenter(); Vector3 responseObject2 = sphere_->getCenter() - ray_->getCenter(); setResponseObject1(responseObject1); setResponseObject2(responseObject2); }
//============================================================================== static Bool test(const Aabb& aabb, const Sphere& s) { const Vec4& c = s.getCenter(); // find the box's closest point to the sphere Vec4 cp(0.0); // Closest Point for(U i = 0; i < 3; i++) { // if the center is greater than the max then the closest // point is the max if(c[i] > aabb.getMax()[i]) { cp[i] = aabb.getMax()[i]; } else if(c[i] < aabb.getMin()[i]) // relative to the above { cp[i] = aabb.getMin()[i]; } else { // the c lies between min and max cp[i] = c[i]; } } F32 rsq = s.getRadius() * s.getRadius(); // if the c lies totally inside the box then the sub is the zero, // this means that the length is also zero and thus its always smaller // than rsq Vec4 sub = c - cp; if(sub.getLengthSquared() <= rsq) { return true; } return false; }
//============================================================================== Bool test(const LineSegment& ls, const Sphere& s) { const Vec4& v = ls.getDirection(); Vec4 w0 = s.getCenter() - ls.getOrigin(); F32 w0dv = w0.dot(v); F32 rsq = s.getRadius() * s.getRadius(); if(w0dv < 0.0) // if the ang is >90 { return w0.getLengthSquared() <= rsq; } Vec4 w1 = w0 - v; // aka center - P1, where P1 = seg.origin + seg.dir F32 w1dv = w1.dot(v); if(w1dv > 0.0) // if the ang is <90 { return w1.getLengthSquared() <= rsq; } // the big parenthesis is the projection of w0 to v Vec4 tmp = w0 - (v * (w0.dot(v) / v.getLengthSquared())); return tmp.getLengthSquared() <= rsq; }
ContainmentResult TestSphereCylinder ( Sphere const & S, Cylinder const & C ) { Vector delta = C.getBase() - S.getCenter(); delta.y = 0; real dist = delta.magnitude(); Range SD( dist - S.getRadius(), dist + S.getRadius() ); Range CD( -C.getRadius(), C.getRadius() ); ContainmentResult hTest = Containment1d::TestRangeRange( SD, CD ); ContainmentResult hTest2 = Containment1d::TestFloatRange( dist, CD ); ContainmentResult vTest = Containment1d::TestRangeRange( S.getRangeY(), C.getRangeY() ); ContainmentResult cTest = Containment1d::TestFloatRange( S.getCenter().y, C.getRangeY() ); // ---------- if(hTest == CR_Outside) { // Sphere can't possibly touch the cylinder return CR_Outside; } else if((hTest == CR_TouchingOutside) || (hTest == CR_Boundary)) { // Sphere is touching the outside of the cylinder's tube if its // center is inside the vertical range of the cylinder if((cTest == CR_Inside) || (cTest == CR_Boundary)) { return CR_TouchingOutside; } else { return CR_Outside; } } else if((hTest == CR_Inside) || (hTest == CR_TouchingInside)) { // Sphere is in the tube of the cylinder. It touches the cylinder // if its vertical range touches the vertical range of the cylinder return Containment::ComposeAxisTests(hTest,vTest); } else { // hTest == CR_Overlap if(vTest == CR_Outside) { return CR_Outside; } else if((vTest == CR_Inside) || (vTest == CR_TouchingInside)) { return CR_Overlap; } else if (vTest == CR_Boundary) { // This really shouldn't be happening return CR_Boundary; } else if (vTest == CR_TouchingOutside) { if(hTest2 == CR_Inside) { // Sphere is touching a cap of the cylinder return CR_TouchingOutside; } else if(hTest2 == CR_Boundary) { // Sphere is touching the edge of the cap of the cylinder return CR_TouchingOutside; } else { // Sphere isn't touching the cap return CR_Outside; } } else { // vTest == CR_Overlap if((cTest == CR_Inside) || (cTest == CR_Boundary)) { // The ranges overlap vertically and horizontally, and the center of // the sphere is inside the vertical range - the sphere overlaps the // cylinder return CR_Overlap; } else { // The sphere is inside both ranges, but its center is outside both // ranges. The sphere overlaps the cylinder if the closest point // on the cylinder is inside the sphere. Vector closestPoint = Distance3d::ClosestPointCylinder(S.getCenter(),C); ContainmentResult result = TestPointSphere(closestPoint,S); if(result == CR_Outside) { return CR_Outside; } else if(result == CR_Boundary) { return CR_TouchingOutside; } else { return CR_Overlap; } } } } }
bool Frustum::projectSphere(const Sphere& sphere, Real* left, Real* top, Real* right, Real* bottom) const { // 变换光源位置到相机空间 updateView(); Vector3 eyeSpacePos = mViewMatrix.transformAffine(sphere.getCenter()); //将球中心坐标转到观察空间中 // 初始化 *left = *bottom = -1.0f; *right = *top = 1.0f; if (eyeSpacePos.z < 0) { updateFrustum(); const Matrix4& projMatrix = getProjectionMatrix(); Real r = sphere.getRadius(); Real rsq = r * r; //半径的平方 if (eyeSpacePos.squaredLength() <= rsq) return false; Real Lxz = Math::Sqr(eyeSpacePos.x) + Math::Sqr(eyeSpacePos.z); //设原点O,球心P, 向量Vop在XZ平面上的投影 Real Lyz = Math::Sqr(eyeSpacePos.y) + Math::Sqr(eyeSpacePos.z); //设原点O,球心P, 向量Vop在YZ平面上的投影 // 用点法式 找出球体切平面 // 首先XZ // 计算二次根判别式: b*b - 4ac // x = Nx // a = Lx^2 + Lz^2 // b = -2rLx // c = r^2 - Lz^2 Real a = Lxz; Real b = -2.0f * r * eyeSpacePos.x; Real c = rsq - Math::Sqr(eyeSpacePos.z); Real D = b*b - 4.0f*a*c; // 两个根 if (D > 0) { Real sqrootD = Math::Sqrt(D); // 解除二次方获取法线的分量 Real Nx0 = (-b + sqrootD) / (2 * a); Real Nx1 = (-b - sqrootD) / (2 * a); // 取得Z Real Nz0 = (r - Nx0 * eyeSpacePos.x) / eyeSpacePos.z; Real Nz1 = (r - Nx1 * eyeSpacePos.x) / eyeSpacePos.z; // 获取切点 // 只考虑相机前面的切点 Real Pz0 = (Lxz - rsq) / (eyeSpacePos.z - ((Nz0 / Nx0) * eyeSpacePos.x)); if (Pz0 < 0) { // 投影在近剪裁平面在世界空间的点 Real nearx0 = (Nz0 * mNearDist) / Nx0; // 现在我们需要映射它到视口坐标 // 用投影矩阵,并考虑所有的因素 Vector3 relx0 = projMatrix * Vector3(nearx0, 0, -mNearDist); //找出这是左边还是右边 Real Px0 = -(Pz0 * Nz0) / Nx0; if (Px0 > eyeSpacePos.x) { *right = std::min(*right, relx0.x); } else { *left = std::max(*left, relx0.x); } } Real Pz1 = (Lxz - rsq) / (eyeSpacePos.z - ((Nz1 / Nx1) * eyeSpacePos.x)); if (Pz1 < 0) { //投影在近剪裁平面在世界空间的点 Real nearx1 = (Nz1 * mNearDist) / Nx1; // 现在我们需要映射它到视口坐标 // 用投影矩阵,并考虑所有的因素 Vector3 relx1 = projMatrix * Vector3(nearx1, 0, -mNearDist); //找出这是左边还是右边 Real Px1 = -(Pz1 * Nz1) / Nx1; if (Px1 > eyeSpacePos.x) { *right = std::min(*right, relx1.x); } else { *left = std::max(*left, relx1.x); } } } // 现在是 YZ 平面 // 计算二次方根判别式: b*b - 4ac // x = Ny // a = Ly^2 + Lz^2 // b = -2rLy // c = r^2 - Lz^2 a = Lyz; b = -2.0f * r * eyeSpacePos.y; c = rsq - Math::Sqr(eyeSpacePos.z); D = b*b - 4.0f*a*c; //两个根 if (D > 0) { Real sqrootD = Math::Sqrt(D); // 解除二次根获得法线的分量 Real Ny0 = (-b + sqrootD) / (2 * a); Real Ny1 = (-b - sqrootD) / (2 * a); // 从这里取得Z Real Nz0 = (r - Ny0 * eyeSpacePos.y) / eyeSpacePos.z; Real Nz1 = (r - Ny1 * eyeSpacePos.y) / eyeSpacePos.z; // 获取切点 // 只考虑相机前面的切点 Real Pz0 = (Lyz - rsq) / (eyeSpacePos.z - ((Nz0 / Ny0) * eyeSpacePos.y)); if (Pz0 < 0) { //投影在近剪裁平面在世界空间的点 Real neary0 = (Nz0 * mNearDist) / Ny0; // 现在我们需要映射它到视口坐标 // 用投影矩阵,并考虑所有的因素 Vector3 rely0 = projMatrix * Vector3(0, neary0, -mNearDist); //找出这是左边还是右边 Real Py0 = -(Pz0 * Nz0) / Ny0; if (Py0 > eyeSpacePos.y) { *top = std::min(*top, rely0.y); } else { *bottom = std::max(*bottom, rely0.y); } } Real Pz1 = (Lyz - rsq) / (eyeSpacePos.z - ((Nz1 / Ny1) * eyeSpacePos.y)); if (Pz1 < 0) { //投影在近剪裁平面在世界空间的点 Real neary1 = (Nz1 * mNearDist) / Ny1; // 现在我们需要映射它到视口坐标 // 用投影矩阵,并考虑所有的因素 Vector3 rely1 = projMatrix * Vector3(0, neary1, -mNearDist); //找出这是左边还是右边 Real Py1 = -(Pz1 * Nz1) / Ny1; if (Py1 > eyeSpacePos.y) { *top = std::min(*top, rely1.y); } else { *bottom = std::max(*bottom, rely1.y); } } } } return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f); }
bool TestSpherePlane ( Sphere const & A, Plane3d const & B ) { float dist = std::abs(Distance3d::DistancePointPlane(A.getCenter(),B)); return dist <= A.getRadius(); }
bool TestYLineSphere ( Vector const & V, Sphere const & S ) { return Distance2d::Distance2PointPoint(V,S.getCenter()) < sqr(S.getRadius()); }
//============================================================================== static Bool test(const Sphere& a, const Sphere& b) { F32 tmp = a.getRadius() + b.getRadius(); return (a.getCenter() - b.getCenter()).getLengthSquared() <= tmp * tmp; }
__global__ void gpuWalkWithSentinel(int seed, DistanceEvaluator* distance, ResultsCalculator* results) { unsigned int index = blockIdx.x * blockDim.x + threadIdx.x; CudaRandom rand(index, seed); Sphere<double> boundingSphere = distance->boundingSphere(); results->gpuConstructor(index); Vector3<double> startingPosition = RandomPoint::generate(&rand, &boundingSphere); while ((*distance)(startingPosition) < epsilon){ results->recordHit(index, startingPosition, startingPosition); Vector3<double> startingPosition = RandomPoint::generate(&rand, &boundingSphere); } Vector3<double> position = startingPosition; bool replace = false; bool done = false; size_t walks = 0; //while (walks < walksPerThread) while (!done) { Sphere<double> displacementSphere{position, (*distance)(position)}; position = RandomPoint::generate(&rand, &displacementSphere); // Check for escape! double centerDistSqr = (position - boundingSphere.getCenter()).getMagnitudeSqr(); if (centerDistSqr > boundingSphere.getRadiusSqr()) { //walker left bounding sphere double alpha = boundingSphere.getRadius() / sqrt(centerDistSqr); if (rand.getRandInRange(0, 1) > (1 - alpha)) { //walker is replaced position = BiasedPoint::generate(&rand, &boundingSphere, &position, alpha); } else { results->recordMiss(index); replace = true; } } if ((*distance)(position) < 0.0001) { results->recordHit(index, startingPosition, position); replace = true; } if (replace) { if (results->runFinished()) { done = true; } else { ++walks; replace = false; startingPosition = RandomPoint::generate(&rand, &boundingSphere); while ((*distance)(startingPosition) < epsilon){ results->recordHit(index, startingPosition, startingPosition); Vector3<double> startingPosition = RandomPoint::generate(&rand, &boundingSphere); } position = startingPosition; } } } }
//--------------------------------------------------------------------- bool Frustum::projectSphere(const Sphere& sphere, Real* left, Real* top, Real* right, Real* bottom) const { // See http://www.gamasutra.com/features/20021011/lengyel_06.htm // Transform light position into camera space updateView(); Vector3 eyeSpacePos = mViewMatrix.transformAffine(sphere.getCenter()); // initialise *left = *bottom = -1.0f; *right = *top = 1.0f; if (eyeSpacePos.z < 0) { updateFrustum(); const Matrix4& projMatrix = getProjectionMatrix(); Real r = sphere.getRadius(); Real rsq = r * r; // early-exit if (eyeSpacePos.squaredLength() <= rsq) return false; Real Lxz = Math::Sqr(eyeSpacePos.x) + Math::Sqr(eyeSpacePos.z); Real Lyz = Math::Sqr(eyeSpacePos.y) + Math::Sqr(eyeSpacePos.z); // Find the tangent planes to the sphere // XZ first // calculate quadratic discriminant: b*b - 4ac // x = Nx // a = Lx^2 + Lz^2 // b = -2rLx // c = r^2 - Lz^2 Real a = Lxz; Real b = -2.0 * r * eyeSpacePos.x; Real c = rsq - Math::Sqr(eyeSpacePos.z); Real D = b*b - 4*a*c; // two roots? if (D > 0) { Real sqrootD = Math::Sqrt(D); // solve the quadratic to get the components of the normal Real Nx0 = (-b + sqrootD) / (2 * a); Real Nx1 = (-b - sqrootD) / (2 * a); // Derive Z from this Real Nz0 = (r - Nx0 * eyeSpacePos.x) / eyeSpacePos.z; Real Nz1 = (r - Nx1 * eyeSpacePos.x) / eyeSpacePos.z; // Get the point of tangency // Only consider points of tangency in front of the camera Real Pz0 = (Lxz - rsq) / (eyeSpacePos.z - ((Nz0 / Nx0) * eyeSpacePos.x)); if (Pz0 < 0) { // Project point onto near plane in worldspace Real nearx0 = (Nz0 * mNearDist) / Nx0; // now we need to map this to viewport coords // use projection matrix since that will take into account all factors Vector3 relx0 = projMatrix * Vector3(nearx0, 0, -mNearDist); // find out whether this is a left side or right side Real Px0 = -(Pz0 * Nz0) / Nx0; if (Px0 > eyeSpacePos.x) { *right = std::min(*right, relx0.x); } else { *left = std::max(*left, relx0.x); } } Real Pz1 = (Lxz - rsq) / (eyeSpacePos.z - ((Nz1 / Nx1) * eyeSpacePos.x)); if (Pz1 < 0) { // Project point onto near plane in worldspace Real nearx1 = (Nz1 * mNearDist) / Nx1; // now we need to map this to viewport coords // use projection matrix since that will take into account all factors Vector3 relx1 = projMatrix * Vector3(nearx1, 0, -mNearDist); // find out whether this is a left side or right side Real Px1 = -(Pz1 * Nz1) / Nx1; if (Px1 > eyeSpacePos.x) { *right = std::min(*right, relx1.x); } else { *left = std::max(*left, relx1.x); } } } // Now YZ // calculate quadratic discriminant: b*b - 4ac // x = Ny // a = Ly^2 + Lz^2 // b = -2rLy // c = r^2 - Lz^2 a = Lyz; b = -2.0 * r * eyeSpacePos.y; c = rsq - Math::Sqr(eyeSpacePos.z); D = b*b - 4*a*c; // two roots? if (D > 0) { Real sqrootD = Math::Sqrt(D); // solve the quadratic to get the components of the normal Real Ny0 = (-b + sqrootD) / (2 * a); Real Ny1 = (-b - sqrootD) / (2 * a); // Derive Z from this Real Nz0 = (r - Ny0 * eyeSpacePos.y) / eyeSpacePos.z; Real Nz1 = (r - Ny1 * eyeSpacePos.y) / eyeSpacePos.z; // Get the point of tangency // Only consider points of tangency in front of the camera Real Pz0 = (Lyz - rsq) / (eyeSpacePos.z - ((Nz0 / Ny0) * eyeSpacePos.y)); if (Pz0 < 0) { // Project point onto near plane in worldspace Real neary0 = (Nz0 * mNearDist) / Ny0; // now we need to map this to viewport coords // use projection matriy since that will take into account all factors Vector3 rely0 = projMatrix * Vector3(0, neary0, -mNearDist); // find out whether this is a top side or bottom side Real Py0 = -(Pz0 * Nz0) / Ny0; if (Py0 > eyeSpacePos.y) { *top = std::min(*top, rely0.y); } else { *bottom = std::max(*bottom, rely0.y); } } Real Pz1 = (Lyz - rsq) / (eyeSpacePos.z - ((Nz1 / Ny1) * eyeSpacePos.y)); if (Pz1 < 0) { // Project point onto near plane in worldspace Real neary1 = (Nz1 * mNearDist) / Ny1; // now we need to map this to viewport coords // use projection matriy since that will take into account all factors Vector3 rely1 = projMatrix * Vector3(0, neary1, -mNearDist); // find out whether this is a top side or bottom side Real Py1 = -(Pz1 * Nz1) / Ny1; if (Py1 > eyeSpacePos.y) { *top = std::min(*top, rely1.y); } else { *bottom = std::max(*bottom, rely1.y); } } } } return (*left != -1.0f) || (*top != 1.0f) || (*right != 1.0f) || (*bottom != -1.0f); }
static bool test( const Sphere< T > &sphere1, const Sphere< T > &sphere2 ) { T centerDiffSqr = ( sphere1.getCenter() - sphere2.getCenter() ).getSquaredMagnitude(); T combinedRadius = ( sphere1.getRadius() + sphere2.getRadius() ); return ( centerDiffSqr < ( combinedRadius * combinedRadius ) ); }
void DebugDraw::draw(const Sphere& sphere, const Color& color, bool mesh) const { Matrix4x4 modelMatrix; if (mesh) { if (!LineGeometryManager::getInstance()->getLineGeometry("Sphere").get()) { return; } modelMatrix.identity(); modelMatrix.translate(sphere.getCenter().getX(), sphere.getCenter().getY(), sphere.getCenter().getZ()); modelMatrix.scale(sphere.getRadius(), sphere.getRadius(), sphere.getRadius()); LineGeometryManager::getInstance()->getLineGeometry("Sphere")->draw(modelMatrix, color); } else { if (!LineGeometryManager::getInstance()->getLineGeometry("Circle").get()) { return; } modelMatrix.identity(); modelMatrix.translate(sphere.getCenter().getX(), sphere.getCenter().getY(), sphere.getCenter().getZ()); modelMatrix.rotateRzRyRx(0.0f, 0.0f, 0.0f); modelMatrix.scale(sphere.getRadius(), sphere.getRadius(), sphere.getRadius()); LineGeometryManager::getInstance()->getLineGeometry("Circle")->draw(modelMatrix, color); modelMatrix.identity(); modelMatrix.translate(sphere.getCenter().getX(), sphere.getCenter().getY(), sphere.getCenter().getZ()); modelMatrix.rotateRzRyRx(0.0f, 90.0f, 0.0f); modelMatrix.scale(sphere.getRadius(), sphere.getRadius(), sphere.getRadius()); LineGeometryManager::getInstance()->getLineGeometry("Circle")->draw(modelMatrix, color); modelMatrix.identity(); modelMatrix.translate(sphere.getCenter().getX(), sphere.getCenter().getY(), sphere.getCenter().getZ()); modelMatrix.rotateRzRyRx(0.0f, 0.0f, 90.0f); modelMatrix.scale(sphere.getRadius(), sphere.getRadius(), sphere.getRadius()); LineGeometryManager::getInstance()->getLineGeometry("Circle")->draw(modelMatrix, color); } }
bool PathFinderManager::getSpawnPointInArea(const Sphere& area, Zone *zone, Vector3& point, bool checkPath) { SortedVector<ManagedReference<NavArea*>> areas; float radius = area.getRadius(); const Vector3& center = area.getCenter(); Vector3 flipped(center.getX(), center.getZ(), -center.getY()); float extents[3] = {3, 5, 3}; dtNavMeshQuery* query = getNavQuery(); if (zone == NULL) return false; zone->getInRangeNavMeshes(center.getX(), center.getY(), &areas, true); if (areas.size() == 0) { Vector3 temp((frand() * 2.0f) - 1.0f, (frand() * 2.0f) - 1.0f, 0); Vector3 result = temp * (frand() * radius); point = center + result; point.setZ(CollisionManager::getWorldFloorCollision(point.getX(), point.getY(), zone, false)); return true; } for (const auto& navArea : areas) { Vector3 polyStart; dtPolyRef startPoly; dtPolyRef ref; int status = 0; float pt[3]; RecastNavMesh *mesh = navArea->getNavMesh(); if (mesh == NULL) continue; ReadLocker rLocker(navArea); dtNavMesh *dtNavMesh = mesh->getNavMesh(); if (dtNavMesh == NULL) continue; query->init(dtNavMesh, MAX_QUERY_NODES); if (!((status = query->findNearestPoly(flipped.toFloatArray(), extents, &m_spawnFilter, &startPoly, polyStart.toFloatArray())) & DT_SUCCESS)) continue; for (int i=0; i<50; i++) { try { if (!((status = query->findRandomPointAroundCircle(startPoly, polyStart.toFloatArray(), radius, &m_spawnFilter, frand, &ref, pt)) & DT_SUCCESS)) { continue; } else { point = Vector3(pt[0], -pt[2], CollisionManager::getWorldFloorCollision(pt[0], -pt[2], zone, false)); Vector3 temp = point - center; float len = temp.length(); if (len > radius) { float multiplier = (frand() * radius) / len; temp.setX(temp.getX() * multiplier); temp.setY(temp.getY() * multiplier); point = center + temp; point.setZ(CollisionManager::getWorldFloorCollision(point.getX(), point.getY(), zone, false)); } if (checkPath) { if (!getRecastPath(center, point, navArea, nullptr, len, false)) { continue; } } return true; } } catch (Exception& exc) { error(exc.getMessage()); } } } return false; }
bool pointInSphere(const Vector3 &point, const Sphere& sphere) { return (point-sphere.getCenter()).length() < sphere.getRadius(); }
bool FrustumT<T>::contains( const Sphere &sphere ) const { return contains( Vec3T( sphere.getCenter() ), (T)sphere.getRadius() ); }
bool FrustumT<T>::intersects( const Sphere &sphere ) const { return intersects( Vec3T( sphere.getCenter() ), (T)sphere.getRadius() ); }