Object Orbiting Camera (Mouse Controlled)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Object Orbiting Camera (Mouse Controlled)

Post by Midnight »

EDIT : Added a demo file since I made it for a friend.
It has a skydome so you can see the rotation of the camera better aswell.


Download that here!

I'm so proud of myself this thing was a pain to get working.

Well anyways I decided to share it. hooray me!


I owe vitek some credit for the math calculations but I added the mouse control for it which is a bit unfinished but useful.

you can view that here also contains the keyboard version in that thread.



Code: Select all

#include <irrlicht.h>
#pragma comment(lib, "Irrlicht.lib")

using namespace irr;
using namespace gui;
using namespace core;
using namespace scene;
using namespace video;


IrrlichtDevice *device;
ISceneManager* smgr;
IVideoDriver* driver;
ICursorControl* CursorControl;

position2d<f32> Cursor;
position2d<f32> OldCursor;
position2d<f32> CursorDiff;

ISceneNode* box;
ICameraSceneNode* cam;

u32 now;
u32 oldNow;
f32 Elapsed;

vector3df offset;

f32 Radius;
f32 Theta; // degrees
f32 Phi; // degrees

f32 LinearVelocity = 5.f;
f32 AngularVelocity = 5.f;


class MyEventReceiver : public IEventReceiver
{
public:

    MyEventReceiver(){}
    virtual ~MyEventReceiver(){}

   // you may need to change the parameter type depending on your Irrlicht version
    virtual bool OnEvent(SEvent event)
    {
        if (event.EventType == EET_MOUSE_INPUT_EVENT)
        {
            if(event.MouseInput.Event == EMIE_MOUSE_MOVED)
            {
                Cursor.X = event.MouseInput.X;
                Cursor.Y = event.MouseInput.Y;
            }

            if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
            {
            }
        }
        return false;
    }
};

int main()
{
    // create device otherwise quit if creation failed
    device = createDevice(EDT_OPENGL, dimension2d<s32>(800, 600), 32, false, false, false);
    if (device == 0)
    return false; // could not create selected driver.

    MyEventReceiver receiver;
    device->setEventReceiver(&receiver);

    driver = device->getVideoDriver();
    smgr = device->getSceneManager();

    // the thing we want to look at
    box = smgr->addCubeSceneNode();

    // add camera
    cam = smgr->addCameraSceneNode(box);
    cam->setTarget( box->getAbsolutePosition() );

    Radius = 20.f;
    Theta  = 180.f; // degrees
    Phi    = 90.f; // degrees

    // add a dynamic light
    smgr->addLightSceneNode(0, core::vector3df(-20, 0, 0), video::SColorf(1.f, 0.f, 0.f, 1.f));
    smgr->addLightSceneNode(0, core::vector3df(0, -20, 0), video::SColorf(0.f, 1.f, 0.f, 1.f));
    smgr->addLightSceneNode(0, core::vector3df(0, 0, -20), video::SColorf(0.f, 0.f, 1.f, 1.f));


    oldNow = device->getTimer()->getRealTime();

    while(device->run())
    {
        // calculate elapsed time as fractional seconds
        now = device->getTimer()->getRealTime();
        Elapsed = (now - oldNow) / 1000.f;
        oldNow = now;


        // window is active, so render scene
        if (device->isWindowActive())
        {
            //everything before this is prerender
            if (driver->beginScene(true, true, video::SColor(255, 0, 0, 100)))
            {

                smgr->drawAll();

                //everything after this is post render
                driver->endScene();
            }

    //       // adjust camera position based on current key input
    //         if (zoom in)
    //            Radius -= (LinearVelocity * Elapsed);
    //         if (zoom out)
    //            Radius += (LinearVelocity * Elapsed);


        if(Cursor.X != OldCursor.X)
        {
            Theta += ((AngularVelocity * Elapsed) + (Cursor.X - OldCursor.X) / 2);
        }
        if(Cursor.Y != OldCursor.Y)
        {
            Phi += ((AngularVelocity * Elapsed) + (Cursor.Y - OldCursor.Y) / 2);
        }

        OldCursor = Cursor;


//         if (reset)
//         {
//            Theta = 180.f;
//            Phi   = 90.f;
//         }

         // prevent camera from walking into our box
        float MinZoom = 10.f;
        if (Radius < MinZoom)
            Radius = MinZoom;

        // lame ***** gimble lock prevention. if you don't want to do this
        // you need to adjust the up vector of the camera so it never is
        // parallel to the look at vector
        if (Phi < 1.f)
            Phi = 2.f;
        else if (179.f < Phi)
                 Phi = 178.f;

        if (Theta < 0.f)
            Theta = 360.f;
        else if (360.f < Theta)
                 Theta = 0.f;

        f32 sinOfPhi = sinf(Phi * DEGTORAD);
        f32 cosOfPhi = cosf(Phi * DEGTORAD);

        f32 sinOfTheta = sinf(Theta * DEGTORAD);
        f32 cosOfTheta = cosf(Theta * DEGTORAD);


        // these are switched around a little from what i posted above
        offset.X = Radius * sinOfTheta * sinOfPhi;
        offset.Y = Radius * cosOfPhi;
        offset.Z = Radius * cosOfTheta * sinOfPhi;

        // camera is a child of the cube, so our offset is actually
        // the position of the camera
        cam->setPosition(offset);
        cam->setTarget( box->getAbsolutePosition() );
        cam->updateAbsolutePosition();


        wchar_t caption[128];
        swprintf(caption, 128, L"r=%f theta=%f phi=%f", Radius, Theta, Phi);

        device->setWindowCaption(caption);
        }
    }

    device->drop();

return 0;
}
Enjoy! 8)
Last edited by Midnight on Wed Dec 27, 2006 4:02 am, edited 3 times in total.
varnie
Posts: 31
Joined: Wed Jul 19, 2006 8:27 pm
Location: Russia, Ural

Post by varnie »

hello, Midnight.
i got two errors during trying to compile your code.
first was '77 C:\delme\orbiting_camera.cpp 'class irr::scene::ISceneManager' has no member named 'addCubeSceneNode.
i changed in line 77

Code: Select all

// the thing we want to look at 
box = smgr->addCubeSceneNode();
on the following:

Code: Select all

// the thing we want to look at 
    box = smgr->addTestSceneNode(); 
and it fixed:)

but the second one is about

Code: Select all

f32 sinOfPhi = sinf(Phi * DEGTORAD); 
f32 cosOfPhi = cosf(Phi * DEGTORAD); 
f32 sinOfTheta = sinf(Theta * DEGTORAD); 
f32 cosOfTheta = cosf(Theta * DEGTORAD); 
my compiler gives me an error: '159 C:\delme\orbiting_camera.cpp `DEGTORAD' undeclared (first use this function) '.

where i have to define this DEGTORAD? thanks for answer!
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You are getting both problems because you are using an old version of Irrlicht. The addTestSceneNode function was renamed to addCubeSceneNode a few revisions back. The constant DEGTORAD is defined in irrMath.h, but the version you have is out of date.

You could just add this to the top of orbiting_camera.cpp

Code: Select all

#define DEGTORAD (3.14159f / 180)
varnie
Posts: 31
Joined: Wed Jul 19, 2006 8:27 pm
Location: Russia, Ural

Post by varnie »

vitek, thanks for info. i have to download the latest Irrlicht version then.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

actually this version is 1.1 but 1.2 should work the demo uses a 1.1 dll

sup vitek 8)
Post Reply