Custom Maya Camera Animator

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
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Custom Maya Camera Animator

Post by Mel »

Ever felt that you wanted to click on something on a scene but suddenly you've started to move the camera because you were using a Maya Camera Animator? Well, this animator solves that issue by forcing also the usage of the control key. That is, to move the camera just like the maya animator, you also have to press the control key, or else, the camera won't move, and the events will slip away further into the events system, perhaps catching up with any click routine you've provided.

It has an onEvent routine which must be provided to Irrlicht somehow, so it can be part of another event receiver. Also, fixes a limitation of the Maya animator when moving the camera forward, this also moves the target forward, so, it never is really too close to the target to produce odd motions. And adds another completely new feature by allowing to zoom in and out using the wheel. It also doesn't have gimbal lock because the up vector is constantly updated, so the view matrix is always kept orthogonal, allowing for any rotation to take place freely.

Features:

Orbit the camera around the camera target with CTRL+LMB.

Pan the camera with CTRL+RMB

Dolly (Moves forward and backward) the camera with CTRL+MMB or RMB+LMB

Zoom in and out (opens and closes the camera FOV) with CTRL+wheel up or down (ranges from a 120 degrees fov to a 5 degrees fov in 5 degrees steps)

Header

Code: Select all

 
#ifndef _CUSTOMMAYAANIMATOR_H_
#define _CUSTOMMAYAANIMATOR_H_
 
#include <irrlicht.h>
 
    class customMayaAnimator : public virtual irr::scene::ISceneNodeAnimator
    {
        irr::core::vector2di currentMousePos;
        irr::core::vector2di lastMousePos;
        irr::core::vector2di deltaMousePos;
        irr::f32 mouseMotionSensitivity;
        irr::f32 mouseRotationSensitivity;
        irr::f32 cameraFOV;
 
        bool LMPressed;
        bool RMPressed;
        bool MBPressed;
        irr::f32 wheelMotion;
 
        irr::u32 currentTime;
        irr::u32 lastTime;
        irr::f32 deltaTime;
 
    public:
        customMayaAnimator();
        
        ~customMayaAnimator();
 
        bool OnEvent(const irr::SEvent& event);
 
        void animateNode(irr::scene::ISceneNode* node, irr::u32 timeMs);
 
        irr::scene::ISceneNodeAnimator* createClone(irr::scene::ISceneNode* node, irr::scene::ISceneManager* newManager = 0);
    };
 
 
#endif
 
Source

Code: Select all

 
#include "customMayaAnimator.h"
 
using namespace irr;
 
    customMayaAnimator::customMayaAnimator()
    {
        LMPressed = RMPressed = MBPressed = false;
        currentTime = lastTime = 0;
        deltaTime = 0.0f;
        mouseMotionSensitivity = 10.0f;
        mouseRotationSensitivity = 50.0f;
        cameraFOV = 60.0f;
    }
 
    customMayaAnimator::~customMayaAnimator()
    {
 
    }
 
    bool customMayaAnimator::OnEvent(const SEvent& event)
    {
        bool result = false;
        switch (event.EventType)
        {
        case EET_MOUSE_INPUT_EVENT:
            switch (event.MouseInput.Event)
            {
            case EMIE_LMOUSE_PRESSED_DOWN:
                LMPressed = true & event.MouseInput.Control;
                if (LMPressed)
                    result = true;
                break;
            case EMIE_RMOUSE_PRESSED_DOWN:
                RMPressed = true & event.MouseInput.Control;
                if (RMPressed)
                    result = true;
                break;
            case EMIE_MMOUSE_PRESSED_DOWN:
                MBPressed = true & event.MouseInput.Control;
                if (MBPressed)
                    result = true;
                break;
            case EMIE_LMOUSE_LEFT_UP:
                LMPressed = false & event.MouseInput.Control;
                break;
            case EMIE_RMOUSE_LEFT_UP:
                RMPressed = false & event.MouseInput.Control;
                break;
            case EMIE_MMOUSE_LEFT_UP:
                MBPressed = false & event.MouseInput.Control;
                break;
            case EMIE_MOUSE_MOVED:
                lastMousePos = currentMousePos;
                if (event.MouseInput.Control)
                {
                    LMPressed = event.MouseInput.isLeftPressed();
                    RMPressed = event.MouseInput.isRightPressed();
                    MBPressed = event.MouseInput.isMiddlePressed();
                    currentMousePos.X = event.MouseInput.X;
                    currentMousePos.Y = event.MouseInput.Y;
                    result = true;
                }
                deltaMousePos = currentMousePos - lastMousePos;
                break;
            case EMIE_MOUSE_WHEEL: //Increase or decrease speed sensitivity?
                if (event.MouseInput.Control)
                    wheelMotion = event.MouseInput.Wheel;
                break;
 
            case EMIE_LMOUSE_DOUBLE_CLICK:
            case EMIE_RMOUSE_DOUBLE_CLICK:
            case EMIE_MMOUSE_DOUBLE_CLICK:
            case EMIE_LMOUSE_TRIPLE_CLICK:
            case EMIE_RMOUSE_TRIPLE_CLICK:
            case EMIE_MMOUSE_TRIPLE_CLICK:
                break;
            }
            break;
        }
 
        return result;
    }
 
    void customMayaAnimator::animateNode(scene::ISceneNode* node, u32 timeMs)
    {
        if (node->getType() != scene::ESNT_CAMERA)
            return;
 
        lastTime = currentTime;
        currentTime = timeMs;
        deltaTime = (currentTime - lastTime)/1000.0f; //What if we take less than 1 msec to render a new frame? O.o
        deltaTime = deltaTime == 0.0f ? 0.001f : deltaTime; //The animator may run out of "time" if the frame speed is just too fast (a low load scene, or an empty scene, for instance)
        //A better measurement would be the inverse of the frames per second stat from the video driver, so perhaps it could be wise to resort to that just in case
 
        scene::ICameraSceneNode* camera = (scene::ICameraSceneNode*)node;
        core::vector3df up = camera->getUpVector();
        core::vector3df view = (camera->getTarget() - camera->getPosition()).normalize();
        core::vector3df right = view.crossProduct(up).normalize();
        up = right.crossProduct(view).normalize();
 
        if (LMPressed & !RMPressed)//Orbit camera
        {
            camera->setPosition(camera->getPosition() + (right*deltaMousePos.X + up*deltaMousePos.Y)*deltaTime*mouseRotationSensitivity);
            camera->setUpVector(up);
        }
 
        if (RMPressed & !LMPressed)//Pan camera
        {
            camera->setPosition(camera->getPosition() + (right*deltaMousePos.X + up*deltaMousePos.Y)*deltaTime*mouseMotionSensitivity);
            camera->setTarget(camera->getTarget() + (right*deltaMousePos.X + up*deltaMousePos.Y)*deltaTime*mouseMotionSensitivity);
        }
 
        if (RMPressed & LMPressed || MBPressed) //Dolly Camera
        {
            camera->setPosition(camera->getPosition() + view*deltaMousePos.X*deltaTime*mouseMotionSensitivity);
            camera->setTarget(camera->getTarget() + view*deltaMousePos.X*deltaTime*mouseMotionSensitivity);
        }
 
        if (abs(wheelMotion) > 0.0f)//ZOOM Camera
        {
            cameraFOV -= wheelMotion*5.0f;
            cameraFOV = cameraFOV < 5 ? 5 : cameraFOV>120 ? 120 : cameraFOV;
            camera->setFOV(cameraFOV*core::DEGTORAD);
        }
 
        wheelMotion = 0.0f;
        deltaMousePos = core::vector2di();
    }
 
    scene::ISceneNodeAnimator* customMayaAnimator::createClone(scene::ISceneNode* node, scene::ISceneManager* newManager)
    {
        return new customMayaAnimator;
    }
 
You have to create a new customMayaAnimator and assign it to any camera for it to work, but remember, for the camera animator to work you have to press the CONTROL KEY! or else the camera won't move, and the events will slip away. And you have to create your custom event receiver that passes the events to this animator.
Last edited by Mel on Wed Oct 26, 2016 11:49 pm, edited 2 times in total.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Custom Maya Camera Animator

Post by Vectrotek »

This is something so cool it should be incorporated in the next major Irrlicht version! :D
I got the code for later!
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Custom Maya Camera Animator

Post by Mel »

Hmm... i've rectified the part where said it wasn't necesary to have an event receiver for this animator, actually, it is necesary. But the good part is that animators inherit from the event reciever interface themselves, so that part is half done.

You have to create an event receiver that simply passes the event to this animator. If it is processed, it will return true, otherwise, false, and you will be able to process it further... my bad, you need an event receiver, after all... it is fixed in the first post.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Custom Maya Camera Animator

Post by Vectrotek »

Cool!
mzadmzad
Posts: 3
Joined: Sun Mar 21, 2021 4:56 pm

Re: Custom Maya Camera Animator

Post by mzadmzad »

is there any simple example or any example of using Custom Maya Camera Animator......
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Custom Maya Camera Animator

Post by CuteAlien »

To use camera animators create a camera (addCameraSceneNode, just like in first example). Then create the animator with new and add it to the camera with addAnimator.

Irrlicht does the same internally (for example in CSceneManager::addCameraSceneNodeMaya in CSceneManager.cpp).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
mzadmzad
Posts: 3
Joined: Sun Mar 21, 2021 4:56 pm

Re: Custom Maya Camera Animator

Post by mzadmzad »

Trying in this way......but still not working......just a corner view of model with no movement/zoom or any effects of mouse with/without CTRL button

Code: Select all

    ICameraSceneNode* Camera_2 = smgr->addCameraSceneNode();
    //Camera_2->setPosition(core::vector3df(0,0,0));
    //Camera_2->setTarget(core::vector3df(200.f, 100.f, 150.f));
    //Camera_2->setRotation(core::vector3df(0,0,0));
 
    if (Camera_2)
    {
        customMayaAnimator* anm = new customMayaAnimator();
        Camera_2->addAnimator(anm);
        anm->drop();
    }
 
    smgr->setActiveCamera(Camera_2);
Anyone with working example :|
Post Reply