OGRE3D场景管理器如何真正找到任何场景节点
How can the OGRE3D SceneManager really find *any* SceneNode?
TL;DR
SceneManager
如何实际找到任何SceneNode
,而不管它在图中的位置当:
SceneManager::createSceneNode(...)
方法明确声明创建的节点不是图的部分?cco,和SceneNode
可以在SceneManager
不知情的情况下独立创造自己的孩子?²
SM不会自动将其创建的场景节点转换为其他节点(例如根节点)的子节点;您必须在该的节点上手动调用addChild
²客户端只需编写sceneManager->getRootSceneNode()->createChildSceneNode("Child");
,SM就不会知道新孩子的存在
背景
我在OGRE3D中查看了源代码,发现了以下关于SceneManager
类的文档(>>添加了<<强调):
/** Retrieves a named SceneNode from the scene graph.
@remarks
If you chose to name a SceneNode as you created it, or if you
happened to make a note of the generated name, you can look it
up >>wherever it is in the scene graph<< using this method.
@note Throws an exception if the named instance does not exist
*/
virtual SceneNode* getSceneNode(const String& name) const;
当您查看实现时,您会看到:
SceneNode* SceneManager::getSceneNode(const String& name) const
{
SceneNodeList::const_iterator i = mSceneNodes.find(name);
if (i == mSceneNodes.end())
{
OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
"SceneManager::getSceneNode");
}
return i->second;
}
到目前为止,一切都很好。我们可以看到SM在其名为mSceneNodes
的SceneNodeList
中搜索您请求的SceneNode
。我想弄清楚的是,文档声称它可以"在场景图中的任何位置"找到节点。当使用SceneManager::createSceneNode(...)
时,新的SceneNode
仅被添加到mSceneNodes
列表中。SM的createSceneNode
方法的文档中写道(>>添加了<<强调):
/** Creates an instance of a SceneNode with a given name.
@remarks
Note that this >>does not add the SceneNode to the scene hierarchy<<.
This method is for convenience, since it allows an instance to
be created for which the SceneManager is responsible for
allocating and releasing memory, which is convenient in complex
scenes.
@par
To include the returned SceneNode in the scene, use the addChild
method of the SceneNode which is to be it's parent.
@par
Note that this method takes a name parameter, which makes the node easier to
retrieve directly again later.
*/
virtual SceneNode* createSceneNode(const String& name);
同时,如果您查看SceneNode
类,它有自己的createChild(const String& name, ...)
方法,它显然不会将自己的子级添加到SceneManager
的列表中,如下所示:
SceneNode* SceneNode::createChildSceneNode(const Vector3& inTranslate,
const Quaternion& inRotate)
{
return static_cast<SceneNode*>(this->createChild(inTranslate, inRotate));
}
//-----------------------------------------------------------------------
SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& inTranslate,
const Quaternion& inRotate)
{
return static_cast<SceneNode*>(this->createChild(name, inTranslate, inRotate));
}
这意味着,如果客户端程序说node.createChildSceneNode(...);
,则SceneManager
将不知道新子节点AFAIK的存在,因此永远无法找到它。
我研究源代码已经有一段时间了,还没有找到这个问题的答案。我看了看BspSceneManager
和BspSceneNode
,只是想看看是否能发现其他东西,但却一无所获。
为了完整性/参考性,主分支中当前可用的最新提交是:
commit 3b13abbdcce146b2813a6cc3bedf16d1d6084340
Author: mkultra333 <unknown>
Date: Sun May 8 19:31:39 2016 +0800
难怪这部分会让你感到困惑,因为它是十多年前过度OOP的一部分。有些人喜欢它,有些人讨厌它。
然而,如果一旦你知道该寻找什么,答案就很简单:Node::createChild
的代码如下:
Node* newNode = createChildImpl( sceneType );
//...
return newNode;
它实际上将创建委托给createChildImpl
("实现者")。此函数是一个纯虚拟函数,因此SceneNode
必须过载。
当我们进入SceneNode::createChildImpl
时,我们得到:
Node* SceneNode::createChildImpl(const String& name)
{
return mCreator->_createSceneNode( name );
}
CCD_ 27是一个CCD_ 28指针变量。因此:当通过createChildSceneNode
创建SceneNode
时,SceneManager
确实会得到通知。
然而要注意的是,一种实现方式(例如BspSceneManager
中的BspSceneNode
)可以使createChildImpl
过载并且不通知SceneManager
;或者它们可能
不过,在SceneManager::_createSceneNode
中放置断点并检查调用堆栈将为您省去很多麻烦。
- 反向给定链表中的K节点
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- Boost Graph Library,修复节点大小
- 如何在不产生任何垃圾的情况下获得C中的像素
- C++A*算法并不总是在路径中具有目标节点
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 查找树(不属于任何特定类型的简单连接树)中两个节点之间的路径
- 是否有任何函数可以从 wxtreelistctrl 获取所有选定的叶节点
- 找到任何节点的BST高度
- OGRE3D场景管理器如何真正找到任何场景节点
- 是否有任何树容器可以存储具有多个值的节点
- C++-从单链循环列表中的任何索引中删除一个节点
- 霍夫曼树中的左节点和右节点指针不指向任何内容
- 找到最大路径总和,我们可以在二叉树中的任何节点开始和结束
- 从链表中删除节点会运行,但不会删除任何内容
- 是否有任何方法可以使用c++ libgraph为子图设置默认节点属性?
- 分割错误:11与节点做任何事情
- DoublyLinkedList.当尝试在2个节点之间插入时不做任何事情