void RenderBoxScene::updateViewport() { if (mCanvas->getWidth() <= 1 || mCanvas->getHeight() <= 1) return; if (mEntity != nullptr && mCamera != nullptr) { mCamera->setAspectRatio((float)mCanvas->getWidth() / (float)mCanvas->getHeight()); AxisAlignedBox box; const Vector3& dpos = mEntity->getParentSceneNode()->_getDerivedPosition(); box.merge(mEntity->getBoundingBox().getMinimum() + dpos); box.merge(mEntity->getBoundingBox().getMaximum() + dpos); if (box.isNull()) return; Vector3 vec = box.getSize(); float width = sqrt(vec.x * vec.x + vec.z * vec.z), height = vec.y; float len2 = width / mCamera->getAspectRatio(), len1 = height; if (len1 < len2) len1 = len2; len1 /= 0.86; // [sqrt(3)/2] for 60 degrees field of view Vector3 pos = box.getCenter(); pos.z += vec.z / 2 + len1 + 1/* min dist*/; pos += Vector3(0, height * 0.9f/* pitch*/, len1 * 0.1f); pos *= 0.85f; //* closer Vector3 look = Vector3(0, box.getCenter().y * 0.8f, 0); mCameraNode->setPosition(pos); mCameraNode->lookAt(look, Node::TS_WORLD); } }
OctreeCamera::Visibility OctreeCamera::getVisibility( const AxisAlignedBox &bound ) { // Null boxes always invisible if ( bound.isNull() ) return NONE; // Get centre of the box Vector3 centre = bound.getCenter(); // Get the half-size of the box Vector3 halfSize = bound.getHalfSize(); bool all_inside = true; for ( int plane = 0; plane < 6; ++plane ) { // Skip far plane if infinite view frustum if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0) continue; // This updates frustum planes and deals with cull frustum Plane::Side side = getFrustumPlane(plane).getSide(centre, halfSize); if(side == Plane::NEGATIVE_SIDE) return NONE; // We can't return now as the box could be later on the negative side of a plane. if(side == Plane::BOTH_SIDE) all_inside = false; } if ( all_inside ) return FULL; else return PARTIAL; }
//----------------------------------------------------------------------- bool Frustum::IsVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) { // Null boxes always invisible if (bound.isNull()) return false; // Infinite boxes always visible if (bound.isInfinite()) return true; // Make any pending updates to the calculated frustum planes _UpdateFrustumPlanes(); // Get centre of the box Vector3f centre = bound.getCenter(); // Get the half-size of the box Vector3f halfSize = bound.getHalfSize(); // For each plane, see if all points are on the negative side // If so, object is not visible for (int plane = 0; plane < 6; ++plane) { // Skip far plane if infinite view frustum if (plane == FRUSTUM_PLANE_FAR && m_farDist == 0) continue; Plane::Side side = m_frustumPlanes[plane].getSide(centre, halfSize); if (side == Plane::NEGATIVE_SIDE) { // ALL corners on negative side therefore out of view if (culledBy) *culledBy = (FrustumPlane)plane; return false; } } return true; }
//----------------------------------------------------------------------- Plane::Side Plane::getSide (const AxisAlignedBox& box) const { if (box.isNull()) return NO_SIDE; if (box.isInfinite()) return BOTH_SIDE; return getSide(box.getCenter(), box.getHalfSize()); }
// ------------------------------------------------------------------------ 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; }
/* A 'more detailed' check for visibility of an AAB. This function returns none, partial, or full for visibility of the box. This is useful for stuff like Octree leaf culling */ PCZFrustum::Visibility PCZFrustum::getVisibility( const AxisAlignedBox &bound ) { // Null boxes always invisible if ( bound.isNull() ) return NONE; // Get centre of the box Vector3 centre = bound.getCenter(); // Get the half-size of the box Vector3 halfSize = bound.getHalfSize(); bool all_inside = true; // Check originplane if told to if (mUseOriginPlane) { Plane::Side side = mOriginPlane.getSide(centre, halfSize); if (side == Plane::NEGATIVE_SIDE) { return NONE; } // We can't return now as the box could be later on the negative side of another plane. if(side == Plane::BOTH_SIDE) { all_inside = false; } } // For each active culling plane, see if the entire aabb is on the negative side // If so, object is not visible PCPlaneList::iterator pit = mActiveCullingPlanes.begin(); while ( pit != mActiveCullingPlanes.end() ) { PCPlane * plane = *pit; Plane::Side xside = plane->getSide(centre, halfSize); if(xside == Plane::NEGATIVE_SIDE) { return NONE; } // We can't return now as the box could be later on the negative side of a plane. if(xside == Plane::BOTH_SIDE) { all_inside = false; break; } pit++; } if ( all_inside ) return FULL; else return PARTIAL; }
static Sphere aabbToSphere(const AxisAlignedBox& aabb) { if (!aabb.isNull()) { // Compute sphere float radius = -1.0f; const Vector3* corners = aabb.getAllCorners(); for(unsigned int i = 0; i < 6; ++i) { float distance = corners[i].distance(aabb.getCenter()); if (distance>radius) { radius = distance; } } return Sphere(aabb.getCenter(), radius); } else return Sphere(Vector3::ZERO, -1.0f); }
virtual bool processUnbufferedKeyInput(const FrameEvent& evt) { if(mKeyboard->isKeyDown(OIS::KC_V)) { _sceneRoot->_update(true, true); _sceneRoot->_updateBounds(); std::cout << "Frame camera" << std::endl; AxisAlignedBox box = _sceneRoot->_getWorldAABB(); std::cout << "Center: " << box.getCenter() << std::endl; } return ExampleFrameListener::processUnbufferedKeyInput(evt); }
void DebugDraw::draw(const AxisAlignedBox& axisAlignedBox, const Color& color) const { if (!LineGeometryManager::getInstance()->getLineGeometry("Square").get()) { return; } Matrix4x4 modelMatrix; // Front modelMatrix.identity(); modelMatrix.translate(axisAlignedBox.getCenter().getX(), axisAlignedBox.getCenter().getY(), axisAlignedBox.getCenter().getZ()); modelMatrix.translate(0.0f, 0.0f, axisAlignedBox.getHalfDepth()); modelMatrix.rotateRzRyRx(0.0f, 0.0f, 0.0f); modelMatrix.scale(axisAlignedBox.getHalfWidth(), axisAlignedBox.getHalfHeight(), 0.0f); LineGeometryManager::getInstance()->getLineGeometry("Square")->draw(modelMatrix, color); // Back modelMatrix.identity(); modelMatrix.translate(axisAlignedBox.getCenter().getX(), axisAlignedBox.getCenter().getY(), axisAlignedBox.getCenter().getZ()); modelMatrix.translate(0.0f, 0.0f, -axisAlignedBox.getHalfDepth()); modelMatrix.rotateRzRyRx(0.0f, 0.0f, 0.0f); modelMatrix.scale(axisAlignedBox.getHalfWidth(), axisAlignedBox.getHalfHeight(), 0.0f); LineGeometryManager::getInstance()->getLineGeometry("Square")->draw(modelMatrix, color); // Top modelMatrix.identity(); modelMatrix.translate(axisAlignedBox.getCenter().getX(), axisAlignedBox.getCenter().getY(), axisAlignedBox.getCenter().getZ()); modelMatrix.translate(0.0f, axisAlignedBox.getHalfHeight(), 0.0f); modelMatrix.rotateRzRyRx(0.0f, 0.0f, 90.0f); modelMatrix.scale(axisAlignedBox.getHalfWidth(), axisAlignedBox.getHalfDepth(), 0.0f); LineGeometryManager::getInstance()->getLineGeometry("Square")->draw(modelMatrix, color); // Bottom modelMatrix.identity(); modelMatrix.translate(axisAlignedBox.getCenter().getX(), axisAlignedBox.getCenter().getY(), axisAlignedBox.getCenter().getZ()); modelMatrix.translate(0.0f, -axisAlignedBox.getHalfHeight(), 0.0f); modelMatrix.rotateRzRyRx(0.0f, 0.0f, 90.0f); modelMatrix.scale(axisAlignedBox.getHalfWidth(), axisAlignedBox.getHalfDepth(), 0.0f); LineGeometryManager::getInstance()->getLineGeometry("Square")->draw(modelMatrix, color); // Left and Right not needed }
void SurveyMapManager::init() { AxisAlignedBox aab = App::GetSimTerrain()->getTerrainCollisionAAB(); Vector3 terrain_size = App::GetSimTerrain()->getMaxTerrainSize(); bool use_aab = App::GetSimTerrain()->isFlat() && std::min(aab.getSize().x, aab.getSize().z) > 50.0f; if (terrain_size.isZeroLength() || use_aab && (aab.getSize().length() < terrain_size.length())) { terrain_size = aab.getSize(); terrain_size.y = aab.getMaximum().y; Vector3 offset = aab.getCenter() - terrain_size / 2; mMapCenterOffset = Vector2(offset.x, offset.z); } mTerrainSize = Vector2(terrain_size.x, terrain_size.z); mPlayerPosition = mTerrainSize / 2; mMapCenter = mTerrainSize / 2; mMapSize = mTerrainSize; ConfigOptionMap ropts = App::GetOgreSubsystem()->GetOgreRoot()->getRenderSystem()->getConfigOptions(); int resolution = StringConverter::parseInt(StringUtil::split(ropts["Video Mode"].currentValue, " x ")[0], 1024); int fsaa = StringConverter::parseInt(ropts["FSAA"].currentValue, 0); int res = std::pow(2, std::floor(std::log2(resolution))); mMapTextureCreatorStatic = std::unique_ptr<SurveyMapTextureCreator>(new SurveyMapTextureCreator(terrain_size.y)); mMapTextureCreatorStatic->init(res, fsaa); mMapTextureCreatorStatic->update(mMapCenter + mMapCenterOffset, mMapSize); // TODO: Find out how to zoom into the static texture instead mMapTextureCreatorDynamic = std::unique_ptr<SurveyMapTextureCreator>(new SurveyMapTextureCreator(terrain_size.y)); mMapTextureCreatorDynamic->init(res / 4, fsaa); mMapTextureCreatorDynamic->update(mMapCenter + mMapCenterOffset, mMapSize); mMapTexture->eventMouseSetFocus += MyGUI::newDelegate(this, &SurveyMapManager::setFocus); mMapTexture->eventMouseLostFocus += MyGUI::newDelegate(this, &SurveyMapManager::lostFocus); mMapTexture->eventMouseMove += MyGUI::newDelegate(this, &SurveyMapManager::mouseMove); mMapTexture->eventMouseButtonPressed += MyGUI::newDelegate(this, &SurveyMapManager::mousePressed); mCursorEntity = createMapEntity("other"); mCursorEntity->setVisibility(false); mCursorEntity->setCaption(_L("Teleport")); }
Actor::Actor(const Ogre::String& name) { _strName = name; _AnimSpeed = 1.0; _pCurAnim = 0; _bPaused = false; _bShowAxes = false; _bShowBone = false; _bShowBoundingBox = false; _axesBoneTagPoint = 0; //the body _pBodyEntity = OgreFramework::getSingletonPtr()->m_pSceneMgr->createEntity(_strName, _strName); _pBodySceneNode = OgreFramework::getSingletonPtr()->m_pSceneMgr->getRootSceneNode()->createChildSceneNode(_strName); _pBodySceneNode->attachObject(_pBodyEntity); //the body axes String axesName = _strName + "_" + "axes"; _axesEntity = OgreFramework::getSingletonPtr()->m_pSceneMgr->createEntity(axesName, "axes.mesh"); SceneNode* pAxesNode = _pBodySceneNode->createChildSceneNode(axesName); pAxesNode->attachObject(_axesEntity); _axesEntity->setVisible(_bShowAxes); //the bone axes axesName = _strName + "_Bone_" + "axes"; _axesBoneEntity = OgreFramework::getSingletonPtr()->m_pSceneMgr->createEntity(axesName, "axes.mesh"); AxisAlignedBox aabb = _pBodyEntity->getBoundingBox(); _vInitCenter = aabb.getCenter(); _fVolumeSize = aabb.getSize().length(); _scaleAxes = _fVolumeSize * 0.01; //for Axes mesh size is about 13, i want the axes to be 1/10 of the mesh pAxesNode->setScale(_scaleAxes, _scaleAxes, _scaleAxes); AddBoneVisualizer(); OgreFramework::getSingletonPtr()->AddActor(this); }
bool PCZFrustum::isVisible( const AxisAlignedBox & bound) const { // Null boxes are always invisible if (bound.isNull()) return false; // Infinite boxes are always visible if (bound.isInfinite()) return true; // Get centre of the box Vector3 centre = bound.getCenter(); // Get the half-size of the box Vector3 halfSize = bound.getHalfSize(); // Check originplane if told to if (mUseOriginPlane) { Plane::Side side = mOriginPlane.getSide(centre, halfSize); if (side == Plane::NEGATIVE_SIDE) { return false; } } // For each extra active culling plane, see if the entire aabb is on the negative side // If so, object is not visible PCPlaneList::const_iterator pit = mActiveCullingPlanes.begin(); while ( pit != mActiveCullingPlanes.end() ) { PCPlane * plane = *pit; Plane::Side xside = plane->getSide(centre, halfSize); if (xside == Plane::NEGATIVE_SIDE) { return false; } pit++; } return true; }
//----------------------------------------------------------------------- bool Frustum::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const { // AABB盒子是个空盒子,不可见 if (bound.isNull()) return false; // AABB盒子无限大 if (bound.isInfinite()) return true; // 进行必要的更新 updateFrustumPlanes(); // 获取AABB盒子的中心 Vector3 centre = bound.getCenter(); // 获取盒子半大小向量 Vector3 halfSize = bound.getHalfSize(); // 遍历视锥体的每个平面,对每个平面, 见如果所有的点都在反面 // 如果这样,对象不可见 for (int plane = 0; plane < 6; ++plane) { // 如果视锥体无限,跳过远裁平面 if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0) continue; Plane::Side side = mFrustumPlanes[plane].getSide(centre, halfSize); if (side == Plane::NEGATIVE_SIDE) { // 所有的角都在反面,那么在视域之外 if (culledBy) *culledBy = (FrustumPlane)plane; return false; } } return true; }
/** Checks how the second box intersects with the first. */ Intersection intersect( const PlaneBoundedVolume &one, const AxisAlignedBox &two ) { OctreeSceneManager::intersect_call++; // Null box? if (two.isNull()) return OUTSIDE; // Infinite box? if (two.isInfinite()) return INTERSECT; // Get centre of the box Vector3 centre = two.getCenter(); // Get the half-size of the box Vector3 halfSize = two.getHalfSize(); // For each plane, see if all points are on the negative side // If so, object is not visible. // If one or more are, it's partial. // If all aren't, full bool all_inside = true; PlaneList::const_iterator i, iend; iend = one.planes.end(); for (i = one.planes.begin(); i != iend; ++i) { const Plane& plane = *i; Plane::Side side = plane.getSide(centre, halfSize); if(side == one.outside) return OUTSIDE; if(side == Plane::BOTH_SIDE) all_inside = false; } if ( all_inside ) return INSIDE; else return INTERSECT; }
Bound::Bound( const AxisAlignedBox & aabb ) { m_center = aabb.getCenter(); m_radius = aabb.getExtents().x * 0.5f; }