Page 1 of 1

[Camera & Nodes] Trouble with Diablo-like-Cam

Posted: Mon Mar 20, 2017 11:18 pm
by Notion
Hey everyone!
I recently started with Irrlicht and enjoy it alot so far. But right now Im pretty much stuck, trying to set up a Camera that basically works like in most Hack n Slay Games (Diablo II for example): While the Camera follows the Position of the PlayerCharacter, it does NOT rotate with the PlayerCharacter, but keeps its rotation and offset relative to the playercharacter.

I hope you know what I try to describe, if you dont, please let me know!

So I came up with the following Code, which should do: Create an Empty Node with fixed rotation. Make the CameraNode the Child of the Non-Rotating EmptyNode. Load a MeshNode and make it a child of the EmptyNode, so the Parent of Camera and Mesh are the same. This should result in both moving in exact the same way once the EmptyNode is moved, right? But it doesnt really work: Moving the Empty Node on the x-axis actually makes either the camera or the model rotate in some weird angle around the other, before making the model completely disappear from the cams view.

(Shortening the code, since the full programm uses a rather large but pretty foolproof structure)

Code: Select all

 
//Declarations
IrrlichtDevice *device;
IVideoDriver* driver;
ISceneManager* smgr;
IGUIEnvironment* guienv;
 
//Cam and Node
    ISceneNode* playerPositionNode; //THIS is basically gonna be the parent to Model and Cam.
    ICameraSceneNode *cam;
 
 
 int main() {
 
 
 
    //Setup Device
                                        
    device = createDevice(video::EDT_OPENGL, dimension2d<u32>(1920, 1080), 32, true, false, true, &receiver);
 
    //Setup Window
    device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
 
    driver = device->getVideoDriver();
    smgr = device->getSceneManager();
    guienv = device->getGUIEnvironment();
 
    //Setup PlayerPositionNode
    playerPositionNode = smgr->addEmptySceneNode();
 
    //Add Camera
    playerPositionNode->addChild(smgr->addCameraSceneNode(0, vector3df(0, 50, -40), vector3df(0, -30, 0)));
 
 
//Loading Model
    IAnimatedMesh* mesh = smgr->getMesh(path + ".md2");
    playerPositionNode->addChild(node = smgr->addAnimatedMeshSceneNode(mesh)); //THIS line is probably important?
 
    //Setting Textures and Animations
    if (node)
    {
        node->setMaterialFlag(EMF_LIGHTING, false);
        node->setMD2Animation(scene::EMAT_STAND);
        node->setMaterialTexture(0, driver->getTexture(path + ".bmp"));
        irr::core::vector3df tempvec(0, 0, 0); 
        node->setPosition(tempvec);
    }
 
while(true)
{
input();
update();
}
 
}
 
irr::f32 x;
void update() {
 
    playerPositionNode->setPosition(irr::core::vector3df(0+x, 0, 0));
 
}
 
void input(){
x++;
}
 

Re: [Camera & Nodes] Trouble with Diablo-like-Cam

Posted: Mon Mar 20, 2017 11:53 pm
by CuteAlien
Not an example that compiles and can be used for testing. I get what you try to do in theory and it might work (don't want to write my own example now for testing as I need to sleep soon).

But maybe just use a simpler solution. Use your player-node and camera-node, forget about that empty node. Then control your player however you want and update the camera manually. Do something like that in your update:

Code: Select all

 
irr::core::vector3df targetPos(  player->getAbsolutePosition() );
camera->setTarget(targetPos );
camera->updateAbsolutePosition(); // just to be save as setting target and position can influence each other
camera->setPosition( targetPos + irr::core::vector3df( 0, 50, -40) );
 
As long as you use a fixed distance it won't care what rotations your target does.

Re: [Camera & Nodes] Trouble with Diablo-like-Cam

Posted: Tue Mar 21, 2017 12:29 am
by Notion
Thanks alot for your fast response! I fixed the code to make it compileable, you probably just need to adjust the path/name of the model file. (Code below). I tried the solution you suggested as well, and it basically does what I want, but when I start moving the character, it changes the offset to the cam a tiny bit until the movement stops. It looks kinda work-around-like and I try to avoid that. Thanks none the less!

Code: Select all

 
 
#include "MainClass.h"
#include <irrlicht.h>
#include <vector>
 
 
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
 
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
using namespace std;
 
//Declarations
IrrlichtDevice *device;
IVideoDriver* driver;
ISceneManager* smgr;
IGUIEnvironment* guienv;
 
//Cam and Node
ISceneNode* playerPositionNode; //THIS is basically gonna be the parent to Model and Cam.
ICameraSceneNode *cam;
 
 
void update();
void input();
void draw();
 
int main() {
 
 
 
    //Setup Device
 
    device = createDevice(video::EDT_OPENGL, dimension2d<u32>(1920, 1080), 32, true, false, true, 0);
 
    //Setup Window
    device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
 
    driver = device->getVideoDriver();
    smgr = device->getSceneManager();
    guienv = device->getGUIEnvironment();
 
    //Setup PlayerPositionNode
    playerPositionNode = smgr->addEmptySceneNode();
 
    //Add Camera
    playerPositionNode->addChild(smgr->addCameraSceneNode(0, vector3df(0, 50, -40), vector3df(0, -30, 0)));
 
    IAnimatedMeshSceneNode* node;
 
    //Loading Model
    IAnimatedMesh* mesh = smgr->getMesh( "Res/sydney.md2");
    playerPositionNode->addChild(node = smgr->addAnimatedMeshSceneNode(mesh)); //THIS line is probably important?
 
                                                                               //Setting Textures and Animations
    if (node)
    {
        node->setMaterialFlag(EMF_LIGHTING, false);
        node->setMD2Animation(scene::EMAT_STAND);
        node->setMaterialTexture(0, driver->getTexture("Res/sydney.bmp"));
        irr::core::vector3df tempvec(0, 0, 0);
        node->setPosition(tempvec);
    }
 
    while (true)
    {
        input();
        update();
        draw();
    }
 
}
 
 
irr::f32 x;
void update() {
 
    playerPositionNode->setPosition(irr::core::vector3df(0 + x, 0, 0));
 
}
 
void input() {
    x++;
}
 
void draw() {
 
    driver->beginScene(true, true, SColor(255, 0, 0, 0));
 
    smgr->drawAll();
    guienv->drawAll();
 
    driver->endScene();
 
 
}

Re: [Camera & Nodes] Trouble with Diablo-like-Cam

Posted: Tue Mar 21, 2017 12:42 am
by CuteAlien
Please copy your example code over one of the examples and just press compile. That way you quickly can test if it compiles (I have to stop for today, so won't test anymore - but pretty certain code above at least does miss includes and namespaces).

Re: [Camera & Nodes] Trouble with Diablo-like-Cam

Posted: Tue Mar 21, 2017 1:25 am
by Notion
Fixed the namespaces and includes, should work now. :)

Re: [Camera & Nodes] Trouble with Diablo-like-Cam

Posted: Tue Mar 21, 2017 10:31 am
by CuteAlien
Your problem is that this only updates camera position, but not the camera target. So it still looks at the old place.

So do something like this (the line with cam->setTarget, other changes don't matter):

Code: Select all

 
#include <irrlicht.h> 
 
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
 
int main() 
{
    //Setup Device
    IrrlichtDevice *device = createDevice(video::EDT_OPENGL, dimension2d<u32>(800, 600));
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager*smgr = device->getSceneManager();
 
    //Setup PlayerPositionNode
    ISceneNode* playerPositionNode = smgr->addEmptySceneNode();
 
    //Add Camera
    irr::core::vector3df camDistance(0, -30, 0);
    ICameraSceneNode *cam = smgr->addCameraSceneNode(playerPositionNode, vector3df(0, 50, -40), camDistance);
 
    //Loading Model
    IAnimatedMesh* mesh = smgr->getMesh( "../../media/sydney.md2");
    IAnimatedMeshSceneNode* node= smgr->addAnimatedMeshSceneNode(mesh, playerPositionNode);
 
    if (node)
    {
        node->setMaterialFlag(EMF_LIGHTING, false);
        node->setMD2Animation(scene::EMAT_STAND);
        node->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp"));
    }
 
    irr::f32 x=0;
    while (device->run())
    {
        x ++;
        playerPositionNode->setPosition(irr::core::vector3df(0 + x, 0, 0));
        cam->setTarget( playerPositionNode->getPosition() + camDistance );
 
        driver->beginScene(true, true, SColor(255, 0, 0, 0));
 
        smgr->drawAll();
 
        driver->endScene();
    }
}
 
(.. and examples that go fullscreen, go black within a second and can't be ended easily because you removed the device->run()...very evil!!!)