23-10-2009 14:18:47
- Fol
- Membres
- Date d'inscription:
- Messages: 4
- IP: 195.221.233.56
- Courriel
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 :
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() constmain.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);
};
#endifMySceneNode.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
23-10-2009 14:51:30
- Hawk
- Membres
- Date d'inscription:
- Messages: 91
- IP: 90.3.182.149
- Courriel 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);
};
#endifAprè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.
Hors ligne
23-10-2009 15:58:27
- Fol
- Membres
- Date d'inscription:
- Messages: 4
- IP: 92.103.129.98
- Courriel
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...
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() constMySceneNode.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
25-10-2009 10:14:01
- Hawk
- Membres
- Date d'inscription:
- Messages: 91
- IP: 90.26.253.75
- Courriel 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.
Hors ligne
26-10-2009 09:38:29
- Fol
- Membres
- Date d'inscription:
- Messages: 4
- IP: 92.139.238.168
- Courriel
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
26-10-2009 11:02:02
- TUpac
- Membres

- Date d'inscription:
- Messages: 387
- IP: 90.29.233.87
- Courriel
Tiens ! c'est bizzard. d'habitude c'est winbouze qui tombe en panne de net ![]()
"Si vous ne partagez pas votre stabilité avec les pauvres, les pauvres partageront leur instabilité avec vous."
Hors ligne
26-10-2009 13:03:35
- Hawk
- Membres
- Date d'inscription:
- Messages: 91
- IP: 91.103.40.50
- Courriel 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
26-10-2009 22:44:31
- TUpac
- Membres

- Date d'inscription:
- Messages: 387
- IP: 88.168.3.38
- Courriel
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



