void DisarmTrapSpell::Launch() { ARX_SOUND_PlaySFX(SND_SPELL_DISARM_TRAP); m_duration = 1; Sphere sphere; sphere.origin = player.pos; sphere.radius = 400.f; for(size_t n = 0; n < MAX_SPELLS; n++) { SpellBase * spell = spells[SpellHandle(n)]; if(!spell || spell->m_type != SPELL_RUNE_OF_GUARDING) { continue; } Vec3f pos = static_cast<RuneOfGuardingSpell *>(spell)->getPosition(); if(sphere.contains(pos)) { spell->m_level -= m_level; if(spell->m_level <= 0) { spells.endSpell(spell); } } } }
bool AABB::intersectsSphere( const Sphere& s ) const { // get the closest pt on the box to the sphere. Vector3f boxPt = s.c ; boxPt.clampComponent( min, max ) ; // see if the pt on the box is inside the sphere return s.contains( boxPt ) ; }
void testGLight() { GLight L = GLight::point(Vector3(1,2,3), Color3::white(), 1,0,0); Sphere s; s = L.effectSphere(); debugAssert(s.contains(Vector3(1,2,3))); debugAssert(s.contains(Vector3(0,0,0))); debugAssert(s.contains(Vector3(100,100,100))); { GLight L = GLight::point(Vector3(1,2,3), Color3::white(), 1,0,1); Sphere s; s = L.effectSphere(); debugAssert(s.contains(Vector3(1,2,3))); debugAssert(s.contains(Vector3(1,1,3))); debugAssert(! s.contains(Vector3(100,100,100))); } }
bool Cone::intersects(const Sphere& b) const { // If the bounding sphere contains the tip, then // they definitely touch. if (b.contains(this->tip)) { return true; } // Move the tip backwards, effectively making the cone bigger // to account for the radius of the sphere. Vector3 tip = this->tip - direction * b.radius / sinf(angle); return Cone(tip, direction, angle).contains(b.center); }
void Sphere::merge(const Sphere& other) { if (other.contains(*this)) { *this = other; } else if (! contains(other)) { // The farthest distance is along the axis between the centers, which // must not be colocated since neither contains the other. Vector3 toMe = center - other.center; // Get a point on the axis from each toMe = toMe.direction(); const Vector3& A = center + toMe * radius; const Vector3& B = other.center - toMe * other.radius; // Now just bound the A->B segment center = (A + B) * 0.5f; radius = (A - B).length(); } // (if this contains other, we're done) }
void testSphere() { printf("Sphere..."); Sphere a(Vector3(0,3,0), 2); Sphere b(Vector3(0,2,0), 0.5f); debugAssert(a.contains(b)); debugAssert(! b.contains(a)); Sphere s = a; s.merge(b); debugAssert(s == a); Sphere c(Vector3(1,0,0), 2); s = a; s.merge(c); debugAssert(s.contains(a)); debugAssert(s.contains(c)); printf("passed\n"); }
bool HoverPlaneHelper::findMinimumHoverPlane (const Object & obj, float & roll, float & pitch, const Vector & lookAhead) { Object const * motor = obj.getParent (); if(motor) { CollisionProperty const * collision = motor->getCollisionProperty(); if(collision) { Footprint const * foot = collision->getFootprint(); if(foot && foot->isOnSolidFloor()) { Vector const & groundNormal_w = foot->getGroundNormal_w(); const Transform & transform_o2w = obj.getTransform_o2w (); computeRollPitch (transform_o2w.rotate_p2l (groundNormal_w), roll, pitch); return true; } } } // ---------- const Appearance * const app = obj.getAppearance (); if (!app) return false; const BoxExtent * const box = dynamic_cast<const BoxExtent *>(app->getExtent ()); if (!box) return false; const Transform & transform_o2w = obj.getTransform_o2w (); Vector points [10]; if (!transformBoxPoints (*box, transform_o2w, points, lookAhead)) return false; const TerrainObject * const terrainObject = TerrainObject::getInstance (); if (!terrainObject) return false; Vector normals [10]; Vector avgNormal; Vector avgLookAhead; int lookAheadContribCount = 0; Sphere s = box->getSphere (); s.setCenter (transform_o2w.getPosition_p ()); float avgDistanceAboveTerrain = 0.0f; float minDistanceAboveTerrain = 10000.0f; //- find terrain heights for points { const Vector oldCenterPoint = points [0]; float y = 0.0f; for (int i = 0; i < 10; ++i) { if (terrainObject->getHeight (points [i], y, normals [i])) { float waterHeight = 0.0f; const bool isWater = terrainObject->getWaterHeight (points[i], waterHeight); if(isWater && waterHeight > y) { normals[i] = Vector::unitY; y = waterHeight; } if (i >= 5) { //-- lookahead point is not in the sphere, let it contribute to the lookahead normal if (!s.contains (points [i])) { points [i].y = y; avgLookAhead += points [i] - oldCenterPoint; ++lookAheadContribCount; } points [i].y = y; } else { const float distanceAbove = points [i].y - y; avgDistanceAboveTerrain += distanceAbove; minDistanceAboveTerrain = std::max (0.0f, std::min (minDistanceAboveTerrain, distanceAbove)); points [i].y = y; avgNormal += normals [i]; } } else return false; } } avgNormal /= 5.0f; avgDistanceAboveTerrain /= 5.0f; computeRollPitch (transform_o2w.rotate_p2l (avgNormal), roll, pitch); //-- decrease the roll & pitch based on height over terrain //-- const float extentRadius = s.getRadius (); avgDistanceAboveTerrain -= extentRadius; if (avgDistanceAboveTerrain > 0.0f) { if (extentRadius > 0.0f) { const float relativeDistance = 1.0f + (avgDistanceAboveTerrain / (extentRadius * 0.5f)); roll /= relativeDistance; pitch /= relativeDistance; } } if (lookAheadContribCount) { avgLookAhead /= static_cast<float>(lookAheadContribCount); Vector vectorToLookAhead = transform_o2w.rotate_p2l (avgLookAhead); float pitchLookAhead = 0.0f; if (vectorToLookAhead.normalize ()) pitchLookAhead = vectorToLookAhead.phi (); else pitchLookAhead = 0.0f; if (pitchLookAhead < pitch) { pitch = pitchLookAhead; } } return true; }
Radiance3 RayTracer::L_indirectDiffuse (const shared_ptr<Surfel>& surfel, const Vector3& wo, ThreadData& threadData) const { if (! surfel->nonZeroFiniteScattering() || (m_photonMap.size() == 0)) { // Either no scattering or no photons; don't bother computing return Radiance3::zero(); } const Point3& X = surfel->position; Radiance3 L; const Sphere gatherSphere(X, m_settings.photon.maxGatherRadius); // Extract local triangles for collision detection Array<Tri>& localTris = threadData.localTri; if (m_settings.checkFinalVisibility && (gatherSphere.radius >= MIN_SURFACE_THICKNESS)) { getNearbyTris(surfel->position, surfel->geometricNormal, gatherSphere, localTris); } // Use the tri tree if there are too many elements in the array const bool useTriTreeVisibility = (localTris.size() > 10); for (PhotonMap::SphereIterator photon = m_photonMap.begin(gatherSphere); photon.isValid(); ++photon) { debugAssert(gatherSphere.contains(photon->position)); const Point3& Y = photon->position; // Distance to the photon; affects falloff const float s = (Y - X).length(); // Radius of the photon's effect const float r = photon->effectRadius; if (s < r) { // The falloff (smoothing) kernel will be non-zero. const Vector3& wi = photon->wi; const Color3& f = surfel->finiteScatteringDensity(wi, wo); // Maybe check visibility; don't bother if there is no illumination if (m_settings.checkFinalVisibility && f.nonZero() && (s > MIN_SURFACE_THICKNESS)) { // The photon is an appreciable distance from the shading point. // Cast a visibility ray to ensure that it is actually a good estimator // of flux at this location and not, for example, on the other side // of a partition. We should ideally be casting the ray back to the source // of the photon, but that information is no longer available. // Note that this code is similar to a VPL shadow ray or final gather ray. // Unlike VPLs, we already have a measure of visibility from the light source (and have // enough photons to make shading robust to moving objects)...and the ray cast // is always over a fairly short distance and thus likely to be fast. // Offset far enough that curved surfaces don't occlude themselves. const Vector3& offset = surfel->geometricNormal * (s * 0.5f + BUMP_EPSILON); const bool isVisible = useTriTreeVisibility ? visible(Y, X + offset) : ::visible(Y, X + offset, localTris, m_triTree.cpuVertexArray()); if (! isVisible) { // Stop processing this photon's contribution to the surfel continue; } } const Biradiance3& B = photon->power * clampedConeFalloff((X - Y).length(), 1.0f / r) / clampedConeVolume(r); L += B * f; } } return L; }