Moving entities (nodes) with MOGRE

Terrice

09-12-2009 10:18:40

Hi,

I looked around on the forums, and have successfully completed all the tutorials which was a lot of fun but was unable to find an answer to this (hopefully) very simple query.

To keep things simple I'll be using the outcome of Tutorial 1 (except with one robot instead of 2) combined with the "handle user input" in Tutorial 4 (CreateInputHandler). I was looking to make the robot slide to the left when the left keyboard button is pressed, and to the right when the right keyboard button is pressed (and so on).

Tutorial 4 covered how to handle user input, which is great, however the the entity and node (and scene manager as a whole) are defined within the SceneCreating function so I'm not really sure how the keyhandle functions would have access to adjust their positions. Should the nodes be declared as part of the MyOgreWindow class? If you name a node as "RobotNode" in the SceneCreating function, can the KeyHandlers call the node by name?

The first tutorial also covered how to move a node (with node.Position) however this appears to be a once-off translation during the program startup, and is not something that occurs with each frame.

Some assistance with this is appreciated. :)

Thanks in advance.

smiley80

09-12-2009 13:50:40

You can get SceneNodes by name with SceneManager.GetSceneNode(string name).

In general, you should check first whether the SceneManager has a node with this name (SceneManager.HasSceneNode(string name)), since GetSceneNode throws an exception when it doesn't.

WarehouseJim

09-12-2009 14:56:23

If you are moving things around the scene, you can just do:

node.Position = new Vector3(x,y,z); //Set a position
//or
node.Translate(dx,dy,dz); //move relative to the previous position

Remember that all these movements are in the parent node's coordinate system, not the global coordinate system - these are the same if the parent node is the rootscenenode.

There is no great issue with doing this every frame - I do it with many hundreds of objects at the same time (at which stage you begin to get issues with your batch count, but that's a discussion for another day!).

Another way to move the robot would be to use ogre's animation tools, which I think are in one of the tutorials. This might make the movement smoother.

I personally tend to keep references to nodes, rather than looking them up by their name the whole time. It's a matter of personal preference.

Terrice

12-12-2009 05:22:24

Thanks for the replies guys, I've been playing around with the code this morning and really enjoy using the Mogre class. Firstly, thanks for the tip on HasSceneNode smiley80, I'll be sure to remember and include this as a safety check.

Ok, so it sounds like a good way is to use the FrameStarted function to help control the movement.

Below is the simplified code that I have so far. Basically I started a new project and threw in the bare minimum required to get this test up and running. To keep it concise I'll only be checking for the left and right key presses.


class MyOgreWindow : OgreWindow
{
const float TRANSLATE = 100; // Might be too large a value, not sure...
Vector3 mTranslation = Vector3.ZERO;

protected override void CreateInputHandler()
{
this.Root.FrameStarted += new FrameListener.FrameStartedHandler(FrameStarted);
this.KeyDown += new KeyEventHandler(KeyDownHandler);
this.KeyUp += new KeyEventHandler(KeyUpHandler);
}

void KeyDownHandler(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left:
mTranslation.x = -TRANSLATE;
break;

case Keys.Right:
mTranslation.x = TRANSLATE;
break;
}
}

void KeyUpHandler(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Left:
case Keys.Right:
mTranslation.x = 0;
break;
}
}

bool FrameStarted(FrameEvent evt)
{
//***** I assume that this is where I will need to move the entity left or right. *****

return true;
}
}

class SceneCreator
{
public SceneCreator(OgreWindow win)
{
win.SceneCreating += new OgreWindow.SceneEventHandler(SceneCreating);
}

void SceneCreating(OgreWindow win)
{
Entity ent = win.SceneManager.CreateEntity("ninja", "ninja.mesh");
SceneNode node = win.SceneManager.RootSceneNode.CreateChildSceneNode("NinjaNode");
node.AttachObject(ent);

//Quick test to move the entity (which works as a once-off when the scene is created)
node.Position += new Vector3(50, 0, 10);

win.Camera.Position = new Vector3(0, 200, 400);
win.Camera.LookAt(ent.BoundingBox.Center);
}
}


WarehouseJim, you mentioned that I could use the Position or Translate properties, however I'm not sure how to allow the FrameStarted function to have access to the node "NinjaNode" to move it. I'm not concerned with animation at this stage I would like to keep things simple. :D

My problem right now is coming to grips with how the functions in the MyOgreWindow class will access nodes (and therefore variables) created in the SceneCreator.

EDIT: Oh, and if you know of any other tutorials for MORGE, besides those mentioned in the OP, that would be great. :)

WarehouseJim

13-12-2009 11:07:05

I don't know of any other Mogre tutorials. Do you know about at http://www.ogre3d.org/wiki/index.php/Mo ... #_Snippets? I'm guessing they won't be that useful for you yet, but worth a look.

When you get stuck in, you will probably find yourself looking at the Ogre, Python-Ogre etc tutorials, articles and HowTos. The other languages often aren't hard to decode even if you haven't got any experience in C++ etc because the important stuff is just calls to classes and methods with the same names as Mogre. The C++ Ogre wiki has by far the most written in it. Python-Ogre has (or did have) the best set of demos. This tends to be a good option when you're trying to more complex things, probably not the basics.

Given the way you have set up your classes, do something like:


class MyOgreWindow
{
...
SceneNode ninjaNode;
bool FrameStarted(FrameEvent evt)
{
...
if(ninjaNode ==null) ninjaNode = sceneManager.GetSceneNode("ninja");
ninjaNode.Translate(translation);
...
}
...
}


alternatively, you could make NinjaNode a public member of SceneCreator and in your FrameStarted do
sceneCreator.NinjaNode.Translate(translation);

I don't know much about how OgreWindow.SceneEventHandler works / when it is called, but you might have to do an extra test for if the ninjaNode has been made yet to stop it crashing. You probably only want to call translate if there's actually a translation to be done as well.

Terrice

14-12-2009 10:11:13

Thanks for the reply WarehouseJim, I played around with the code (and your suggestion) and everything is working great!