Real MathUtil::distance(const AxisAlignedBox& b1, const AxisAlignedBox& b2) { if (b1.intersects(b2)) { return 0.0f; } else { Vector3 dv; const Vector3& min1 = b1.getMinimum(); const Vector3& min2 = b2.getMinimum(); const Vector3& max1 = b1.getMaximum(); const Vector3& max2 = b2.getMaximum(); dv.x = min1.x > max2.x ? min1.x - max2.x : min2.x > max1.x ? min2.x - max1.x : 0.0f; dv.y = min1.y > max2.y ? min1.y - max2.y : min2.y > max1.y ? min2.y - max1.y : 0.0f; dv.z = min1.z > max2.z ? min1.z - max2.z : min2.z > max1.z ? min2.z - max1.z : 0.0f; return dv.length(); } }
void COctreeTriangleSelector::getTrianglesFromOctree( SOctreeNode* node, SINT32& trianglesWritten, SINT32 maximumSize, const AxisAlignedBox& box, const Matrix4* mat, triangle3df* triangles) const { if (!box.intersects(node->Box)) //if (!box.intersectsWithBox(node->Box)) return; const UINT32 cnt = node->Triangles.size(); for (UINT32 i = 0; i<cnt; ++i) { const triangle3df& srcTri = node->Triangles[i]; // This isn't an accurate test, but it's fast, and the // API contract doesn't guarantee complete accuracy. if (srcTri.isTotalOutsideBox(box)) continue; triangle3df& dstTri = triangles[trianglesWritten]; //mat->transformVect(dstTri.pointA, srcTri.pointA //mat->transformVect(dstTri.pointB, srcTri.pointB); //mat->transformVect(dstTri.pointC, srcTri.pointC); dstTri.pointA = mat->transformAffine(srcTri.pointA); dstTri.pointB = mat->transformAffine(srcTri.pointB); dstTri.pointC = mat->transformAffine(srcTri.pointC); ++trianglesWritten; // Halt when the out array is full. if (trianglesWritten == maximumSize) return; } for (UINT32 i = 0; i<8; ++i) if (node->Child[i]) getTrianglesFromOctree(node->Child[i], trianglesWritten, maximumSize, box, mat, triangles); }
//----------------------------------------------------------------------- bool Light::isInLightRange(const Ogre::AxisAlignedBox& container) const { bool isIntersect = true; //Check the 2 simple / obvious situations. Light is directional or light source is inside the container if ((mLightType != LT_DIRECTIONAL) && (container.intersects(mDerivedPosition) == false)) { //Check that the container is within the sphere of the light isIntersect = Math::intersects(Sphere(mDerivedPosition, mRange),container); //If this is a spotlight, do a more specific check if ((isIntersect) && (mLightType == LT_SPOTLIGHT) && (mSpotOuter.valueRadians() <= Math::PI)) { //Create a rough bounding box around the light and check if Quaternion localToWorld = Vector3::NEGATIVE_UNIT_Z.getRotationTo(mDerivedDirection); Real boxOffset = Math::Sin(mSpotOuter * 0.5) * mRange; AxisAlignedBox lightBoxBound; lightBoxBound.merge(Vector3::ZERO); lightBoxBound.merge(localToWorld * Vector3(boxOffset, boxOffset, -mRange)); lightBoxBound.merge(localToWorld * Vector3(-boxOffset, boxOffset, -mRange)); lightBoxBound.merge(localToWorld * Vector3(-boxOffset, -boxOffset, -mRange)); lightBoxBound.merge(localToWorld * Vector3(boxOffset, -boxOffset, -mRange)); lightBoxBound.setMaximum(lightBoxBound.getMaximum() + mDerivedPosition); lightBoxBound.setMinimum(lightBoxBound.getMinimum() + mDerivedPosition); isIntersect = lightBoxBound.intersects(container); //If the bounding box check succeeded do one more test if (isIntersect) { //Check intersection again with the bounding sphere of the container //Helpful for when the light is at an angle near one of the vertexes of the bounding box isIntersect = isInLightRange(Sphere(container.getCenter(), container.getHalfSize().length())); } } } return isIntersect; }
//----------------------------------------------------------------------- void BoxCollider::_affect(ParticleTechnique* particleTechnique, Particle* particle, Real timeElapsed) { mPredictedPosition = particle->position + mVelocityScale * particle->direction; bool collision = false; /** Collision detection is a two-step. First, we determine whether the particle is now colliding. If it is, the particle is re-positioned. However, a timeElapsed value is used, which is not the same as the one that was used at the moment before the particle was colliding. Therefore, we rather want to predict particle collision in front. This probably isn't the fastest solution. The same approach was used for the other colliders. */ switch(mIntersectionType) { case BaseCollider::IT_POINT: { // Validate for a point-box intersection if (mInnerCollision != mBox.intersects(particle->position)) { // Collision detected (re-position the particle) particle->position -= mVelocityScale * particle->direction; collision = true; } else if (mInnerCollision != mBox.intersects(mPredictedPosition)) { // Collision detected collision = true; } } break; case BaseCollider::IT_BOX: { // Validate for a box-box intersection if (particle->particleType != Particle::PT_VISUAL) break; VisualParticle* visualParticle = static_cast<VisualParticle*>(particle); AxisAlignedBox box; populateAlignedBox(box, visualParticle->position, visualParticle->width, visualParticle->height, visualParticle->depth); if (mInnerCollision != box.intersects(mBox)) { // Collision detected (re-position the particle) particle->position -= mVelocityScale * particle->direction; collision = true; } else { AxisAlignedBox box; populateAlignedBox(box, mPredictedPosition, visualParticle->width, visualParticle->height, visualParticle->depth); if (mInnerCollision != box.intersects(mBox)) { // Collision detected collision = true; } } } break; } if (collision) { calculateDirectionAfterCollision(particle); calculateRotationSpeedAfterCollision(particle); particle->addEventFlags(Particle::PEF_COLLIDED); } }
// --- find nodes which intersect various types of BV's --- void DefaultZone::_findNodes( const AxisAlignedBox &t, PCZSceneNodeList &list, PortalList &visitedPortals, bool includeVisitors, bool recurseThruPortals, PCZSceneNode *exclude ) { // if this zone has an enclosure, check against the enclosure AABB first if (mEnclosureNode) { if (!mEnclosureNode->_getWorldAABB().intersects(t)) { // AABB of zone does not intersect t, just return. return; } } // check nodes at home in this zone PCZSceneNodeList::iterator it = mHomeNodeList.begin(); while ( it != mHomeNodeList.end() ) { PCZSceneNode * pczsn = *it; if ( pczsn != exclude ) { // make sure node is not already in the list (might have been added in another // zone it was visiting) PCZSceneNodeList::iterator it2 = list.find(pczsn); if (it2 == list.end()) { bool nsect = t.intersects( pczsn -> _getWorldAABB() ); if ( nsect ) { list.insert( pczsn ); } } } ++it; } if (includeVisitors) { // check visitor nodes PCZSceneNodeList::iterator iter = mVisitorNodeList.begin(); while ( iter != mVisitorNodeList.end() ) { PCZSceneNode * pczsn = *iter; if ( pczsn != exclude ) { // make sure node is not already in the list (might have been added in another // zone it was visiting) PCZSceneNodeList::iterator it2 = list.find(pczsn); if (it2 == list.end()) { bool nsect = t.intersects( pczsn -> _getWorldAABB() ); if ( nsect ) { list.insert( pczsn ); } } } ++iter; } } // if asked to, recurse through portals if (recurseThruPortals) { PortalList::iterator pit = mPortals.begin(); while ( pit != mPortals.end() ) { Portal * portal = *pit; // check portal versus bounding box if (portal->intersects(t)) { // make sure portal hasn't already been recursed through PortalList::iterator pit2 = std::find(visitedPortals.begin(), visitedPortals.end(), portal); if (pit2 == visitedPortals.end()) { // save portal to the visitedPortals list visitedPortals.push_front(portal); // recurse into the connected zone portal->getTargetZone()->_findNodes(t, list, visitedPortals, includeVisitors, recurseThruPortals, exclude); } } pit++; } } }