ray ray - 1 year ago 71
C++ Question

How can the OGRE3D SceneManager really find *any* SceneNode?


How can the
actually find any
regardless of where it happens to be in the graph when:

  1. The
    method explicitly claims that the nodes created are not part of the graph?¹, and

  2. SceneNode
    s can independently create their own children without the
    's knowledge?²

¹ The SM does not automatically turn the scene nodes it creats into children of other nodes (e.g. root); you have to manually call
on a node for that

² The client can simply write
, and the SM wouldn't know about the new child's existence


I was going over the source code in OGRE3D and came across the following piece of documentation on the
class (>> << emphasis added):

/** Retrieves a named SceneNode from the scene graph.
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;

When you look at the implementation, you see:

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.",

return i->second;

So far, so good. We can see that the SM searches for your requested
in its own
. The part I'm trying to figure out is that the documentation claims it can find a node "wherever it is in the scene graph". New
s are only added into the
list when using
. The documentation for the SM's
method says (>> << emphasis added):

/** Creates an instance of a SceneNode with a given name.
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
To include the returned SceneNode in the scene, use the addChild
method of the SceneNode which is to be it's parent.
Note that this method takes a name parameter, which makes the node easier to
retrieve directly again later.
virtual SceneNode* createSceneNode(const String& name);

At the same time, if you look at the
class, it has its own
createChild(const String& name, ...)
method, which clearly does not add its own children into the
's list, as shown below:

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));

This means that if the client program says
, the
would not be aware of the existence of the new child node, AFAIK, so it'd never be able to find it.

I've been studying the source code for a while now and I've not found an answer to this question. I looked at the
and the
just to see if I could spot something else, but came up empty.

For the sake of completeness/reference, the most recent commit currently available in the master branch is:

commit 3b13abbdcce146b2813a6cc3bedf16d1d6084340
Author: mkultra333 <unknown>
Date: Sun May 8 19:31:39 2016 +0800

Answer Source

It's no wonder this part confuses you because it's part of over-OOP from more than a decade ago. Some like it, some hate it.

The answer however, is quite simple if once you know what to look for: The code for Node::createChild is the following:

Node* newNode = createChildImpl( sceneType );
return newNode;

It actually delegates creation to createChildImpl (the "implementer"). This function is a pure virtual function, thus SceneNode must overload.

When we go to SceneNode::createChildImpl, we get:

Node* SceneNode::createChildImpl(const String& name)
    return mCreator->_createSceneNode( name );

mCreator is a SceneManager pointer variable. So there you go: The SceneManager does get informed when a SceneNode is created via createChildSceneNode.

Note however an implementation (e.g. BspSceneNode in BspSceneManager) may overload createChildImpl and not inform the SceneManager; or they may.

Placing a breakpoint inside SceneManager::_createSceneNode and checking out the callstack will save you a lot of headaches though.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download