Disable of scaling child node.

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
svedach
Posts: 20
Joined: Fri Oct 14, 2016 12:22 pm

Disable of scaling child node.

Post by svedach »

Is it possible to disable or compensate of scaling child node when the assignment of its parent?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Disable of scaling child node.

Post by CuteAlien »

Dividing scale values by 1./scale should work I think (interestingly Irrlicht doesn't seem to have a function yet to divide a scalar by a vector, but only the other way round - so you have to do it component wise for now).

At least seems to work in my simple test:

Code: Select all

 
#include <irrlicht.h>
 
using namespace irr;
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
 
int main(int argc, char *argv[])
{
    IrrlichtDevice * Device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(640,480) );
    if (!Device)
        return false;
    
    scene::ISceneManager* smgr = Device->getSceneManager();
    gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
    video::IVideoDriver* videoDriver =  Device->getVideoDriver();   
 
    smgr->addCameraSceneNodeFPS(0, 20.f, 0.1f );
 
    irr::core::vector3df scale(20.f, 10.f, 3.f);
    
    irr::scene::ISceneNode * parent = smgr->addCubeSceneNode (10.0f, 0, -1, 
                            core::vector3df(0, 20, 100),
                            core::vector3df(45, 45, 45),
                            scale);
    parent->getMaterial(0).Lighting = false;
    
    irr::scene::ISceneNode * child = smgr->addCubeSceneNode (10.0f, 0, -1, 
                            core::vector3df(0, 20, 100),
                            core::vector3df(0, 0, 0),
                            core::vector3df(1.0f/scale.X, 1.0f/scale.Y, 1.0f/scale.Z));
    child->getMaterial(0).Lighting = false;
    child->setParent(parent);
 
    while ( Device->run() )
    {
        if ( Device->isWindowActive() )
        {
            videoDriver->beginScene(true, true);
 
            smgr->drawAll();
            guiEnv->drawAll();
 
            videoDriver->endScene();
        }
        Device->sleep( 1 );
    }
    
    Device->closeDevice();
    Device->drop();
    
    return 0;
}
 
 
edit: And no - can't be disabled. Thought you can also use a flat scenegraph and do the parent/child computations yourself.
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
svedach
Posts: 20
Joined: Fri Oct 14, 2016 12:22 pm

Re: Disable of scaling child node.

Post by svedach »

Thanks for the quick reply, but somehow it does not work. I add child node with a turn and it is distorted (child node is created as g_GraphicalWorld-> SceneManager () -> addMeshSceneNode (.....); bluish transparent tetrahedron shown in figure is child node).If turn the child node relative parent is set to 0 on all axes, then no distortion and correct scale.

Image

But if you turn a child node, its display distorted, so 30 degrees of rotation axis Y - is on image.

Image

I think that this is due to different axes of child node relative parent node, and accordingly the scale used is not correct. By this I would like to simply prohibit the use of the scale of the parent node to the child.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Disable of scaling child node.

Post by CuteAlien »

Sorry, I need a test-case to reproduce it. Can you can adapt my code above to show the problem? I can't see what's wrong in the code from images.
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
svedach
Posts: 20
Joined: Fri Oct 14, 2016 12:22 pm

Re: Disable of scaling child node.

Post by svedach »

Please try this:

Code: Select all

 
#include "stdafx.h"
#include <irrlicht.h>
 
using namespace irr;
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
int main()
{
    IrrlichtDevice * Device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(1280,1024) );
    if (!Device)
        return false;
 
    scene::ISceneManager* smgr = Device->getSceneManager();
    gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
    video::IVideoDriver* videoDriver =  Device->getVideoDriver();   
    smgr->setAmbientLight(video::SColorf(0.4f, 0.4f, 0.35f, 0.0f));
    smgr->addLightSceneNode(0, core::vector3df(0, 2000, -1000), video::SColorf(0.7f, 0.7f, 0.4f, 1.0f), 1000);
    smgr->addCameraSceneNodeFPS(0, 200.f, 0.1f );
 
    irr::core::vector3df scale(2.f, 1.f, 0.3f);
 
    irr::scene::ISceneNode * parent = smgr->addCubeSceneNode (10.0f, 0, -1, 
        core::vector3df(0, 0, 100),
        core::vector3df(0, 0, 0),
        scale);
    parent->getMaterial(0).Lighting = true;
    parent->getMaterial(0).AmbientColor = video::SColor(0, 200, 0, 0);
 
    irr::scene::ISceneNode * child = smgr->addCubeSceneNode (30.0f, 0, -1, 
        core::vector3df(0, 0, 50),
        core::vector3df(0, 10, 0),
        core::vector3df(1/scale.X, 1/scale.Y, 1/scale.Z));
    child->getMaterial(0).Lighting = true;
    child->getMaterial(0).AmbientColor  = video::SColor(0, 0, 200, 0);
 
    child->setParent(parent);
 
    while ( Device->run() )
    {
        if ( Device->isWindowActive() )
        {
            videoDriver->beginScene(true, true);
 
            smgr->drawAll();
            guiEnv->drawAll();
 
            videoDriver->endScene();
        }
        Device->sleep( 1 );
    }
 
    Device->closeDevice();
    Device->drop();
 
    return 0;
}
 
Child green Rect is distorted.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Disable of scaling child node.

Post by CuteAlien »

Hm, the scale is probably along the direction of the rotated original node. I even remember now I had to work around that once ... it's possible, but in the end I didn't use it because it just adds lots of computations.
It probably was something like applying the inverse of the scale and rotation of the parent-matrix (absolute matrix with translation reseted and then getInverse on that). And maybe then you have to apply the rotation part once again to not lose that.

But likely easier (and less to compute) to break the parent/child relationship here and do that calculation yourself completely. So use an own update function which knows about those relation. Alternatively you create your own scenenode which can recalculate the absolute transformation matrix in it's own way by overloading updateAbsolutePosition.

Default scenegraph is nice and easy for many cases, but sometimes it's just the wrong structure.
In those cases keep your scenegraph flat (which is generally faster anyway) and calculate relations between nodes yourself.
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
svedach
Posts: 20
Joined: Fri Oct 14, 2016 12:22 pm

Re: Disable of scaling child node.

Post by svedach »

Is it possible to easily add the appointment of child nodes of the parent node flag application scale? Maybe it would even increased performance - it is not always necessary to use the parent node scope.
I use Irrlicht to display the results of the Bullet Physics, and there is a class with the aid of which do what you say. But in this case there are problems with the correctness turn nodes ...
You can still add the flag of the application scale?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Disable of scaling child node.

Post by CuteAlien »

Not quite sure what you said. You mean we should add a flag for that? Basically - can't do that easily. The reason is that it's just not how the scenegraph works (childs use parent tranformations - if you want to get rid of scale you can no longer use those but have to calculate 2 different types of transformations).
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
svedach
Posts: 20
Joined: Fri Oct 14, 2016 12:22 pm

Re: Disable of scaling child node.

Post by svedach »

Well, I mean ... Tell me, then, please, how do I determine the correct origin and rotation the child node relative to the parent.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Disable of scaling child node.

Post by CuteAlien »

Hm, yeah - slightly tricky. Maybe following solution is easiest - you add a node in between which filters out the scaling of the parent. Note - only that of the direct parent - so if you a deeper scene-tree here (a few parents) you have to insert it in between each one where you need that.

Code: Select all

 
#include <irrlicht.h>
 
using namespace irr;
 
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 
// Can be placed in betweeen parent-child to ignore the scale of the parent.
class IgnoreScaleSceneNode : public irr::scene::ISceneNode
{
public:
 
    //! Constructor
    IgnoreScaleSceneNode(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, s32 id=-1)
        : irr::scene::ISceneNode(parent, mgr, id) {}
 
    virtual void updateAbsolutePosition()
    {
        AbsoluteTransformation.makeIdentity();
        if (Parent)
        {
            AbsoluteTransformation.setRotationDegrees( Parent->getRotation() );
            AbsoluteTransformation.setTranslation( Parent->getPosition() );
 
            if ( Parent->getParent() )
            {
                AbsoluteTransformation = Parent->getParent()->getAbsoluteTransformation() * AbsoluteTransformation;
             }
        }
    }
    
    //! returns the axis aligned bounding box of this node
    virtual const core::aabbox3d<f32>& getBoundingBox() const
    {
        return Box;
    }
 
 
    //! Returns the relative transformation of the scene node.
    virtual core::matrix4 getRelativeTransformation() const
    {
        return RelativeTransformationMatrix;
    }
 
    //! does nothing.
    virtual void render() _IRR_OVERRIDE_ {}
        
private:
    irr::core::matrix4 RelativeTransformationMatrix;    // identity matrix
    irr::core::aabbox3d<f32> Box;
};
 
 
 
 
int main()
{
    IrrlichtDevice * Device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(1280,1024) );
    if (!Device)
        return false;
 
    scene::ISceneManager* smgr = Device->getSceneManager();
    gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
    video::IVideoDriver* videoDriver =  Device->getVideoDriver();  
    smgr->setAmbientLight(video::SColorf(0.4f, 0.4f, 0.35f, 0.0f));
    smgr->addLightSceneNode(0, core::vector3df(0, 2000, -1000), video::SColorf(0.7f, 0.7f, 0.4f, 1.0f), 1000);
    smgr->addCameraSceneNodeFPS(0, 200.f, 0.1f );
 
    irr::core::vector3df scale(2.f, 1.f, 0.3f);
 
    irr::scene::ISceneNode * parent = smgr->addCubeSceneNode (10.0f, 0, -1,
        core::vector3df(0, 0, 100),
        core::vector3df(0, 0, 0),
        scale);
    parent->getMaterial(0).Lighting = true;
    parent->getMaterial(0).AmbientColor = video::SColor(0, 200, 0, 0);
 
    irr::scene::ISceneNode * child = smgr->addCubeSceneNode (30.0f, 0, -1,
        core::vector3df(0, 0, 50),
        core::vector3df(0, 10, 0),
        core::vector3df(1.f, 1.f, 1.f));
    child->getMaterial(0).Lighting = true;
    child->getMaterial(0).AmbientColor  = video::SColor(0, 0, 200, 0);
    
    IgnoreScaleSceneNode* ignoreNode = new IgnoreScaleSceneNode(parent, smgr);
    child->setParent(ignoreNode);
    ignoreNode->drop();
 
    while ( Device->run() )
    {
        if ( Device->isWindowActive() )
        {
            videoDriver->beginScene(true, true);
 
            smgr->drawAll();
            guiEnv->drawAll();
 
            videoDriver->endScene();
        }
        Device->sleep( 1 );
    }
 
    Device->closeDevice();
    Device->drop();
 
    return 0;
}
 
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
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Disable of scaling child node.

Post by CuteAlien »

Hm, wait - bad solution. That fails every time the hierarchy is deeper. Have to think again...

edit: I did edit the code above. I think it should work now probably...
edit2: Note that it will be faster if you do the customized updateAbsolutePosition() function directly in the node where you need it.
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
svedach
Posts: 20
Joined: Fri Oct 14, 2016 12:22 pm

Re: Disable of scaling child node.

Post by svedach »

Thank you very much. The class that you recommend doing exactly what I need. Since computation physics and rendering scene are performed in different threads, I do not need very high performance graphics engine. I was a little changed your class and spread it here, all of a sudden someone else will need ...

Code: Select all

 
class IgnoreScaleSceneNode : public scene::ISceneNode
{
private:
    core::matrix4           RelativeTransformationMatrix;    // identity matrix
    core::aabbox3d<f32>     Box;
public:
    IgnoreScaleSceneNode(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, s32 id=-1) : irr::scene::ISceneNode(parent, mgr, id) {}
 
    virtual void updateAbsolutePosition()
    {
        AbsoluteTransformation.makeIdentity();
        if (Parent)
        {
            AbsoluteTransformation.setRotationDegrees(Parent->getRotation());
            AbsoluteTransformation.setTranslation(Parent->getPosition());
            AbsoluteTransformation  *= RelativeTransformationMatrix;
            if (Parent->getParent())
            {
                AbsoluteTransformation = Parent->getParent()->getAbsoluteTransformation() * AbsoluteTransformation;
            }
        }
    }
    virtual void setRotation(const core::vector3df& rotation)
    {
        RelativeRotation        = rotation;
        RelativeTransformationMatrix.makeIdentity();
        RelativeTransformationMatrix.setRotationDegrees(RelativeRotation);
        RelativeTransformationMatrix.setTranslation(RelativeTranslation);
    }
    virtual void setPosition(const core::vector3df& newpos)
    {
        RelativeTranslation     = newpos;
        RelativeTransformationMatrix.makeIdentity();
        RelativeTransformationMatrix.setRotationDegrees(RelativeRotation);
        RelativeTransformationMatrix.setTranslation(RelativeTranslation);
    }
    virtual const core::aabbox3d<f32>&      getBoundingBox() const              {   return Box;     }
    virtual core::matrix4                   getRelativeTransformation() const   {   return RelativeTransformationMatrix;    }
    //! does nothing.
    virtual void                            render()  {}
};
 
Post Reply