void DumpNodes(std::stringstream &ss, Ogre::Node *n, int level) { for (int i = 0; i < level; i++) { ss << " "; } ss << "SceneNode: " << n->getName() << std::endl; Ogre::SceneNode::ObjectIterator object_it = ((Ogre::SceneNode *)n)->getAttachedObjectIterator(); Ogre::Node::ChildNodeIterator node_it = n->getChildIterator(); Ogre::MovableObject *m; while (object_it.hasMoreElements()) { for (int i = 0; i < level + 2; i++) { ss << " "; } m = object_it.getNext(); ss << m->getMovableType() << ": " << m->getName() << std::endl; } while (node_it.hasMoreElements()) { DumpNodes(ss, node_it.getNext(), level + 2); } }
//! //! Creates a deep copy of the given scene node. //! //! \param sceneNode The scene node to copy. //! \param sceneNodeCopy The scene node to add the copied objects to (will be created if 0). //! \param namePrefix The prefix to use for names of copied objects. //! \param sceneManager The scene manager to use for creating the object. //! void OgreTools::deepCopySceneNode ( Ogre::SceneNode *sceneNode, Ogre::SceneNode *&sceneNodeCopy, const QString &namePrefix, Ogre::SceneManager *sceneManager /* = 0 */ ) { // make sure the given scene node is valid if (!sceneNode) { Log::error("The given scene node is invalid.", "OgreTools::deepCopySceneNode"); return; } // make sure a valid scene manager is available if (!sceneManager) sceneManager = sceneNode->getCreator(); if (!sceneManager) { Log::error("No valid scene manager available.", "OgreTools::deepCopySceneNode"); return; } // create the target scene node if it doesn't exist yet if (!sceneNodeCopy) { QString sceneNodeCopyName = QString("%1_%2Copy").arg(namePrefix).arg(sceneNode->getName().c_str()); sceneNodeCopy = copySceneNode(sceneNode, sceneNodeCopyName, sceneManager); if (!sceneNodeCopy) { Log::error("The scene node could not be copied.", "OgreTools::deepCopySceneNode"); return; } } // iterate over the list of attached objects Ogre::SceneNode::ObjectIterator objectIterator = sceneNode->getAttachedObjectIterator(); while (objectIterator.hasMoreElements()) { Ogre::MovableObject *movableObject = objectIterator.getNext(); if (movableObject) { QString entityCopyName = QString("%1_%2Copy").arg(namePrefix).arg(movableObject->getName().c_str()); Ogre::MovableObject *movableObjectCopy = cloneMovableObject(movableObject, entityCopyName, sceneManager); if (movableObjectCopy) sceneNodeCopy->attachObject(movableObjectCopy); } } // iterate over the list of child nodes Ogre::SceneNode::ChildNodeIterator childNodeIterator = sceneNode->getChildIterator(); while (childNodeIterator.hasMoreElements() ) { Ogre::SceneNode *childSceneNode = (Ogre::SceneNode *) childNodeIterator.getNext(); QString childSceneNodeCopyName = QString("%1_%2Copy").arg(namePrefix).arg(childSceneNode->getName().c_str()); Ogre::SceneNode *childSceneNodeCopy = copySceneNode(childSceneNode, childSceneNodeCopyName, sceneManager); if (childSceneNodeCopy) { sceneNodeCopy->addChild(childSceneNodeCopy); deepCopySceneNode(childSceneNode, childSceneNodeCopy, namePrefix, sceneManager); } } }
//该函数不支持多线程 string BaseManager::pickMovableObject( int x,int y ){ //如果相同的帧同时相同的x,y就直接返回结果 if( mPickFrameCount == getFrameCount() && mPickX == x && mPickY == y ){ return mPickName; } mRay = mCamera->getCameraToViewportRay( (Ogre::Real)x/(Ogre::Real)mWindow->getWidth(), (Ogre::Real)y/(Ogre::Real)mWindow->getHeight() ); mSceneQuery->setRay( mRay ); //距离排序 mSceneQuery->setSortByDistance(true); Ogre::RaySceneQueryResult result = mSceneQuery->execute(); //execute不能执行像素级的查询,它仅仅是和包围盒进行比较 //可以考虑使用渲染到纹理,使用1x1的纹理来对查询结果进行像素级别的查询 //这里使用逐个求交点的办法 Ogre::MovableObject* pmo = nullptr; Ogre::Real dis; for( size_t i = 0;i < result.size();++i ){ if( result[i].movable && result[i].movable->isVisible() && //不可见的 result[i].movable->isInScene() ){ //不在场景中的 mIntersect = false; result[i].movable->visitRenderables(this); if( mIntersect ){ //考虑到同一帧中间有多个地方的代码需要调用该函数 //这样使用内存换速度 if( !pmo || dis>mIntersectDistance ){ dis = mIntersectDistance; pmo = result[i].movable; } } } } if( pmo ){ mPickX = x; mPickY = y; mPickFrameCount = getFrameCount(); mPickName = pmo->getName(); return mPickName; } //返回一个空字串表示没有 return ""; }
void RenderBoxWrap::removeNode(Ogre::SceneNode* _node) { //System::Console::WriteLine("remove node {0}", gcnew System::String(_node->getName().c_str())); while(_node->numAttachedObjects() != 0) { Ogre::MovableObject* object = _node->getAttachedObject(0); removeEntity(object->getName()); } while (_node->numChildren() != 0) { Ogre::SceneNode* forDelete = (Ogre::SceneNode*)_node->getChild(0); removeNode(forDelete); } _node->getParentSceneNode()->removeAndDestroyChild(_node->getName()); }
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result,Ogre::MovableObject* &target,float &closest_distance, const Ogre::uint32 queryMask) { target = NULL; // check we are initialised if (mRaySceneQuery != NULL) { // create a query object mRaySceneQuery->setRay(ray); mRaySceneQuery->setSortByDistance(true); mRaySceneQuery->setQueryMask(queryMask); // execute the query, returns a vector of hits if (mRaySceneQuery->execute().size() <= 0) { // raycast did not hit an objects bounding box return (false); } } else { //LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG; return (false); } // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. //Ogre::Ogre::Real closest_distance = -1.0f; closest_distance = -1.0f; Ogre::Vector3 closest_result; Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults(); #if 0 for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) { const Ogre::RaySceneQueryResultEntry& result = query_result[qr_idx]; Ogre::Real distance = result.distance; Ogre::MovableObject* movable = static_cast<Ogre::MovableObject*>(result.movable); Ogre::SceneQuery::WorldFragment* worldFragment = result.worldFragment; if (movable) { const Ogre::String& type = movable->getMovableType(); const Ogre::String& name = movable->getName(); const Ogre::String& parentName = movable->getParentNode()->getName(); Ogre::uint32 flag = movable->getQueryFlags(); if (type.compare("Entity") == 0) { Ogre::Entity* ent = (Ogre::Entity*)movable; } std::ostrstream oss; oss<<"name:"<<name<<" distance:"<< distance <<" type:"<<type<<" flag:"<<flag<<" parent:"<<parentName<<std::endl; OutputDebugString(oss.str() ); } } #endif for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++) { // stop checking if we have found a raycast hit that is closer // than all remaining entities if ((closest_distance >= 0.0f) && (closest_distance < query_result[qr_idx].distance)) { break; } // only check this result if its a hit against an entity if ((query_result[qr_idx].movable != NULL) && (query_result[qr_idx].movable->getMovableType().compare("Entity") == 0)) { // get the entity to check Ogre::MovableObject *pentity = static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable); // mesh data to retrieve size_t vertex_count; size_t index_count; Ogre::Vector3 *vertices = NULL; Ogre::uint32 *indices = NULL; // get the mesh information GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), vertex_count, vertices, index_count, indices, pentity->getParentNode()->_getDerivedPosition(), pentity->getParentNode()->_getDerivedOrientation(), pentity->getParentNode()->_getDerivedScale()); // test for hitting individual triangles on the mesh bool new_closest_found = false; for (size_t i = 0; i < index_count; i += 3) { // check for a hit against this triangle std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]], vertices[indices[i+1]], vertices[indices[i+2]], true, false); // if it was a hit check if its the closest if (hit.first) { if ((closest_distance < 0.0f) || (hit.second < closest_distance)) { // this is the closest so far, save it off closest_distance = hit.second; new_closest_found = true; } } } // free the verticies and indicies memory delete vertices; delete indices; // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if (new_closest_found) { target = pentity; closest_result = ray.getPoint(closest_distance); } } } // return the result if (closest_distance >= 0.0f) { // raycast success result = closest_result; return (true); } else { // raycast failed return (false); } }
void OgreInfo::diagnose(std::ostream& outputStream) { Ogre::SceneManagerEnumerator::SceneManagerIterator sceneManagerI = Ogre::Root::getSingleton().getSceneManagerIterator(); while (sceneManagerI.hasMoreElements()) { Ogre::SceneManager* sceneManager = sceneManagerI.getNext(); outputStream << "Scenemanager(" << sceneManager->getTypeName() << ") " << sceneManager->getName() << std::endl; outputStream << " Number of scene nodes: " << countNodes(sceneManager->getRootSceneNode()) << std::endl; outputStream << " Movable objects:" << std::endl; unsigned int movableObjectCounter = 0; Ogre::Root::MovableObjectFactoryIterator movableObjectFactoryI = Ogre::Root::getSingleton().getMovableObjectFactoryIterator(); while (movableObjectFactoryI.hasMoreElements()) { Ogre::MovableObjectFactory* factory = movableObjectFactoryI.getNext(); std::string type(factory->getType()); { Ogre::SceneManager::MovableObjectIterator I = sceneManager->getMovableObjectIterator(type); while (I.hasMoreElements()) { movableObjectCounter++; Ogre::MovableObject* movable = I.getNext(); if (movable->getMovableType() == "Light") { Ogre::Light* light = static_cast<Ogre::Light*> (movable); outputStream << " * Light " << light->getName() << "(" << (light->isInScene() ? "in scene" : "not in scene") << ")" << std::endl; outputStream << " Pos: " << light->getDerivedPosition() << std::endl; outputStream << " Direction: " << light->getDerivedDirection() << std::endl; } else { std::stringstream ssPosAndOrientation; if (movable->getParentSceneNode() && movable->isInScene()) { ssPosAndOrientation << " pos: " << movable->getParentSceneNode()->getPosition() << " orientation: " << movable->getParentSceneNode()->getOrientation(); } outputStream << " * " << type << " " << movable->getName() << "(" << (movable->isInScene() ? "in scene" : "not in scene") << ")" << ssPosAndOrientation.str() << std::endl; // outputStream << " Pos: " << light->getDerivedPosition() << std::endl; // outputStream << " Direction: " << light->getDerivedDirection() << std::endl; } } } } outputStream << " Number of movable objects: " << movableObjectCounter << std::endl; outputStream << " Cameras:" << std::endl; { Ogre::SceneManager::CameraIterator I = sceneManager->getCameraIterator(); while (I.hasMoreElements()) { Ogre::Camera* camera = I.getNext(); outputStream << " Camera " << camera->getName() << "(" << (camera->isInScene() ? "in scene" : "not in scene") << ")" << std::endl; outputStream << " Pos: " << camera->getDerivedPosition() << std::endl; outputStream << " Direction: " << camera->getDerivedDirection() << std::endl; outputStream << " Clip distances: " << camera->getNearClipDistance() << " - " << camera->getFarClipDistance() << std::endl; } } } size_t resourceMemoryUsage = 0; outputStream << "Resource Managers:" << std::endl; Ogre::ResourceGroupManager::ResourceManagerIterator I = Ogre::ResourceGroupManager::getSingleton().getResourceManagerIterator(); while (I.hasMoreElements()) { std::string name = I.peekNextKey(); Ogre::ResourceManager* manager = I.getNext(); outputStream << " Resource Manager: " << name << std::endl; if (manager->getMemoryBudget() == std::numeric_limits<size_t>::max()) { outputStream << " Memory budget: not set" << std::endl; } else { outputStream << " Memory budget: " << manager->getMemoryBudget() << " bytes" << std::endl; } outputStream << " Memory usage: " << manager->getMemoryUsage() << " bytes" << std::endl; resourceMemoryUsage += manager->getMemoryUsage(); Ogre::ResourceManager::ResourceMapIterator resourceI = manager->getResourceIterator(); if (resourceI.hasMoreElements()) { outputStream << " Resources: " << std::endl; int resourceCount = 0; int loadedResourceCount = 0; while (resourceI.hasMoreElements()) { Ogre::ResourcePtr resource = resourceI.getNext(); if (resource->isLoaded()) { std::string reloadable = resource->isReloadable() ? " reloadable" : ""; outputStream << " " << resource->getName() << " ( " << resource->getSize() << " bytes)" << reloadable; Ogre::Texture* texture = dynamic_cast<Ogre::Texture*>(resource.get()); if (texture) { outputStream << texture->getWidth() << "x" << texture->getHeight() << " "; } outputStream << std::endl; loadedResourceCount++; } resourceCount++; } outputStream << " Total number of resources: " << resourceCount << std::endl; outputStream << " Number of loaded resources: " << loadedResourceCount << std::endl; } } outputStream << "Total memory usage for all resource manager: " << resourceMemoryUsage << " bytes" << std::endl; outputStream << std::flush; }
Ogre::String ObjectControl::mouseDragged (QPoint lastPos,QPoint currPos,float w,float h) { using namespace Ogre; float RatioX = float(lastPos.x())/w; float RatioY = float(lastPos.y())/h; Ray mouseRay = mCamera->getCameraToViewportRay(RatioX,RatioY); mRaySceneQuery->setRay(mouseRay); mRaySceneQuery->setSortByDistance(true); mRaySceneQuery->setQueryMask(DUMMY_PLANE); mRaySceneQuery->setQueryTypeMask(SceneManager::ENTITY_TYPE_MASK); RaySceneQueryResult &result = mRaySceneQuery->execute(); Ogre::MovableObject *closestObject = NULL; Real closestDistance = 100000; Ogre::RaySceneQueryResult::iterator rayIterator= result.begin(); for( rayIterator; rayIterator != result.end(); rayIterator++ ) { if ( (*rayIterator).movable !=NULL && closestDistance>(*rayIterator).distance ) { closestObject = ( *rayIterator ).movable; Ogre::String name = closestObject->getName(); Ogre::Vector3 newpos = Ogre::Vector3::ZERO; float rotateFactor = 0.0f; float scaleFactor = 0.0f; switch( currntOperation ) { //==== 處理物體平移 ====// case MoveX: if ( name != "dummy_plane_y" ) continue; newpos = mouseRay.getPoint((*rayIterator).distance); node->setPosition(newpos.x,node->getPosition().y,node->getPosition().z); break; case MoveY: if( name == "dummy_plane_y" ) continue; newpos = mouseRay.getPoint((*rayIterator).distance); node->setPosition(node->getPosition().x,newpos.y-node->_getWorldAABB().getHalfSize().y,node->getPosition().z); break; case MoveZ: if( name != "dummy_plane_y" ) continue; newpos = mouseRay.getPoint((*rayIterator).distance); node->setPosition(node->getPosition().x,node->getPosition().y,newpos.z); break; //==== 處理物體旋轉 ====// case RotateX: rotateFactor = 1*(currPos.y()-lastPos.y()); node->pitch(Ogre::Degree(rotateFactor),Node::TS_WORLD); break; case RotateY: rotateFactor = 1*(currPos.x()-lastPos.x()); node->yaw(Ogre::Degree(rotateFactor),Node::TS_WORLD); break; case RotateZ: rotateFactor = 1*(currPos.y()-lastPos.y()); node->roll(Ogre::Degree(rotateFactor),Node::TS_WORLD); break; //==== 處理物體縮放 ====// case ScaleX: scaleFactor = 1+0.001*(currPos.x()-lastPos.x()); node->scale(scaleFactor,1,1); break; case ScaleY: scaleFactor = 1-0.001*(currPos.y()-lastPos.y()); node->scale(1,scaleFactor,1); break; case ScaleZ: scaleFactor = 1+0.001*(currPos.x()-lastPos.x()); node->scale(1,1,scaleFactor); break; case ScaleXYZ: scaleFactor = 1+0.001*(currPos.x()-lastPos.x()); node->scale(scaleFactor,scaleFactor,scaleFactor); break; } update(); } } mRaySceneQuery->clearResults(); return (node==NULL)?"":node->getName(); }