//------------------------------------------------------------------------------ void SegmentedDynamicLightManager::LightData::setBounds(const AxisAlignedBox& i_Bounds) { mMinX = i_Bounds.getMinimum().x; mMaxX = i_Bounds.getMaximum().x; mMinZ = i_Bounds.getMinimum().z; mMaxZ = i_Bounds.getMaximum().z; }
//------------------------------------------------------------------------- TerrainTile * OverhangTerrainPage::getTerrainTile( const Vector3 & pt ) { /* Since we don't know if the terrain is square, or has holes, we use a line trace to find the containing tile... */ TerrainTile * tile = tiles[ 0 ][ 0 ]; while ( tile != 0 ) { AxisAlignedBox b = tile -> getBoundingBox(); if ( pt.x < b.getMinimum().x ) tile = tile -> _getNeighbor( TerrainTile::WEST ); else if ( pt.x > b.getMaximum().x ) tile = tile -> _getNeighbor( TerrainTile::EAST ); else if ( pt.z < b.getMinimum().z ) tile = tile -> _getNeighbor( TerrainTile::NORTH ); else if ( pt.z > b.getMaximum().z ) tile = tile -> _getNeighbor( TerrainTile::SOUTH ); else return tile; } return 0; }
/** Returns true is the box will fit in a child. */ bool Octree::_isTwiceSize( const AxisAlignedBox &box ) const { return ( ( box.getMaximum().x - box.getMinimum().x ) <= ( mBox.getMaximum().x - mBox.getMinimum().x ) / 2 ) && ( ( box.getMaximum().y - box.getMinimum().y ) <= ( mBox.getMaximum().y - mBox.getMinimum().y ) / 2 ) && ( ( box.getMaximum().z - box.getMinimum().z ) <= ( mBox.getMaximum().z - mBox.getMinimum().z ) / 2 ) ; }
// ------------------------------------------------------------------------ static bool isBoundOkForMcGuire(const AxisAlignedBox& lightCapBounds, const Ogre::Vector3& lightPosition) { // If light position is inside light cap bound then extrusion could be in opposite directions // and McGuire cap could intersect near clip plane of camera frustum without being noticed if(lightCapBounds.contains(lightPosition)) return false; // If angular size of object is too high then extrusion could be in almost opposite directions, // interpolated points would be extruded by shorter distance, and strange geometry of McGuire cap // could be visible even for well tesselated meshes. As a heuristic we will avoid McGuire cap if // angular size is larger than 60 degrees - it guarantees that interpolated points would be // extruded by at least cos(60deg/2) ~ 86% of the original extrusion distance. if(lightCapBounds.getHalfSize().length() / (lightCapBounds.getCenter() - lightPosition).length() > 0.5) // if boundingSphereAngularSize > 60deg { // Calculate angular size one more time using edge corners angular distance comparision, // Determine lit sides of the bound, store in mask enum { L = 1, R = 2, B = 4, T = 8, F = 16, N = 32 }; // left, right, bottom, top, far, near unsigned lightSidesMask = (lightPosition.x < lightCapBounds.getMinimum().x ? L : 0) | // left (lightPosition.x > lightCapBounds.getMaximum().x ? R : 0) | // right (lightPosition.y < lightCapBounds.getMinimum().y ? B : 0) | // bottom (lightPosition.y > lightCapBounds.getMaximum().y ? T : 0) | // top (lightPosition.z < lightCapBounds.getMinimum().z ? F : 0) | // far (lightPosition.z > lightCapBounds.getMaximum().z ? N : 0); // near // find corners on lit/unlit edge (should not be more than 6 simultaneously, but better be safe than sorry) Ogre::Vector3 edgeCorners[8]; unsigned edgeCornersCount = 0; std::pair<unsigned, AxisAlignedBox::CornerEnum> cornerMap[8] = { { F|L|B, AxisAlignedBox::FAR_LEFT_BOTTOM }, { F|R|B, AxisAlignedBox::FAR_RIGHT_BOTTOM }, { F|L|T, AxisAlignedBox::FAR_LEFT_TOP }, { F|R|T, AxisAlignedBox::FAR_RIGHT_TOP }, { N|L|B, AxisAlignedBox::NEAR_LEFT_BOTTOM },{ N|R|B, AxisAlignedBox::NEAR_RIGHT_BOTTOM }, { N|L|T, AxisAlignedBox::NEAR_LEFT_TOP }, { N|R|T, AxisAlignedBox::NEAR_RIGHT_TOP }}; for(auto& c : cornerMap) if((lightSidesMask & c.first) != 0 && (lightSidesMask & c.first) != c.first) // if adjacent sides not all lit or all unlit edgeCorners[edgeCornersCount++] = lightCapBounds.getCorner(c.second); // find max angular size in range [0..pi] by finding min cos of angular size, range [1..-1] Real cosAngle = 1.0; for(unsigned i0 = 0; i0 + 1 < edgeCornersCount; ++i0) for(unsigned i1 = i0 + 1; i1 < edgeCornersCount; ++i1) { // 4~6 edge corners, 6~15 angular distance calculations Vector3 a = (edgeCorners[i0] - lightPosition).normalisedCopy(); Vector3 b = (edgeCorners[i1] - lightPosition).normalisedCopy(); Real cosAB = a.dotProduct(b); if(cosAngle > cosAB) cosAngle = cosAB; } if(cosAngle < 0.5) // angularSize > 60 degrees return false; } return true; }
/** Since we are loose, only check the center. */ bool OctreeNode::_isIn( AxisAlignedBox &box ) { // Always fail if not in the scene graph or box is null if (!mIsInSceneGraph || box.isNull()) return false; // Always succeed if AABB is infinite if (box.isInfinite()) return true; Vector3 center = mWorldAABB.getMaximum().midPoint( mWorldAABB.getMinimum() ); Vector3 bmin = box.getMinimum(); Vector3 bmax = box.getMaximum(); bool centre = ( bmax > center && bmin < center ); if (!centre) return false; // Even if covering the centre line, need to make sure this BB is not large // enough to require being moved up into parent. When added, bboxes would // end up in parent due to cascade but when updating need to deal with // bbox growing too large for this child Vector3 octreeSize = bmax - bmin; Vector3 nodeSize = mWorldAABB.getMaximum() - mWorldAABB.getMinimum(); return nodeSize < octreeSize; }
/** It's assumed the the given box has already been proven to fit into * a child. Since it's a loose octree, only the centers need to be * compared to find the appropriate node. */ void Octree::_getChildIndexes( const AxisAlignedBox &box, int *x, int *y, int *z ) const { Vector3 max = mBox.getMaximum(); Vector3 min = box.getMinimum(); Vector3 center = mBox.getMaximum().midPoint( mBox.getMinimum() ); Vector3 ncenter = box.getMaximum().midPoint( box.getMinimum() ); if ( ncenter.x > center.x ) * x = 1; else *x = 0; if ( ncenter.y > center.y ) * y = 1; else *y = 0; if ( ncenter.z > center.z ) * z = 1; else *z = 0; }
//----------------------------------------------------------------------- bool Math::intersects(const Sphere& sphere, const AxisAlignedBox& box) { if (box.isNull()) return false; if (box.isInfinite()) return true; // Use splitting planes const Vector3& center = sphere.getCenter(); Real radius = sphere.getRadius(); const Vector3& min = box.getMinimum(); const Vector3& max = box.getMaximum(); // Arvo's algorithm Real s, d = 0; for (int i = 0; i < 3; ++i) { if (center.ptr()[i] < min.ptr()[i]) { s = center.ptr()[i] - min.ptr()[i]; d += s * s; } else if(center.ptr()[i] > max.ptr()[i]) { s = center.ptr()[i] - max.ptr()[i]; d += s * s; } } return d <= radius * radius; }
ParaEngine::AxisAlignedBox AxisAlignedBox::intersection(const AxisAlignedBox& b2) const { if (this->isNull() || b2.isNull()) { return AxisAlignedBox(); } else if (this->isInfinite()) { return b2; } else if (b2.isInfinite()) { return *this; } Vector3 intMin = mMinimum; Vector3 intMax = mMaximum; intMin.makeCeil(b2.getMinimum()); intMax.makeFloor(b2.getMaximum()); // Check intersection isn't null if (intMin.x < intMax.x && intMin.y < intMax.y && intMin.z < intMax.z) { return AxisAlignedBox(intMin, intMax); } return AxisAlignedBox(); }
/* Find the best (smallest) zone that contains a point */ PCZone * PCZSceneManager::findZoneForPoint(Vector3 & point) { PCZone * zone; PCZone * bestZone = mDefaultZone; Real bestVolume = Ogre::Math::POS_INFINITY; ZoneMap::iterator zit = mZones.begin(); while ( zit != mZones.end() ) { zone = zit->second; AxisAlignedBox aabb; zone->getAABB(aabb); SceneNode * enclosureNode = zone->getEnclosureNode(); if (enclosureNode != 0) { // since this is the "local" AABB, add in world translation of the enclosure node aabb.setMinimum(aabb.getMinimum() + enclosureNode->_getDerivedPosition()); aabb.setMaximum(aabb.getMaximum() + enclosureNode->_getDerivedPosition()); } if (aabb.contains(point)) { if (aabb.volume() < bestVolume) { // this zone is "smaller" than the current best zone, so make it // the new best zone bestZone = zone; bestVolume = aabb.volume(); } } // proceed to next zone in the list ++zit; } return bestZone; }
void OctreeSceneManager::resize( const AxisAlignedBox &box ) { list< SceneNode * >::type nodes; list< SceneNode * >::type ::iterator it; _findNodes( mOctree->mBox, nodes, 0, true, mOctree ); OGRE_DELETE mOctree; mOctree = OGRE_NEW Octree( 0 ); mOctree->mBox = box; const Vector3 &min = box.getMinimum(); const Vector3 &max = box.getMaximum(); mOctree->mHalfSize = ( max - min ) * 0.5f; it = nodes.begin(); while ( it != nodes.end() ) { OctreeNode * on = static_cast < OctreeNode * > ( *it ); on -> setOctant( 0 ); _updateOctreeNode( on ); ++it; } }
TEST_FIXTURE(ScriptingTestEnvironment, ConvertFiniteAxisAlignedBoxFromJavaScript) { HandleScope handle_scope; Handle<Value> result = pScriptingManager->execute("import_module('Athena.Math'); new Athena.Math.AxisAlignedBox(1, 2, 3, 4, 5, 6);"); AxisAlignedBox aab = fromJSAxisAlignedBox(result); CHECK(aab.isFinite()); CHECK_CLOSE(1.0f, aab.getMinimum().x, 1e-6f); CHECK_CLOSE(2.0f, aab.getMinimum().y, 1e-6f); CHECK_CLOSE(3.0f, aab.getMinimum().z, 1e-6f); CHECK_CLOSE(4.0f, aab.getMaximum().x, 1e-6f); CHECK_CLOSE(5.0f, aab.getMaximum().y, 1e-6f); CHECK_CLOSE(6.0f, aab.getMaximum().z, 1e-6f); }
void Actor::setHighlighted(bool highlight) { if (highlight != mHighlighted) { //getControlledObject()->setHighlighted(highlight); mHighlighted = highlight; } if (mHighlighted && mDescription == NULL) { if (mSceneNode != NULL) { mDescription = new MovableText(mName + "_desc", mName); mDescription->showOnTop(true); mDescription->setAlignment(MovableText::ALIGN_CENTER); if (mActorControlledObject && mActorControlledObject->isMeshObject()) { MeshObject* mo = static_cast<MeshObject*>(mActorControlledObject); AxisAlignedBox aabb = mo->getDefaultSize(); mDescription->setPositionOffset(Vector3(0, aabb.getMaximum().y * 1.1, 0)); } mSceneNode->attachObject(mDescription); } } else if (mDescription) { mDescription->setVisible(highlight); } }
/** Checks how the box intersects with the sphere. */ Intersection intersect( const Sphere &one, const AxisAlignedBox &two ) { OctreeSceneManager::intersect_call++; // 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; } }
String StringConv::axisAlignedBoxToString(const AxisAlignedBox& _val, size_t _precision) { String r; r += toString(_val.getMinimum(), _precision); r += " "; r += toString(_val.getMaximum(), _precision); return r; }
// ------------------------------------------------------------------------ void ShadowCaster::extrudeBounds(AxisAlignedBox& box, const Vector4& light, Real extrudeDist) const { Vector3 extrusionDir; if (light.w == 0) { // Parallel projection guarantees min/max relationship remains the same extrusionDir.x = -light.x; extrusionDir.y = -light.y; extrusionDir.z = -light.z; extrusionDir.normalise(); extrusionDir *= extrudeDist; box.setExtents(box.getMinimum() + extrusionDir, box.getMaximum() + extrusionDir); } else { Vector3 vmin, vmax; Vector3 corner, tmp; #define __EXTRUDE_POINT() \ { \ extrusionDir.x = corner.x - light.x; \ extrusionDir.y = corner.y - light.y; \ extrusionDir.z = corner.z - light.z; \ extrusionDir.normalise(); \ extrusionDir *= extrudeDist; \ tmp = corner + extrusionDir; \ } corner = box.getMinimum(); __EXTRUDE_POINT(); vmin = vmax = tmp; corner.x = box.getMaximum().x; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); corner.y = box.getMaximum().y; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); corner.x = box.getMinimum().x; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); corner.z = box.getMaximum().z; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); corner.x = box.getMaximum().x; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); corner.y = box.getMinimum().y; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); corner.x = box.getMinimum().x; __EXTRUDE_POINT(); vmin.makeFloor(tmp); vmax.makeCeil(tmp); #undef __EXTRUDE_POINT box.setExtents(vmin, vmax); } }
void TerrainInfo::setExtents(const AxisAlignedBox& extents) { if (mWidth == 0) OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "You must set a heightmap first.", "TerrainInfo::setExtents"); mOffset = extents.getMinimum(); mScale = extents.getMaximum() - extents.getMinimum(); mScale.x /= mWidth; mScale.z /= mHeight; }
void DebugDisplay::drawCube( AxisAlignedBox bbox ) { oht_assert_threadmodel(ThrMdl_Main); ManualObject * pManObj = _pSceneManager->createManualObject(); rollbackTransforms(bbox); pManObj->begin(getCurrentMaterial(), RenderOperation::OT_LINE_LIST); const Vector3 m0 = bbox.getMinimum(), mN = bbox.getMaximum(); pManObj->position(m0.x, m0.y, m0.z); pManObj->position(mN.x, m0.y, m0.z); pManObj->position(m0.x, m0.y, m0.z); pManObj->position(m0.x, mN.y, m0.z); pManObj->position(m0.x, m0.y, m0.z); pManObj->position(m0.x, m0.y, mN.z); pManObj->position(mN.x, mN.y, m0.z); pManObj->position(mN.x, m0.y, m0.z); pManObj->position(mN.x, mN.y, m0.z); pManObj->position(m0.x, mN.y, m0.z); pManObj->position(mN.x, mN.y, m0.z); pManObj->position(mN.x, mN.y, mN.z); pManObj->position(m0.x, mN.y, mN.z); pManObj->position(m0.x, mN.y, m0.z); pManObj->position(m0.x, mN.y, mN.z); pManObj->position(m0.x, m0.y, mN.z); pManObj->position(m0.x, mN.y, mN.z); pManObj->position(mN.x, mN.y, mN.z); pManObj->position(mN.x, m0.y, mN.z); pManObj->position(m0.x, m0.y, mN.z); pManObj->position(mN.x, m0.y, mN.z); pManObj->position(mN.x, m0.y, m0.z); pManObj->position(mN.x, m0.y, mN.z); pManObj->position(mN.x, mN.y, mN.z); pManObj->end(); _pScNode->attachObject(pManObj); }
std::pair<bool, Vector3> TerrainInfo::rayIntersects(const Ray& ray) const { AxisAlignedBox box = getExtents(); Vector3 point = ray.getOrigin(); Vector3 dir = ray.getDirection(); // first, does the ray start from inside the terrain extents? if (!box.contains(point)) { // not inside the box, so let's see if we are actually // colliding with it pair<bool, Real> res = ray.intersects(box); if (!res.first) return make_pair(false, Vector3::ZERO); // update point to the collision position point = ray.getPoint(res.second); } // now move along the ray until we intersect or leave the bounding box while (true) { // have we arived at or under the terrain height? // note that this approach means that ray queries from below won't work // correctly, but then again, that shouldn't be a usual case... float height = getHeightAt(point.x, point.z); if (point.y <= height) { point.y = height; return make_pair(true, point); } // move further... point += dir; // check if we are still inside the boundaries if (point.x < box.getMinimum().x || point.z < box.getMinimum().z || point.x > box.getMaximum().x || point.z > box.getMaximum().z) return make_pair(false, Vector3::ZERO); } }
/** Returns true is the box will fit in a child. */ bool PagingLandScapeOctree::_isNotCrossingAxes(const AxisAlignedBox &box) const { const Vector3 &boxMin = box.getMinimum(); const Vector3 &boxMax = box.getMaximum(); const Vector3 octCullCenter = mCullBox.getMinimum() + mCullHalfSize; return !((boxMin.x <= octCullCenter.x && octCullCenter.x <= boxMax.x) || (boxMin.y <= octCullCenter.y && octCullCenter.y <= boxMax.y) || (boxMin.z <= octCullCenter.z && octCullCenter.z <= boxMax.z)); }
//--------------------------------------------------------------------- Real Math::boundingRadiusFromAABB(const AxisAlignedBox& aabb) { Vector3 max = aabb.getMaximum(); Vector3 min = aabb.getMinimum(); Vector3 magnitude = max; magnitude.makeCeil(-max); magnitude.makeCeil(min); magnitude.makeCeil(-min); return magnitude.length(); }
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(); } }
// ------------------------------------------------------------------------- CollisionsWorld::CollisionsWorld(SceneManager *scn, const AxisAlignedBox &bounds, bool init, bool set32bitsAxisSweep, unsigned int maxHandles): mScnMgr(scn), mBounds(bounds), mShowDebugShapes(false), mShowDebugContactPoints(false), mDebugContactPoints(0), mDebugDrawer(0) { mDispatcher = new btCollisionDispatcher(&mDefaultCollisionConfiguration); if (set32bitsAxisSweep) { mBroadphase = new bt32BitAxisSweep3( OgreBtConverter::to(bounds.getMinimum()), OgreBtConverter::to(bounds.getMaximum()), maxHandles); } else { if(maxHandles > USHRT_MAX) { Ogre::String logNote("Exceeded the maximum number of handles for btAxisSweep3. Max = USHRT_MAX. Resetting maxHandles to USHRT_MAX in OgreBulletCollisions::CollisionsWorld::CollisionsWorld()."); Ogre::LogManager::getSingleton().logMessage(logNote); maxHandles = USHRT_MAX; } mBroadphase = new btAxisSweep3( OgreBtConverter::to(bounds.getMinimum()), OgreBtConverter::to(bounds.getMaximum()), static_cast<unsigned short>(maxHandles)); } // if not called by a inherited class if (init) { mWorld = new btCollisionWorld(mDispatcher, mBroadphase, &mDefaultCollisionConfiguration); btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(mWorld->getDispatcher()); btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); } }
/** Checks how the second box intersects with the first. */ Intersection intersect( const AxisAlignedBox &one, const AxisAlignedBox &two ) { OctreeSceneManager::intersect_call++; // Null box? if (one.isNull() || two.isNull()) return OUTSIDE; if (one.isInfinite()) return INSIDE; if (two.isInfinite()) return INTERSECT; const Vector3& insideMin = two.getMinimum(); const Vector3& insideMax = two.getMaximum(); const Vector3& outsideMin = one.getMinimum(); const Vector3& outsideMax = one.getMaximum(); if ( insideMax.x < outsideMin.x || insideMax.y < outsideMin.y || insideMax.z < outsideMin.z || insideMin.x > outsideMax.x || insideMin.y > outsideMax.y || insideMin.z > outsideMax.z ) { return OUTSIDE; } bool full = ( insideMin.x > outsideMin.x && insideMin.y > outsideMin.y && insideMin.z > outsideMin.z && insideMax.x < outsideMax.x && insideMax.y < outsideMax.y && insideMax.z < outsideMax.z ); if ( full ) return INSIDE; else return INTERSECT; }
void PhysicsManager::addLevelGeometry( Ogre::Entity* levelEntity, const std::vector<OgreNewt::CollisionPtr> &collisions) { RlAssert1(levelEntity); RlAssert1(levelEntity->getParentSceneNode()); SceneNode* node = levelEntity->getParentSceneNode(); //Level entity has to be attached to a scene node. // try one compound collision for the entity if there are several collisions OgreNewt::CollisionPtr collision; switch( collisions.size() ) { case 0: break; case 1: collision = collisions[0]; break; default: collision = OgreNewt::CollisionPtr(new OgreNewt::CollisionPrimitives::CompoundCollision(mWorld, collisions, 0)); break; } if( collision ) { OgreNewt::Body* body = new OgreNewt::Body(mWorld, collision ); body->attachNode(node); body->setPositionOrientation(node->_getDerivedPosition(), node->_getDerivedOrientation()); body->setMaterialGroupID(getMaterialID("level")); mLevelBodiesQuadTree.add(body); //mLevelBodies.push_back(body); } // adjust worldAABB Vector3 minV(mWorldAABB.getMinimum()); Vector3 maxV(mWorldAABB.getMaximum()); AxisAlignedBox entityAABB = levelEntity->getWorldBoundingBox(true); minV.makeFloor(entityAABB.getMinimum()); maxV.makeCeil(entityAABB.getMaximum()); mWorldAABB.setMinimum(minV - Vector3(50, 50, 50)); mWorldAABB.setMaximum(maxV + Vector3(50, 50, 50)); mWorld->setWorldSize(mWorldAABB); }
DiMeshPtr ModelConverter::WriteMesh( const Ogre::Mesh* pMesh ) { DiMeshPtr model = Demi::DiAssetManager::GetInstancePtr( )->CreateOrReplaceAsset<DiMesh>(pMesh->getName().c_str()); // write AABB AxisAlignedBox aabb = pMesh->getBounds(); DiAABB maabb; maabb.SetExtents(aabb.getMinimum().x,aabb.getMinimum().y,aabb.getMinimum().z, aabb.getMaximum().x,aabb.getMaximum().y,aabb.getMaximum().z); model->SetBounds(maabb); // write sub meshes for (int i = 0; i < pMesh->getNumSubMeshes(); ++i) { DiSubMesh* sub = model->CreateSubMesh(); LogManager::getSingleton().logMessage("Writing submesh..."); WriteSubMesh(sub, pMesh->getSubMesh(i)); LogManager::getSingleton().logMessage("Submesh exported."); } return model; }
/* get the aabb of the zone - default implementation uses the enclosure node, but there are other perhaps better ways */ void PCZone::getAABB(AxisAlignedBox & aabb) { // if there is no node, just return a null box if (mEnclosureNode == 0) { aabb.setNull(); } else { aabb = mEnclosureNode->_getWorldAABB(); // since this is the "local" AABB, subtract out any translations aabb.setMinimum(aabb.getMinimum() - mEnclosureNode->_getDerivedPosition()); aabb.setMaximum(aabb.getMaximum() - mEnclosureNode->_getDerivedPosition()); } return; }
void SplineRoad::AddMesh(MeshPtr mesh, String sMesh, const AxisAlignedBox& aabox, Entity** pEnt, SceneNode** pNode, String sEnd) { mesh->_setBounds(aabox); mesh->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0); mesh->load(); unsigned short src, dest; if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) mesh->buildTangentVectors(VES_TANGENT, src, dest); *pEnt = mSceneMgr->createEntity("rd.ent"+sEnd, sMesh); *pNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("rd.node"+sEnd); (*pNode)->attachObject(*pEnt); (*pEnt)->setVisible(false); (*pEnt)->setCastShadows(false); (*pEnt)->setVisibilityFlags(RV_Road); }
//----------------------------------------------------------------------- void ConvexBody::clip(const AxisAlignedBox& aab) { // only process finite boxes if (!aab.isFinite()) return; // ordering of the AAB points: // 1-----2 // /| /| // / | / | // 5-----4 | // | 0--|--3 // | / | / // |/ |/ // 6-----7 const Vector3& min = aab.getMinimum(); const Vector3& max = aab.getMaximum(); // clip object for each plane of the AAB Plane p; // front p.redefine(Vector3::UNIT_Z, max); clip(p); // back p.redefine(Vector3::NEGATIVE_UNIT_Z, min); clip(p); // left p.redefine(Vector3::NEGATIVE_UNIT_X, min); clip(p); // right p.redefine(Vector3::UNIT_X, max); clip(p); // bottom p.redefine(Vector3::NEGATIVE_UNIT_Y, min); clip(p); // top p.redefine(Vector3::UNIT_Y, max); clip(p); }
//------------------------------------------------------------------------------ void SegmentedDynamicLightManager::calculateLightBounds(const Light* i_Light, LightData& o_LightData) { Real lightRange = i_Light->getAttenuationRange(); const Vector3& lightPosition = i_Light->getDerivedPosition(true); AxisAlignedBox boundBox(lightPosition - lightRange, lightPosition + lightRange); if (i_Light->getType() == Light::LT_SPOTLIGHT) { static const Radian c_RadianPI(Math::PI); static const Radian c_RadianZero(0); Radian halfOuterAngle = i_Light->getSpotlightOuterAngle() * 0.5; Real boxOffset = Math::Sin(halfOuterAngle) * lightRange; const Vector3& lightDirection = i_Light->getDerivedDirection(); Radian dirUpAngle(fabs(Math::ASin(lightDirection.y).valueRadians())); Radian dirUpMaxAngle = std::max<Radian>(dirUpAngle - halfOuterAngle,c_RadianZero); Radian dirUpMinAngle = std::min<Radian>(dirUpAngle + halfOuterAngle, c_RadianPI); Real dirDistanceMax = Math::Cos(dirUpMaxAngle) * lightRange; Real dirDistanceMin = Math::Cos(dirUpMinAngle) * lightRange; Vector3 flatDirection(lightDirection.x, 0, lightDirection.z); Real flatDirLen = flatDirection.length(); if (flatDirLen != 0) flatDirection /= flatDirLen; else flatDirection = Vector3(1,0,0); Vector3 flatDirectionPerp(flatDirection.z, 0, -flatDirection.x); flatDirectionPerp *= boxOffset; Vector3 flatPositionMax = lightPosition + dirDistanceMax * flatDirection; Vector3 flatPositionMin = lightPosition + dirDistanceMin * flatDirection; AxisAlignedBox spotBox; spotBox.merge(flatPositionMax + flatDirectionPerp); spotBox.merge(flatPositionMax - flatDirectionPerp); spotBox.merge(flatPositionMin + flatDirectionPerp); spotBox.merge(flatPositionMin - flatDirectionPerp); spotBox.merge(lightPosition); boundBox.getMaximum().makeFloor(spotBox.getMaximum()); boundBox.getMinimum().makeCeil(spotBox.getMinimum()); } o_LightData.setBounds(boundBox); }
void OctreeSceneManager::init( AxisAlignedBox &box, int depth ) { delete mSceneRoot; //get rid of old root. // -- Changes by Steve // Don't do it this way, it will add it to the mSceneNodes which we don't want //mSceneRoot = createSceneNode( "SceneRoot" ); mSceneRoot = new OctreeNode( this, "SceneRoot" ); mSceneRoot->_notifyRootNode(); // -- End changes by Steve if ( mOctree != 0 ) delete mOctree; mOctree = new Octree( 0 ); mMaxDepth = depth; mBox = box; mOctree -> mBox = box; Vector3 min = box.getMinimum(); Vector3 max = box.getMaximum(); mOctree -> mHalfSize = ( max - min ) / 2; mShowBoxes = false; mNumObjects = 0; Vector3 v( 1.5, 1.5, 1.5 ); mScaleFactor.setScale( v ); // setDisplaySceneNodes( true ); // setShowBoxes( true ); // //mSceneRoot isn't put into the octree since it has no volume. }