/* ----------------------------------------------------------------------------- This source file is part of the GameTools Project http://www.gametools.org Author: Martin Szydlowski ----------------------------------------------------------------------------- */ #include "OgreBvHierarchySceneNode.h" #include "OgreBvHierarchySceneManager.h" #include #include namespace Ogre { // TRIVIA: this function is _not_ called for nodes which did not change since the last frame // only exception: the root node ... it's aabb should be null however, so we don't care void BvHierarchySceneNode::_updateBounds(void) { // Reset bounds first mWorldAABB.setNull(); // Update bounds from own attached objects ObjectMap::iterator i; for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i) { // Merge world bounds of each object mWorldAABB.merge(i->second->getWorldBoundingBox(true)); } if (!mWorldAABB.isNull()) { static_cast(mCreator)->_updateNode(this); } } void BvHierarchySceneNode::computeScene(BvhPlaneEventList& events, AxisAlignedBox& aabb, int& nObjects, bool includeChildren) { /**************************************************************************************/ /* HACK: do not include camera node, FUCKS UP world AABB really BAD, dunno why */ /* TODO: find a generic solution where MOVABLE nodes are NOT INSERTED into the BvHierarchy */ /**************************************************************************************/ //if (mName == "PlayerCamNode") // return; // first compute nodes AABB mWorldAABB.setNull(); // Update bounds from own attached objects ObjectMap::iterator i; for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i) { // ignore objects with no actual geometry like frustums & lights if (getExcludedMovables().find(i->second->getMovableType()) == getExcludedMovables().end()) { //LogManager::getSingleton().getLog(BvHierarchy_LOGNAME)->logMessage("Adding movable type " + i->second->getMovableType() + " to BvHierarchy"); // Merge world bounds of each object mWorldAABB.merge(i->second->getWorldBoundingBox(true)); } } // create information for BvHierarchy/SAH if (!mWorldAABB.isNull()) { // merge aabb with global AABB aabb.merge(mWorldAABB); // increase object count nObjects++; // generate events BvhPlaneEvent::Dimension axes[] = {BvhPlaneEvent::PED_X, BvhPlaneEvent::PED_Y, BvhPlaneEvent::PED_Z}; Vector3 min = mWorldAABB.getMinimum(); Vector3 max = mWorldAABB.getMaximum(); for (int i = 0; i < 3; i++) { // 1-D and 2-D objects if (min[i] == max[i]) { //e = new BvhPlaneEvent(this, min, axes[i], BvhPlaneEvent::PET_ON); //sceneinfo.events.push_back(*e); events.push_back(BvhPlaneEvent(this, min, axes[i], BvhPlaneEvent::PET_ON)); } else { //e = new BvhPlaneEvent(this, min, axes[i], BvhPlaneEvent::PET_START); //sceneinfo.events.push_back(*e); //e = new BvhPlaneEvent(this, max, axes[i], BvhPlaneEvent::PET_END); //sceneinfo.events.push_back(*e); events.push_back(BvhPlaneEvent(this, min, axes[i], BvhPlaneEvent::PET_START)); events.push_back(BvhPlaneEvent(this, max, axes[i], BvhPlaneEvent::PET_END)); } } } // Merge with children if (includeChildren) { ChildNodeMap::iterator child; for (child = mChildren.begin(); child != mChildren.end(); ++child) { BvHierarchySceneNode* sceneChild = static_cast(child->second); sceneChild->computeScene(events, aabb, nObjects); } } } //void BvHierarchySceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue, // bool includeChildren, bool displayNodes, bool onlyShadowCasters) void BvHierarchySceneNode::queueObjects(Camera* cam, RenderQueue* queue, bool onlyShadowCasters) { //SceneNode::_findVisibleObjects(cam, queue, includeChildren, displayNodes, onlyShadowCasters); // Add all entities ObjectMap::iterator iobj; ObjectMap::iterator iobjend = mObjectsByName.end(); for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj) { // Tell attached objects about camera position (incase any extra processing they want to do) iobj->second->_notifyCurrentCamera(cam); if (iobj->second->isVisible() && (!onlyShadowCasters || iobj->second->getCastShadows())) { iobj->second->_updateRenderQueue(queue); } } // Check if the bounding box should be shown. // See if our flag is set or if the scene manager flag is set. if (mShowBoundingBox || (mCreator && mCreator->getShowBoundingBoxes())) { _addBoundingBoxToQueue(queue); } } void BvHierarchySceneNode::getGeometryList(GtpVisibility::GeometryVector *geometryList) { SceneNode::ObjectIterator objIt = getAttachedObjectIterator(); while (objIt.hasMoreElements()) { MovableObject *movable = objIt.getNext(); // we are interested only in the entities, i.e., instances of geometry if (movable->getMovableType() == "Entity") { Entity *ent = static_cast(movable); geometryList->push_back(ent); } } } // recalculate the world aabb AxisAlignedBox BvHierarchySceneNode::getBoundingBox(void) const { return mWorldAABB; } BvHierarchySceneNode::StringSet& BvHierarchySceneNode::getExcludedMovables(void) { static StringSet sExluded; // initialise once if (sExluded.empty()) { sExluded.insert("Camera"); sExluded.insert("Frustum"); sExluded.insert("Light"); } return sExluded; } // DEBUG String BvHierarchySceneNode::dumpToString(void) { String objects; // Add all entities ObjectMap::iterator iobj = mObjectsByName.begin(); ObjectMap::iterator iobjend = mObjectsByName.end(); while (iobj != iobjend) { objects += " " + iobj->second->getName(); iobj++; } objects += " Attached to " + StringConverter::toString(mLeaves.size()) + " KdLeaves."; return objects; } }