#0 

23-10-2009 16:18:47

Fol
Petit nouveau
Date d'inscription: 23-10-2009
Messages: 4

Bonjour,

Je débute avec Irrlicht. J'essaye de créer une classe héritant de ISceneNode pour pouvoir gérer des déplacements plus facilement.
Seulement le compilateur renvoie une belle erreur lors de la compilation (qui se fait sous Linux). Si j'ai bien compris ce qu'il raconte, c'est parce que la classe MySceneNode est abstraite... alors qu'elle hérite de ISceneNode qu'on peut tout à fait instancier oO

Je met ici juste une fraction de mon code, le reste des méthodes présentes pour le moment dans la classe est quasi indentique à avanceX.

L'erreur :

Code:

main.cpp: In function ‘int main()’:
main.cpp:142: erreur: cannot allocate an object of abstract type ‘MySceneNode’
MonVolume.h:10: note:   because the following virtual functions are pure within ‘MySceneNode’:
../include/ISceneNode.h:133: note:      virtual void irr::scene::ISceneNode::render()
../include/ISceneNode.h:168: note:      virtual const irr::core::aabbox3d<float>& irr::scene::ISceneNode::getBoundingBox() const

main.cpp

Code c++ :

MySceneNode * node = new MySceneNode(smgr->addSphereSceneNode(30.f));


MySceneNode.h

Code c++ :

#ifndef DEF_MYSCENENODE
#define DEF_MYSCENENODE

#include <irrlicht.h>
#include <iostream>

using namespace irr;

class MySceneNode : public irr::scene::ISceneNode
{
    public:

    MySceneNode(ISceneNode * parent,
                 scene::ISceneManager *  mgr,
                 s32                     id,
                     const core::vector3df & position,
                 const core::vector3df & rotation,
                 const core::vector3df & scale);

    MySceneNode(scene::ISceneNode *);

    ~MySceneNode();

    void avanceX(s32 avance);
};

#endif


MySceneNode.cpp

Code c++ :

#include "MonVolume.h"


using namespace irr;

MySceneNode::MySceneNode(    scene::ISceneNode * parent,
                        scene::ISceneManager * mgr,
                        s32      id = -1,
                        const core::vector3df &      position = core::vector3df(0,0,0),
                        const core::vector3df &      rotation = core::vector3df(0,0,0),
                        const core::vector3df &      scale = core::vector3df(1.0f, 1.0f, 1.0f)) : irr::scene::ISceneNode::ISceneNode(parent,mgr,id,position,rotation,scale)
{
}

MySceneNode::MySceneNode(scene::ISceneNode * node)
{
    MonVolume(node->getParent(),
             node->getSceneManager(),
             node->getID(),
             node->getPosition(),
             node->getRotation(),
             node->getScale())
}

MySceneNode::~MySceneNode()
{
}

void MySceneNode::avanceX(s32 avance)
{
    core::vector3df nodePos = getPosition();
    nodePos.X += avance;
    setPosition(nodePos);
}

Hors ligne


#1 

23-10-2009 16:51:30

Hawk
Membre
Lieu: Wissous
Date d'inscription: 08-11-2008
Messages: 91
Site web

En fait, le problème que tu as est très simple.

La classe ISceneNode est abstraite, comme toutes les classes d'Irrlicht qui commence par un I (I = Interface)
Cette classe a donc un certain nombre de fonctions qui sont virtuelles pures. Quand tu définis qui dérive de ISceneNode, tu dois impérativement redefinir ces fonctions, de telles sortes à ce qu'elles ne soient plus virtuelles pures.

Je pense que pour corriger ce problème, tu dois avoir dans ton header :

Code c++ :


#ifndef DEF_MYSCENENODE
#define DEF_MYSCENENODE

#include <irrlicht.h>
#include <iostream>

using namespace irr;

class MySceneNode : public irr::scene::ISceneNode
{
    public:

    MySceneNode(ISceneNode * parent,
                 scene::ISceneManager *  mgr,
                 s32                     id,
                     const core::vector3df & position,
                 const core::vector3df & rotation,
                 const core::vector3df & scale);

    MySceneNode(scene::ISceneNode *);

    ~MySceneNode();

    /*Ici tu redéfinies la méthode render de ISceneNode. Elle est virtuelle, au cas où tu veux redériver encore ta classe, mais ce n'est pas obligatoire.*/
    virtual void render();

    /*De même, ici tu redéfinies la méthode getBoundingBox(). */
    virtual const irr::core::aabbox3d<float>& getBoundingBox() const;

    void avanceX(s32 avance);
};

#endif


Après, tu dois définir ces fonctions dans ton code source. Dans render tu mets la manière dont tu veux dessiner ton noeud, et dans getBoudingBox, tu renvoies la BB de ton noeud.

Dernière modification par Hawk (23-10-2009 16:56:17)

Hors ligne


#2 

23-10-2009 17:58:27

Fol
Petit nouveau
Date d'inscription: 23-10-2009
Messages: 4

Merci pour la rapidité de la réponse. Je ne connaissais pas la signification du "I" devant le nom de la classe, pour moi ca voulait juste dire "Irrlicht".

Effectivement, c'est tout bête. Pourtant cela m'étonne. Avant de créer cette classe, j'instanciais un objet de type ISceneNode dans mon main et ca fonctionnait parfaitement :

Code c++ :

scene::ISceneNode * node = smgr->addSphereSceneNode(30.f);


Je ne l'ai pas inventé, c'est du code récupéré des tutos officiels (si c'est bien le terme). Donc à priori faire une classe héritant d'une classe instanciable ne me posait pas de soucis.

Je viens d'essayer de définir les méthodes render() et getBoundingBox() dans MySceneNode. J'y suis allé comme une brute en copiant le code des méthodes du même nom des fichiers source "CSphereSceneNode.cpp" ou "CMeshSceneNode". Résultat, ca plante toujours à la compilation quel que soit le code copié, mais l'erreur s'est déplacée...

Code:

main.cpp:142: erreur: cannot allocate an object of abstract type «MySceneNode»
MonVolume.h:10: note:   because the following virtual functions are pure within «MySceneNode»:
MonVolume.h:25: note:   virtual void MySceneNode::render()
MonVolume.h:28: note:   virtual const irr::core::aabbox3d<float>& MySceneNode::getBoundingBox() const

MySceneNode.h

Code c++ :

void render();
const core::aabbox3d<f32>& getBoundingBox() const;


MySceneNode.cpp

Code c++ :

void MySceneNode::render()
{
    video::IVideoDriver* driver = SceneManager->getVideoDriver();

    if (Mesh && driver)
    {
        driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial());
        driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
        driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
        if ( DebugDataVisible & scene::EDS_BBOX )
        {
            video::SMaterial m;
            m.Lighting = false;
            driver->setMaterial(m);
            driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255));
        }
    }
}

const core::aabbox3d<f32>& MySceneNode::getBoundingBox() const
{
    return Mesh ? Mesh->getBoundingBox() : Box;
}


Au cas ou j'ai essayé avec ou sans "virtual" devant ces méthodes dans le *.cpp (on ne sait jamais...).

Je suis sûr que c'est encore une erreur à la c**. Je suis désolé de demander et d'abuser de votre l'aide ^^"

Hors ligne


#3 

25-10-2009 11:14:01

Hawk
Membre
Lieu: Wissous
Date d'inscription: 08-11-2008
Messages: 91
Site web

En fait, tu n'instancies jamais un ISceneNode, tu instancies toujours un objet dérivé du ISceneNode (Un CSphereSceneNode par exemple, C voulant dire Concrete, je pense), mais le SceneManager d'irrlicht te renvoie un pointeur vers la super classe (ISceneNode), ce qui peut te permettre, par exemple, de stocker dans un tableau tous les pointeurs vers tes nodes, peut importe le type.
Essaie d'instancier autrement un ISceneNode, par exemple de cette manière :

Code c++ :


ISceneNode scenenode(); //Avec les bons arguments quand même, là je ne les ai pas en tête



Bon ensuite pour ton problème, j'ai d'abord quelques questions sur le but de ton MySceneNode :
- A quoi doit servir ton sceneNode ?
- A quoi il va ressembler, une fois rendu dans ton environnement 3D ? (un cube, une sphere, rien, un mesh ?)

En théorie, on ne dérive pas de ISceneNode, qui est vraiment LA super classe des Nodes, mais plutôt d'une de ses dérivées qui correspond mieux à ton problème.

Dernière modification par Hawk (25-10-2009 11:14:55)

Hors ligne


#4 

26-10-2009 10:38:29

Fol
Petit nouveau
Date d'inscription: 23-10-2009
Messages: 4

Mwai, je me disais bien que j'avais fait une erreur bête...
Je voulais que mon sceneNode puisse se déplacer et tourner dans son propre repère x-y-z, et non par rapport à un repère absolu fixe dans l'environnement (je ne suis pas très clair sans doute). Ce sceneNode est un mesh.

Ce que j'ai jusqu'à présent est un node qui se déplace suivant x-y, avec les touches ZQSD, ce qui pose certains problèmes d'orientation. Mais je me suis rendu compte hier soir que en fait je m'embête à créer ma propre classe peut être pour rien parce que en fait je n'ai pas essayé de faire tourner mon node... et si ca se trouve cela résoudrait mon problème actuel.

Je teste ca dès que j'ai trouvé comment faire tourner Irrlicht sous Windoze, mon Linux est sans internet en ce moment et c'est assez problèmatique

Mais créer MySceneNode (MyMeshSceneNode ?) serait sans doute intéressant pour la suite. (Et même si ca ne me sert pas, au moins j'aurai eu ma vengeance sur cette classe !)

Hors ligne


#5 

26-10-2009 12:02:02

TUpac
Habitué
Date d'inscription: 08-09-2009
Messages: 387
Corrections: 1

Tiens ! c'est bizzard. d'habitude c'est winbouze qui tombe en panne de net tongue

Dernière modification par TUpac (26-10-2009 12:02:20)


"Si vous ne partagez pas votre stabilité avec les pauvres, les pauvres partageront leur instabilité avec vous."

Hors ligne


#6 

26-10-2009 14:03:35

Hawk
Membre
Lieu: Wissous
Date d'inscription: 08-11-2008
Messages: 91
Site web

En ce qui concerne les déplacements et rotation d'un Node, quand tu utilise setRotation/setPosition, tu changes l'orientation/la position de ton node par rapport à son père. Si son père est 0, ou root, alors c'est dans le repère absolu de ton monde 3D.

Ensuite, vu que ton node est un Mesh, je te conseille de faire dériver ta classe de ImeshSceneNode (voire de IAnimatedMeshSceneNode), pour pouvoir appelé render et getBoundingBox de la classe mère.

Code c++ :


void MySceneNode::render()
{
    ImeshSceneNode::render();
}

const core::aabbox3d<f32>& MySceneNode::getBoundingBox() const
{
    return ImeshSceneNode::getBoundingBox();
}



A vérifier tout de même, je ne suis pas sur que render et getBoundingBox sont implémentées dans le ImeshSceneNode. Il te faudra peut être utiliser le CMeshSceneNode à la place.

Hors ligne


#7 

26-10-2009 23:44:31

TUpac
Habitué
Date d'inscription: 08-09-2009
Messages: 387
Corrections: 1

yep render et getboundingbox sont virtual. Les IAnimatedMeshSceneNode sont bien cool car on peut y mettre ce qu'on veut : static ou animé. Reste à voir si c'est plus gourmand mais j'en doute.


"Si vous ne partagez pas votre stabilité avec les pauvres, les pauvres partageront leur instabilité avec vous."

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
881 membres
1427 sujets
11117 messages
Dernier membre inscrit: Bidule
17 invités en ligne
Aucun membre connecté
RSS Feed