Thursday, December 17, 2009

Irrlicht – my third person camera

Currently I work on my own RPG game and I hope after gaining enough experience with it I’ll try to make my own MMORPG. Am I humble enough?

There are many MMORPG games on the market and all of them can work as an inspiration. My first task was to make a third person camera or more precisely third person camera animator. You don’t need to make an animator to use this logic. Creating an animator leads to some complications that I won’t discuss here.

We will use the right mouse button to orbit around the object and the scroller to zoom in and out. You need to add something like this in your event receiver or in OnEvent function of the animator:

 case EMIE_RMOUSE_PRESSED_DOWN:
  MouseKeys[2] = true;

  break;
 case EMIE_RMOUSE_LEFT_UP:
  MouseKeys[2] = false;

  break;
 case EMIE_MOUSE_MOVED:
  MousePos = CursorControl->getRelativePosition();

  break;
 case EMIE_MOUSE_WHEEL:
  Zoom = Zoom + event.MouseInput.Wheel*ZoomSpeed;

  if (Zoom < TargetMinDistance)
   Zoom = TargetMinDistance;

  if (Zoom > TargetMaxDistance)
      Zoom = TargetMaxDistance;

Now, when we have the input data, we must implement the logic. You must add this in animateNode function of your animator, or in some update method if you don’t use an animator.

 core::vector3df target = targetNode->getPosition();

 f32 nRotX = RotX;
 f32 nRotY = RotY;

 if (isMouseKeyDown(2))
 {
  if (!Rotating)

  {
   RotateStart = MousePos;
   Rotating = true;

   nRotX = RotX;
   nRotY = RotY;
  }

  else
  {
   nRotX += (RotateStart.X - MousePos.X) * RotateSpeed;

   nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;

  }
 }
 else if(Rotating)
 {

  RotX += (RotateStart.X - MousePos.X) * RotateSpeed;

  RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;

  nRotX = RotX;
  nRotY = RotY;
  Rotating = false;

 }

 target = targetNode->getPosition();

 Pos.X = Zoom + target.X;
 Pos.Y = Zoom + target.Y;

 Pos.Z = target.Z;

 Pos.rotateXYBy(nRotY, target);

 Pos.rotateXZBy(-nRotX, target);

 camera->setPosition(Pos);

 camera->setTarget(target); 

This is very basic functionality but you will grasp the logic. I’ve used the Maya animator the get the idea. My code have a nasty flip on the top and the bottom, you can fix it if you want with restricting the camera movement or changing the up vector. And don’t make the camera parent or child of the target.

Saturday, November 7, 2009

Blender – more than 3D

Blender is quite popular, open-source, graphics software released under the GNU General Public License. It is used in many projects – commercial or other, and can be a good choice for resource creation.


Blender has many nice features for modeling, rendering and animation of 3D characters and scenes.

Blender is relatively complex and difficult for newbies. If you intent to learn blender you need to equip yourself with some patience.

Animation with Blender - Best Character Animation for Suzanne Awards 2009.

Saturday, October 31, 2009

Irrlicht Engine - Easy Tutorial – Basics

This post is part of my tutorial on how to use Irrlicht Engine and a continuation to the article Irrlicht Engine - Easy Tutorial – Intro.

Let’s view the example I used in the previous post. Here is the code:

#include <irrlicht.h>

using namespace irr;

using namespace core;
using namespace scene;
using namespace video;

using namespace io;
using namespace gui;

int main()

{
 IrrlichtDevice *device = createDevice(
   video::EDT_OPENGL,
   dimension2d<u32>(800, 600),
   16, false, false, false, 0);

 if (!device)
  return 1;

 IVideoDriver* driver = device->getVideoDriver();

 ISceneManager* sceneManager =
   device->getSceneManager();

 sceneManager->addCameraSceneNode();

 while(device->run())

 {
  driver->beginScene(
    true, true, SColor(255,50,130,50));

  sceneManager->drawAll();
  driver->endScene();
 }

 device->drop();
 return 0;
}


This is a very basic application. First thing we need to do is to create Irrlicht device with the createDevice function. The first parameter is video::E_DRIVER_TYPE type and can be video::EDT_DIRECT3D9, video::EDT_DIRECT3D8, video::EDT_OPENGL, video::EDT_NULL, video::EDT_SOFTWARE, video::EDT_BURNINGSVIDEO. I’ll use video::EDT_OPENGL because my Irrlicht binaries are from the official site and they are not built with DirectX. (And I am lazy.)

Next parameter as you can assume is the window size. I won’t discuss the other parameters now as they are not important for my tutorial. In fact I can call createDevice this way:

IrrlichtDevice *device = createDevice(

   video::EDT_OPENGL,
   dimension2d<u32>(800, 600));

When you finish using the device don’t forget to call:
device->drop(); 
You can learn more for the Irrlicht device class here - http://irrlicht.sourceforge.net/docu/classirr_1_1_irrlicht_device.html.

And now the cool part – the scene manager object. It manages the scene nodes, meshes, cameras, lights and so on. Your scene is represented as a hierarchical scene graph.
You obtain a reference to the scene manager object through the call:

device->getSceneManager();

Let’s do something fun with our example. I’ll change our camera to FPS mode – FPS camera in Irrlicht is a camera node suited for a first person shooter. It moves with the arrows and rotates with the mouse.
I’ll add some simple scene nodes as cube and sphere.

To add a FPS camera we must call:
ICameraSceneNode *camera = sceneManager->addCameraSceneNodeFPS();

Our cube:
ISceneNode *cube = sceneManager->

        addCubeSceneNode(15.0f, 0, -1, core::vector3df(150,10,10));

To make the camera look at the cube:
camera->setTarget(cube->getAbsolutePosition());

I’ll add a light source with the default parameters. Without it our objects will look ugly and black. Now they will be ugly but with some light on the front side.

Here is the full code:
#include <irrlicht.h>

using namespace irr;

using namespace core;
using namespace scene;
using namespace video;

using namespace io;
using namespace gui;

int main()

{
 IrrlichtDevice *device = createDevice(
   video::EDT_OPENGL,
   dimension2d<u32>(800, 600));

 if (!device)
  return 1;

 IVideoDriver* driver = device->getVideoDriver();

 ISceneManager* sceneManager =
   device->getSceneManager();

 ICameraSceneNode *camera =
   sceneManager->addCameraSceneNodeFPS();

 ISceneNode *cube = sceneManager->
   addCubeSceneNode(15.0f, 0, -1,
     core::vector3df(150,10,10));

 sceneManager->addSphereSceneNode(
   5.0f, 16, 0, -1,
   core::vector3df(100,30,10));

 sceneManager->addLightSceneNode();

 camera->setTarget(cube->getAbsolutePosition());

 while(device->run())
 {
  driver->beginScene(

    true, true, SColor(255,50,130,50));

  sceneManager->drawAll();
  driver->endScene();
 }

 device->drop();
 return 0;
} 
 
 

And the result