Intermediate tutorials

Acheron

22-03-2011 12:33:05

Hi, I just completed Intermediate tutorial 1 using MOGRE. I used the TutorialFramework as a base class.

using Mogre;
using Mogre.TutorialFramework;
using System;
using System.Collections.Generic;

namespace Mogre.Tutorials
{
class Tutorial : BaseApplication
{
protected Entity mEntity = null; // The entity of the object we are animating
protected SceneNode mNode = null; // The SceneNode of the object we are moving
protected AnimationState mAnimationState = null; //The AnimationState the moving object

protected float mDistance = 0.0f; //The distance the object has left to travel
protected Vector3 mDirection = Vector3.ZERO; // The direction the object is moving
protected Vector3 mDestination = Vector3.ZERO; // The destination the object is moving towards
protected LinkedList<Vector3> mWalkList = null; // A doubly linked containing the waypoints

protected float mWalkSpeed = 35.0f; // The speed at which the object is moving
protected bool mWalking = false; // Whether or not the object is moving

public static void Main()
{
new Tutorial().Go();
}

protected override void CreateScene()
{
//temporary entity and SceneNode

mEntity = mSceneMgr.CreateEntity("Robot", "robot.mesh");

// Create the Robot's SceneNode
mNode = mSceneMgr.RootSceneNode.CreateChildSceneNode("RobotNode", new Vector3(0, 0, 25));
mNode.AttachObject(mEntity);

mWalkList = new LinkedList<Vector3>();
mWalkList.AddLast(new Vector3(550.0f, 0.0f, 50.0f));
mWalkList.AddLast(new Vector3(-100.0f, 0.0f, -200.0f));
mWalkList.AddLast(new Vector3(0.0f, 0.0f, 25.0f));

// Create knot objects so we can see movement
Entity knot1 = mSceneMgr.CreateEntity("Knot1", "knot.mesh");
SceneNode knot1Node = mSceneMgr.RootSceneNode.CreateChildSceneNode("Knot1Node",
new Vector3(0, -10, 25));
knot1Node.AttachObject(knot1);
knot1Node.SetScale(0.1f, 0.1f, 0.1f);
//
Entity knot2 = mSceneMgr.CreateEntity("Knot2", "knot.mesh");
SceneNode knot2Node = mSceneMgr.RootSceneNode.CreateChildSceneNode("Knot2Node",
new Vector3(550.0f, -10.0f, 50.0f));
knot2Node.AttachObject(knot2);
knot2Node.SetScale(0.1f, 0.1f, 0.1f);
//
Entity knot3 = mSceneMgr.CreateEntity("Knot3", "knot.mesh");
SceneNode knot3Node = mSceneMgr.RootSceneNode.CreateChildSceneNode("Knot3Node",
new Vector3(-100, -10, -200));
knot3Node.AttachObject(knot3);
knot3Node.SetScale(0.1f, 0.1f, 0.1f);

// Set the camera to look at our handywork
mCamera.SetPosition(-400, 0, -200);
mCamera.LookAt(knot2Node.Position);

// Set idle animation
mAnimationState = mEntity.GetAnimationState("Idle");
mAnimationState.Loop = true;
mAnimationState.Enabled = true;

}

protected bool NextLocation()
{
if (mWalkList.Count == 0)
return false;

return true;
}

protected override void UpdateScene(FrameEvent evt)
{
base.UpdateScene(evt);
mAnimationState.AddTime(evt.timeSinceLastFrame);

if (!mWalking)
//either we've not started walking or reached a way point
{
//check if there are places to go
if (NextLocation())
{
LinkedListNode<Vector3> tmp;

//Start the walk animation
mAnimationState = mEntity.GetAnimationState("Walk");
mAnimationState.Loop = true;
mAnimationState.Enabled = true;
mWalking = true;

//Update the destination using the walklist.
mDestination = mWalkList.First.Value; //get the next destination.
tmp = mWalkList.First; //save the node that held it
mWalkList.RemoveFirst(); //remove that node from the front of the list
mWalkList.AddLast(tmp); //add it to the back of the list.

//update the direction and the distance
mDirection = mDestination - mNode.Position;
mDistance = mDirection.Normalise();
}
else //nowhere to go. set the idle animation. (or Die)
{
mAnimationState = mEntity.GetAnimationState("Idle");
//mAnimationState = mEntity.GetAnimationState("Die");
//mAnimationState.SetLoop(false);
}
}
else //we're in motion
{
//determine how far to move this frame
float move = mWalkSpeed * evt.timeSinceLastFrame;
mDistance -= move;
//Check to see if we've arrived at a waypoint
if (mDistance <= 0.0f)
{
//set our node to the destination we've just reached & reset direction to 0
mNode.Position = mDestination;
mDirection = Vector3.ZERO;
mWalking = false;
}
else
{
//movement code goes here
mNode.Translate(mDirection * move);
//Rotation code goes here
Vector3 src = mNode.Orientation * Vector3.UNIT_X;
if ((1.0f + src.DotProduct(mDirection)) < 0.0001f)
{
mNode.Yaw(180.0f);
}
else
{
Quaternion quat = src.GetRotationTo(mDirection);
mNode.Rotate(quat);
}
}
}
}
}
}

Acheron

22-03-2011 13:41:54

Here is intermediate tutorial 2.


using Mogre;
using Mogre.TutorialFramework;
using System;
using System.Collections.Generic;
using MOIS;

namespace Mogre.Tutorials
{
class Tutorial : BaseApplication
{
protected int mCount = 0; // The number of robots on the screen
protected SceneNode mCurrentObject = null; // The newly created object

public static void Main()
{
new Tutorial().Go();
}

protected override void CreateScene()
{
mSceneMgr.AmbientLight = new ColourValue(127, 127, 127);

// World geometry & Sky
mSceneMgr.SetSkyDome(true, "Examples/CloudySky", 5, 8);
mSceneMgr.SetWorldGeometry("terrain.cfg");

// Set camera look point
mCamera.SetPosition(40, 100, 280);
mCamera.Pitch(new Radian(new Degree(-30)));
mCamera.Yaw(new Radian(new Degree(-45)));
}

protected override void ChooseSceneManager()
{
mSceneMgr = mRoot.CreateSceneManager(SceneType.ST_EXTERIOR_CLOSE);
}

protected override void InitializeInput()
{
// this is completely overridden from the base class
LogManager.Singleton.LogMessage("*** Initializing MOIS ***");

ParamList paramList = new ParamList();
paramList.Insert("w32_mouse", "DISCL_FOREGROUND");
paramList.Insert("w32_mouse", "DISCL_NONEXCLUSIVE");

IntPtr windowHnd;
mWindow.GetCustomAttribute("WINDOW", out windowHnd);
paramList.Insert("WINDOW", windowHnd.ToString());

InputManager inputMgr = InputManager.CreateInputSystem(paramList);

mKeyboard = (MOIS.Keyboard)inputMgr.CreateInputObject(MOIS.Type.OISKeyboard, true);
mMouse = (MOIS.Mouse)inputMgr.CreateInputObject(MOIS.Type.OISMouse, true);

MOIS.MouseState_NativePtr state = mMouse.MouseState;
state.width = (int)mWindow.Width;
state.height = (int)mWindow.Height;

mKeyboard.KeyPressed += new KeyListener.KeyPressedHandler(OnKeyPressed);
mKeyboard.KeyReleased += new KeyListener.KeyReleasedHandler(OnKeyReleased);
mMouse.MouseMoved += new MouseListener.MouseMovedHandler(OnMouseMoved);
mMouse.MousePressed += new MouseListener.MousePressedHandler(OnMousePressed);
mMouse.MouseReleased += new MouseListener.MouseReleasedHandler(OnMouseReleased);
}


protected override bool OnMouseMoved(MouseEvent evt)
{
// mouse look
if (evt.state.ButtonDown(MouseButtonID.MB_Right))
{
mCameraMan.MouseMovement(evt.state.X.rel, evt.state.Y.rel);
}
if (evt.state.ButtonDown(MouseButtonID.MB_Left))
{
using (RaySceneQuery raySceneQuery = mSceneMgr.CreateRayQuery(new Ray()))
{
Vector3 camPos = mCamera.Position;
float mouseX = (float)evt.state.X.abs / (float)evt.state.width;
float mouseY = (float)evt.state.Y.abs / (float)evt.state.height;
Ray mouseRay = mCamera.GetCameraToViewportRay(mouseX, mouseY);
raySceneQuery.Ray = mouseRay;
using (RaySceneQueryResult result = raySceneQuery.Execute())
{
foreach (RaySceneQueryResultEntry entry in result)
{
if (entry.worldFragment != null)
{
mCurrentObject.Position = entry.worldFragment.singleIntersection;
break;
}
}
}
}
}

return true;
}

protected override void UpdateScene(FrameEvent evt)
{
RaySceneQuery raySceneQuery = null; // The ray scene query pointer
using (raySceneQuery = mSceneMgr.CreateRayQuery(new Ray()))
{
Vector3 camPos = mCamera.Position;
Ray cameraRay = new Ray(new Vector3(camPos.x, 5000.0f, camPos.z), Vector3.NEGATIVE_UNIT_Y);
raySceneQuery.Ray = cameraRay;
using (RaySceneQueryResult result = raySceneQuery.Execute())
{
foreach (RaySceneQueryResultEntry entry in result)
{
if (entry.worldFragment != null)
{
float terrainHeight = entry.worldFragment.singleIntersection.y;

if ((terrainHeight + 10.0f) > camPos.y)
mCamera.SetPosition(camPos.x, terrainHeight + 10.0f, camPos.z);
}
}
}
}
}

protected override bool OnMousePressed(MouseEvent evt, MouseButtonID id)
{
if (id == MouseButtonID.MB_Left)
{
using (RaySceneQuery raySceneQuery = mSceneMgr.CreateRayQuery(new Ray()))
{
Vector3 camPos = mCamera.Position;
float mouseX = (float)evt.state.X.abs / (float)evt.state.width;
float mouseY = (float)evt.state.Y.abs / (float)evt.state.height;
Ray mouseRay = mCamera.GetCameraToViewportRay(mouseX, mouseY);
raySceneQuery.Ray = mouseRay;
using (RaySceneQueryResult result = raySceneQuery.Execute())
{
foreach (RaySceneQueryResultEntry entry in result)
{
if (entry.worldFragment != null)
{
Entity ent = mSceneMgr.CreateEntity("Robot" + mCount.ToString(), "robot.mesh");

mCurrentObject = mSceneMgr.RootSceneNode.CreateChildSceneNode(
"RobotNode" + mCount, entry.worldFragment.singleIntersection);

mCount++;
mCurrentObject.AttachObject(ent);
mCurrentObject.SetScale(0.1f, 0.1f, 0.1f);
break;
}
}
}
}
}
return true;
}
}
}

Acheron

23-03-2011 10:21:01

intermediate tutorial 3


using Mogre;
using Mogre.TutorialFramework;
using System;
using System.Collections.Generic;
using MOIS;

namespace Mogre.Tutorials
{
class Tutorial : BaseApplication
{
protected int mCount = 0; // The number of robots on the screen
protected SceneNode mCurrentObject = null; // The newly created object
protected bool mRobotMode = true; // The current state

class QueryFlags
{
public const uint NINJA_MASK = 0x1;
public const uint ROBOT_MASK = 0x2;
};

public static void Main()
{
new Tutorial().Go();
}

protected override void CreateScene()
{
mSceneMgr.AmbientLight = new ColourValue(127, 127, 127);

// World geometry & Sky
mSceneMgr.SetSkyDome(true, "Examples/CloudySky", 5, 8);
mSceneMgr.SetWorldGeometry("terrain.cfg");

// Set camera look point
mCamera.SetPosition(40, 100, 280);
mCamera.Pitch(new Radian(new Degree(-30)));
mCamera.Yaw(new Radian(new Degree(-45)));
}

protected override void ChooseSceneManager()
{
mSceneMgr = mRoot.CreateSceneManager(SceneType.ST_EXTERIOR_CLOSE);
}

protected override void InitializeInput()
{
// this is completely overridden from the base class
LogManager.Singleton.LogMessage("*** Initializing MOIS ***");

ParamList paramList = new ParamList();
paramList.Insert("w32_mouse", "DISCL_FOREGROUND");
paramList.Insert("w32_mouse", "DISCL_NONEXCLUSIVE");

IntPtr windowHnd;
mWindow.GetCustomAttribute("WINDOW", out windowHnd);
paramList.Insert("WINDOW", windowHnd.ToString());

InputManager inputMgr = InputManager.CreateInputSystem(paramList);

mKeyboard = (MOIS.Keyboard)inputMgr.CreateInputObject(MOIS.Type.OISKeyboard, true);
mMouse = (MOIS.Mouse)inputMgr.CreateInputObject(MOIS.Type.OISMouse, true);

MOIS.MouseState_NativePtr state = mMouse.MouseState;
state.width = (int)mWindow.Width;
state.height = (int)mWindow.Height;

mKeyboard.KeyPressed += new KeyListener.KeyPressedHandler(OnKeyPressed);
mKeyboard.KeyReleased += new KeyListener.KeyReleasedHandler(OnKeyReleased);
mMouse.MouseMoved += new MouseListener.MouseMovedHandler(OnMouseMoved);
mMouse.MousePressed += new MouseListener.MousePressedHandler(OnMousePressed);
mMouse.MouseReleased += new MouseListener.MouseReleasedHandler(OnMouseReleased);
}


protected override bool OnMouseMoved(MouseEvent evt)
{
// mouse look
if (evt.state.ButtonDown(MouseButtonID.MB_Right))
{
mCameraMan.MouseMovement(evt.state.X.rel, evt.state.Y.rel);
}
if (evt.state.ButtonDown(MouseButtonID.MB_Left))
{
using (RaySceneQuery raySceneQuery = mSceneMgr.CreateRayQuery(new Ray()))
{
Vector3 camPos = mCamera.Position;
float mouseX = (float)evt.state.X.abs / (float)evt.state.width;
float mouseY = (float)evt.state.Y.abs / (float)evt.state.height;
Ray mouseRay = mCamera.GetCameraToViewportRay(mouseX, mouseY);
raySceneQuery.Ray = mouseRay;
raySceneQuery.SetSortByDistance(false);
using (RaySceneQueryResult result = raySceneQuery.Execute())
{
foreach (RaySceneQueryResultEntry entry in result)
{
if (entry.worldFragment != null)
{
mCurrentObject.Position = entry.worldFragment.singleIntersection;
break;
}
}
}
}
}

return true;
}

protected override void UpdateScene(FrameEvent evt)
{
RaySceneQuery raySceneQuery = null; // The ray scene query pointer
using (raySceneQuery = mSceneMgr.CreateRayQuery(new Ray()))
{
Vector3 camPos = mCamera.Position;
Ray cameraRay = new Ray(new Vector3(camPos.x, 5000.0f, camPos.z), Vector3.NEGATIVE_UNIT_Y);
raySceneQuery.Ray = cameraRay;
raySceneQuery.SetSortByDistance(false);
using (RaySceneQueryResult result = raySceneQuery.Execute())
{
foreach (RaySceneQueryResultEntry entry in result)
{
if (entry.worldFragment != null)
{
float terrainHeight = entry.worldFragment.singleIntersection.y;

if ((terrainHeight + 10.0f) > camPos.y)
mCamera.SetPosition(camPos.x, terrainHeight + 10.0f, camPos.z);
break;
}
}
}
}
}

protected override bool OnMousePressed(MouseEvent evt, MouseButtonID id)
{
if (id == MouseButtonID.MB_Left)
{
if (mCurrentObject != null)
mCurrentObject.ShowBoundingBox = false;
using (RaySceneQuery raySceneQuery = mSceneMgr.CreateRayQuery(new Ray()))
{
Vector3 camPos = mCamera.Position;
float mouseX = (float)evt.state.X.abs / (float)evt.state.width;
float mouseY = (float)evt.state.Y.abs / (float)evt.state.height;
Ray mouseRay = mCamera.GetCameraToViewportRay(mouseX, mouseY);
raySceneQuery.Ray = mouseRay;
raySceneQuery.SetSortByDistance(true);
raySceneQuery.QueryMask = (mRobotMode ? QueryFlags.ROBOT_MASK : QueryFlags.NINJA_MASK);

using (RaySceneQueryResult result = raySceneQuery.Execute())
{
foreach (RaySceneQueryResultEntry entry in result)
{
if (entry.movable != null)
{
if (entry.movable.Name.StartsWith("tile"))
{
continue;
}
mCurrentObject = entry.movable.ParentSceneNode;
break;
}
else if (entry.worldFragment != null)
{
Entity ent;
if (mRobotMode)
{
ent = mSceneMgr.CreateEntity("Robot" + mCount, "robot.mesh");
ent.QueryFlags = QueryFlags.ROBOT_MASK;
}
else
{
ent = mSceneMgr.CreateEntity("Ninja" + mCount, "ninja.mesh");
ent.QueryFlags = QueryFlags.NINJA_MASK;
}


mCurrentObject = mSceneMgr.RootSceneNode.CreateChildSceneNode(
"RobotNode" + mCount, entry.worldFragment.singleIntersection);

mCount++;
mCurrentObject.AttachObject(ent);
if (mRobotMode)
mCurrentObject.SetScale(0.1f, 0.1f, 0.1f);
else
mCurrentObject.SetScale(0.05f, 0.05f, 0.05f);
break;
}
}
}
}
}
if (mCurrentObject != null)
mCurrentObject.ShowBoundingBox = true;
return true;
}

protected override bool OnKeyPressed(KeyEvent evt)
{
switch (evt.key)
{
case KeyCode.KC_SPACE:
mRobotMode = !mRobotMode;
mDebugOverlay.AdditionalInfo = (mRobotMode ? "Robot" : "Ninja") + " Mode Enabled";
break;
}
return base.OnKeyPressed(evt);
}
}
}

BobbyFischer

23-03-2011 11:16:10

Thank you for your efforts!

It seems this forum doesn't have much of a community, which is unfortunate. There is no other open source 3D engine out there that can be used with C#. Maybe most people that visit here are already accomplished programmers (that already know enough not to need any assistance). Still, it would be much better if beginners had more help. After all, one of the reasons Mogre exists is because C# is so much easier than C++. Mogre is the best tool for introducing people into making serious 3D applications.

Anyway, thanks for your work, I'll check it out and hopefully a moderator can add it to the wiki soon enough. :D

McDonte

23-03-2011 12:21:11

Hi, I just completed Intermediate tutorial 1 using MOGRE. I used the TutorialFramework as a base class.

Hey Acheron,

thanks a lot for your work. I have already started with this work some time ago. See here.
To port the source to Mogre is not very hard but to update the whole tutorial is much more work. A lot of it is not right anymore or has to be done some other way. I did this for the first as you can see, but for the others there is still some work to do. I think I will start with it next week.

Anyways you porting the code is defintely a big help for the whole community!

koirat

23-03-2011 12:38:44


It seems this forum doesn't have much of a community, which is unfortunate.


Most of us (the Mogre users) came from c++ Ogre so usually we have all the tutorials behind us.
Also most questions are Ogre related, so don't expect a flood of post on this forum.

Acheron

23-03-2011 12:55:32

Thanks I had fun porting the code, and learned quite a lot at the same time.

Here is intermediate tutorial 4, the one about switching scene managers.

Glad to be of help!


using Mogre;
using Mogre.TutorialFramework;
using System;
using System.Collections.Generic;
using MOIS;

namespace Mogre.Tutorials
{
// SceneManagerState
internal class SceneManagerState
{
private Vector3 mCamPosition;

public Vector3 CamPosition
{
get { return mCamPosition; }
set { mCamPosition = value; }
}

private Quaternion mCamOrientation; // The camera orientation

public Quaternion CamOrientation
{
get { return mCamOrientation; }
set { mCamOrientation = value; }
}

private SceneManager mSceneManager; // The SceneManager this object wraps

internal SceneManager SceneManager
{
get { return mSceneManager; }
set { mSceneManager = value; }
}

private RenderWindow mRenderWindow; // The RenderWindow the application uses

internal RenderWindow RenderWindow
{
get { return mRenderWindow; }
set { mRenderWindow = value; }
}

// Called when this SceneManager is being displayed
public Camera ShowScene()
{
// create the camera and viewport
Camera camera = mSceneManager.CreateCamera("PlayerCam");
Viewport viewPort = mRenderWindow.AddViewport(camera);
viewPort.BackgroundColour = ColourValue.Black;

camera.AspectRatio = (viewPort.ActualWidth / viewPort.ActualHeight);
camera.NearClipDistance = 5;

// Set the camera's position and orientation
camera.Position = mCamPosition;
camera.Orientation = mCamOrientation;
return camera;
}

// called when this SceneManager is no longer being displayed
public void HideScene(Camera camera)
{
// save camera position and orientation
mCamPosition = camera.Position;
mCamOrientation = camera.Orientation;
mRenderWindow.RemoveAllViewports();
mSceneManager.DestroyAllCameras();
}
}

class Tutorial : BaseApplication
{
SceneManagerState mTerrain;
SceneManagerState mGeneric;

public static void Main()
{
new Tutorial().Go();
}

protected override void ChooseSceneManager()
{
mTerrain = new SceneManagerState();
mTerrain.SceneManager = mRoot.CreateSceneManager(SceneType.ST_EXTERIOR_CLOSE);
mTerrain.RenderWindow = mWindow;
mGeneric = new SceneManagerState();
mGeneric.SceneManager = mRoot.CreateSceneManager(SceneType.ST_GENERIC);
mGeneric.RenderWindow = mWindow;
mSceneMgr = mGeneric.SceneManager;
}

protected override void CreateScene()
{
mTerrain.SceneManager.SetWorldGeometry("terrain.cfg");
mTerrain.SceneManager.SetSkyBox(true, "Examples/SpaceSkyBox", 50);
mCamera.SetPosition(60, 60, 500);
mCamera.LookAt(0, 0, 0);
mTerrain.CamPosition = mCamera.Position;
mTerrain.CamOrientation = mCamera.Orientation;

Entity ent = mGeneric.SceneManager.CreateEntity("Robot", "robot.mesh");
SceneNode node = mGeneric.SceneManager.RootSceneNode.CreateChildSceneNode("RobotNode");
node.AttachObject(ent);
mCamera.SetPosition(60, 60, 500);
mCamera.LookAt(0, 0, -250); // is there some other way to calculate a lookat quaternion without using the camera?
mGeneric.CamPosition = mCamera.Position;
mGeneric.CamOrientation = mCamera.Orientation;
}

protected override bool OnKeyPressed(KeyEvent evt)
{
switch (evt.key)
{
case KeyCode.KC_C:
if (mGeneric.SceneManager == mSceneMgr)
{
mGeneric.HideScene(mCamera);
mCamera = mTerrain.ShowScene();
mSceneMgr = mTerrain.SceneManager;
mCameraMan = new CameraMan(mCamera);
}
else if (mTerrain.SceneManager == mSceneMgr)
{
mTerrain.HideScene(mCamera);
mCamera = mGeneric.ShowScene();
mSceneMgr = mGeneric.SceneManager;
mCameraMan = new CameraMan(mCamera);
}
break;
}
return base.OnKeyPressed(evt);
}
}
}

BobbyFischer

23-03-2011 15:17:12


Most of us (the Mogre users) came from c++ Ogre so usually we have all the tutorials behind us.
Also most questions are Ogre related, so don't expect a flood of post on this forum.


Since Mogre was created for ease of use, this should be something everyone benefits from, including of course people that know c# and not Ogre / c++.
If someone has to learn Ogre in C++ before they can start working with Mogre then that pretty much defeats the whole purpose and restricts the audience down to a minimum.

Acheron

25-03-2011 17:24:22

How slow is C# compared to C++? has anyone measured it?

I was thinking that the biggest bottleneck is going to be calls through the wrapper. It would seem that C++ would have a big advantage here, since its using the engine directly instead of through a wrapper.

So I did a little test, this program does many calls per frame through the wrapper. It shows 2000 robots walking (I adapted it from the demo). You can toggle movement and animation by pressing 1 or 2. It seems to run very well to me, switching on pure movement has no effect on the frame rate, despite the fact that it is repositioning 2000 robots every single frame, through the wrapper.


using Mogre;
using Mogre.TutorialFramework;
using System;
using System.Collections.Generic;
using MOIS;

namespace Mogre.Tutorials
{
class Tutorial : BaseApplication
{
public static void Main()
{
new Tutorial().Go();
}

const int NUM_ROBOTS = 2000;
const int ROW_COUNT = 100;

AnimationState[] animState = new AnimationState[NUM_ROBOTS];
SceneNode[] nodes = new SceneNode[NUM_ROBOTS];
float[] animationSpeed = new float[NUM_ROBOTS];
bool animate = false;
bool move = false;

protected override void CreateScene()
{
// Setup animation default
Animation.DefaultInterpolationMode = Animation.InterpolationMode.IM_LINEAR;
Animation.DefaultRotationInterpolationMode = Animation.RotationInterpolationMode.RIM_LINEAR;

// Set ambient light
mSceneMgr.AmbientLight = new ColourValue(0.5f, 0.5f, 0.5f);

Entity ent = null;
int row = 0;
int column = 0;
Random rnd = new Random();
for (int i = 0; i < NUM_ROBOTS; ++i, ++column)
{
if (column > ROW_COUNT)
{
++row;
column = 0;
}
ent = mSceneMgr.CreateEntity("robot" + i, "robot.mesh");
nodes[i] = mSceneMgr.RootSceneNode.CreateChildSceneNode(
new Vector3(-(row * 100), 0, (column * 50)));
nodes[i].AttachObject(ent);

animState[i] = ent.GetAnimationState("Walk");
animState[i].Enabled = true;
animState[i].Loop = true;
animationSpeed[i] = (float)(rnd.NextDouble() + 0.5);
}


// Give it a little ambience with lights
Light l = null;
l = mSceneMgr.CreateLight("BlueLight");
l.SetPosition(-200, -80, -100);
l.SetDiffuseColour(0.5f, 0.5f, 1.0f);

l = mSceneMgr.CreateLight("GreenLight");
l.SetPosition(0, 0, -100);
l.SetDiffuseColour(0.5f, 1.0f, 0.5f);

// Position the camera
mCamera.SetPosition(100, 50, 100);
mCamera.LookAt(-50, 50, 0);
}

protected override void UpdateScene(FrameEvent evt)
{
if (animate)
{
for (int i = 0; i < NUM_ROBOTS; ++i)
{
//animState[i].AddTime(evt.timeSinceLastFrame * animationSpeed[i]);
animState[i].AddTime(evt.timeSinceLastFrame);
}
}
if (move)
{
for (int i = 0; i < NUM_ROBOTS; ++i)
{
nodes[i].SetPosition(nodes[i].Position.x + (35 * evt.timeSinceLastFrame), nodes[i].Position.y, nodes[i].Position.z);
}
}
base.UpdateScene(evt);
}

protected override bool OnKeyPressed(MOIS.KeyEvent evt)
{
switch (evt.key)
{
case KeyCode.KC_1:
move = !move;
break;
case KeyCode.KC_2:
animate = !animate;
break;
}
return base.OnKeyPressed(evt);
}
}
}

McDonte

28-03-2011 19:07:03

Hey Acheron,

I finished the first tutorial. I didn't use your code because mine was already placed in the wiki but for the second tutorial I will use yours :D Please check the new tutorial, you and everybody else, to find any errors.

When it's fine we could move it from the current site to the place of the current intermediate tutorials:

Now: New Mogre Intermediate Tutorial 1

tafkag

29-03-2011 08:52:32

Hey McDonte,

great job on the turorial!
I noticed one minor thing: you wrote...

The name of the animation is chosen by the animator when they create the animation and it is stored in the mesh file.

...which would be true for vertex animations. The robot uses skeletal animations though, which are stored in the robot.skeleton file.

McDonte

29-03-2011 12:58:20

I noticed one minor thing
Thanks tafkag, I've already changed it to:
The name of the animation is chosen by the animator when they create the animation and it is stored in the .mesh file for vertex animations and in the .skeleton file for skeletal animations.
I hope now it's all right. Actually I'm not an expert with animation stuff, I just copied the passage from the OgreDotNet tutorial.

Tubulii

07-04-2011 10:21:15

Thanks for sharing!!


Most of us (the Mogre users) came from c++ Ogre so usually we have all the tutorials behind us.
Also most questions are Ogre related, so don't expect a flood of post on this forum.


Since Mogre was created for ease of use, this should be something everyone benefits from, including of course people that know c# and not Ogre / c++.
If someone has to learn Ogre in C++ before they can start working with Mogre then that pretty much defeats the whole purpose and restricts the audience down to a minimum.


I agree, and I think the most important thing is: community supports community. And these tutorials are always helpfull ;)

wiso

25-04-2011 15:45:29

Hello,
Just went through the initial tutorials for MOGRE and just found these translated Intermediate tuts. Thanks a lot for the effort of translating them! I look forward to the others, but for now, I think I have enough to build my first scene.

Thanks again!