Classes for making mesh nodes

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.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Classes for making mesh nodes

Post by CuteAlien »

I will opensource that project soon (I hope). Just posting my main.cpp would probably only confuse you more. All I have in there is a class-object called app (for application class) for which I call init, run and quit. The class above is only part of the application class.

For passing around pointers you probably find better tutorials. But I can try to give you a very quick introduction using your EMissile class. When you create class objects you have usually 2 ways to do that:

Code: Select all

 
EMissile myMissile; // stack
EMissile * myOtherMissile = new EMissile(); // heap
 
The first one tends to be faster because all it does is increase the value of the stack-pointer by the size of your class-object. That variable is valid as long as the scope it is in and will then release the memory again automatically. Scope is generally the closest surrounding pair of those brackets {}. So if you create it inside a function that variables memory will only be valid inside the function. If you create it inside a class it will stay valid as long as objects of that class. If you create outside all functions and classes it's global and will stay valid as long as your application. You can pass around pointers to memory of variables of that type with &myMissile. & means give me the address of an object (aka a pointer). But - be very careful when doing that. The compiler will not check for you if that memory you pass around is still valid. So for example if you create a variable on the stack inside a function and return a pointer to it the compiler might allow you to do that. But it will have random effects when you run the application as the object memory is invalid at the end of the function. It might even work for a while as the memory might still contain the same values for a short time (but you have no guarantee of that). Meaning - whenever you return pointers to objects on the stack you _must_ know they are still valid in memory. Usually that means you know they are inside an object which is still valid or that they are global.

The second one is on the heap. You can return it simply by returning myOtherMissile as it already is a pointer. Creating it is slow because new is more complicated function as it has to figure out stuff like where to get it's memory from. And you have to release the memory of that variable yourself at the end because it's memory is not released automatically. So you get memory-leaks if you never release that memory. The memory will stay valid until you call delete. Or for Irrlicht objects you call drop() which internally will call delete when it was the last reference to that object (Irrlicht does reference counting - but that's another topic). General rule to make it easier to work with such classes is - whoever created the object should be responsible for destroying it again (NOTE that Irrlicht does not always do that - so it is a bad architecture example - even good programmers mess that up once in a while).

So let's make a very short example of how to use functions with pointers:

Code: Select all

 
class Application
{
public:
    Application() 
    : myOtherMissile(0), theThirdMissible(0) // always initialize all pointers to 0 to make your life a lot(!) easier
    {
        myOtherMissile = new EMissile(); // allocate heap memory
    }
    ~Application() 
    {
        delete myOtherMissile;
    }
    EMissile * getMyMissile() { return &myMissile; }
    EMissile * getMyOtherMissile() { return myOtherMissile; }
 
    void setThirdMissile(EMissile *  missile) { theThirdMissible = missile; }
    EMissile * getThirdMissile() { return theThirdMissible; }
 
private:
    EMissile myMissile;
    EMissile * myOtherMissile;
    EMissile * theThirdMissible;
};
 
void main()
{
    Application myApp;
    EMissile * missileHeap = new Missile();
    EMissile missileStack;
    myApp.setThirdMissile(missileHealp);
    myApp.setThirdMissile(&missileStack);    
    EMissile * missile = myApp.getMyMissile(); // would also work with other getters.
    missile->Shield(); // call some function 
}
 
That should show you most cases of how to pass around pointers. There's still arrays and you can also work with references, but get some c++ tutorial for those. Also I didn't show too complicated examples about scopes (I'm running out of time). I hope it helped a little.

About examples - they are kept as simple as possible because it's about showing how to do stuff with Irrlicht. They are not about teaching c++. You could use headers and certainly should when writing own applications. Check the Demo code - that works with headers.
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
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: Classes for making mesh nodes

Post by Asimov »

Hi CuteAlien,

Thanks, will study this.
I am going to try and start from scratch and build an application with a header file to start with.

I spent ages learning C++, forgotten some, learnt some, forgotten some, and some things go right over my head.
The word polymorphism scares the willies out of me LOL.

I was quite proud of my file encryption routine I made for my Missile command game.
I got to a point where I could make games with previous engines, but it is just learning how a new engine works and how to intergrate with it.
I started makng a game straight with directx, and I got all the 2D stuff working, but this 3D stuff is over my head. I also got on quite well with XNA until they stopped developing for it grr.
https://www.youtube.com/watch?v=aGcuNegUmqU
https://www.youtube.com/watch?v=BmN1A00JvOo
https://www.youtube.com/watch?v=6YFr5inyltk
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: Classes for making mesh nodes

Post by Asimov »

Hi all,

I have had a little success creating my meshloading class. Basically this class is going to be designed to load any static model. Later I might do an animated one, once I get this to work. It actually loads in the mesh fine, but I know I am doing something wrong. The thing I am doing wrong at the moment is that I am creating the node in this class, and I know I shouldn't do this.

I should create my node either in another class or in main.cpp and pass that node into my meshloading class somehow, but I do not know the correct way to do this.

First of all I don't know how to create an empty node, and then pass that node into my meshloading class. I should possibly use a pointer to the node pass in, or pass in the node directly. I don't know. My model comes out black at the moment because I haven't specified any light, yet, but it does load in.

Ok I will show you my class and what I have done so far.

I initialise the class with this
LoadMesh spaceinvader;
because i am loading a spaceinvader model.

Then I load in my model with this line passing in the screen manager and the mesh location
spaceinvader.loadMesh(smgr,L"data/invad.md2");

Eventually I will load in model coordinates here also.

Ok and here is my meshloading class.
You can see at the moment I am creating the node in the class, but I shouldn't be doing this.
That is the bit I cannot work out yet.

Any help would be appreciated.

LoadMesh.h

Code: Select all

#ifndef LOADMESH_H
#define LOADMESH_H
 
#include "irrlicht.h"
 
class LoadMesh
{
     irr::scene::IMesh *mesh;
 
    public:
        LoadMesh();
        void loadMesh(irr::scene::ISceneManager* smgr,const wchar_t* modelname);
 
    private:
 
};
 
#endif // LOADMESH_H
 
LoadMesh.cpp

Code: Select all

#include "LoadMesh.h"
 
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
using namespace io;
using namespace gui;
 
LoadMesh::LoadMesh()
{
    //constructor
}
 
void LoadMesh::loadMesh(ISceneManager* smgr,const wchar_t* modelname)
{
     //mesh = smgr->getMesh("data/invad.md2");
     mesh = smgr->getMesh(modelname);
     //This line should be taking in a node from outside and not being initialised here
    IMeshSceneNode*node = smgr->addMeshSceneNode(mesh);
}
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: Classes for making mesh nodes

Post by Seven »

not exactly sure what you are trying to do, however, you could return the scenenode from the loadmesh function if you wanted to.

Code: Select all

 
IMEshSceneNode* LoadMesh::loadMesh(ISceneManager* smgr,const wchar_t* modelname)
{
     //mesh = smgr->getMesh("data/invad.md2");
     mesh = smgr->getMesh(modelname);
     //This line should be taking in a node from outside and not being initialised here
    IMeshSceneNode*node = smgr->addMeshSceneNode(mesh);
 
    // return the node pointer to the calling function
    return node;
}
 
and use it like this

Code: Select all

 
IMeshSceneNode* myNode = LoadMesh::loadMesh(ISceneManager* smgr,const wchar_t* modelname);
[\code]
 
although I would personally create an object class and store the node in it similar to what you are doing.
 
[code]
class Object
{
  public:
          IMeshSceneNode* m_Node;
 
          Object::Object() { m_Node = 0; }
          virtual Object::~Object() { if (m_Node) m_Node->release(); m_Node = 0; }
 
          bool LoadMesh::loadMesh(ISceneManager* smgr,const wchar_t* modelname)
          {
               
              IAnimatedMesh* mesh = smgr->getMesh(modelname);
 
             if (!mesh) 
             {
                  printf("ERROR! Object::LoadMesh(%s) failed...unable to load mesh?...\n",stringc(modelname.c_str());
                  return false;
             }
 
             
             //This line now creates the scenenode and stores it in the m_Node variable for this instance of this class
             m_Node = smgr->addMeshSceneNode(mesh);
          
             if (!m_Node) 
             {
                  printf("ERROR! Object::LoadMesh(%s) failed...unable to create node?...\n",stringc(modelname.c_str());
                  return false;
             }
 
             return true; 
          }
 
        
};
 
then I would have a list of objects that I can do things with
 

Code: Select all

class myApplication
{
public:
       list<Object*> m_Objects;
 
       myApplication::myApplication() { m_Objects.clear(); }
       myApplication::~myApplication() 
       { 
          list<Object*>::iterator it;
          for (it= m_Objects.begin(); it != m_Objects.end();)
           {
                 delete(*it);
                 it = m_Objects.erase(it);
           }
          m_Objects.clear(); 
       }
}
 

now you can run through your list of objects and do lots of cool things. in addition, this means that your game objects HAVE a scenenode, not they ARE a scenenode. This allows you to create a lot of different game objects with lots of different functionality, but they all have one thing in common, they all have a scenenode in them.
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: Classes for making mesh nodes

Post by Asimov »

Hi Seven,

I am afraid I didn't understand your code segment, but thanks for replying. It has been a long time since I have done any C++, so I am very rusty, and have forgotten a lot, and so I am beginning again in a lot of ways.

Anyway I have decided that I don't need to access the node outside of the class, and I don't need to pass the node in. For instance if I need to rotate the node I can do it with a function within the class itself. Every mesh has to have a node and this class will create the node for each model loaded anyway.
Also my class has improved now so I can pass in the texture into my class also.

The beauty of my class is this. Anytime I want to add a new model to my game, I can just pass one line to my class and I have my new model, plus the initialise line of course. I might add another function to load in animated meshes next, but that isn't important yet, as I have no animated meshes to play with yet. Also I will be wanting to pass in in the coordinate position of my model also. I don't want all my models appearing in the same location heh heh.

For instance here is my line to call my class now.

LoadMesh spaceinvader;
spaceinvader.loadMesh(smgr,driver,L"data/invad.md2",L"data/invader.tga");

And for test purposes I have added a function to rotate my model. Yes I know the rotation variable should be a member variable, and I will probably do that later, but I wanted to test this quick and dirty.

LoadMesh.h

Code: Select all

#ifndef LOADMESH_H
#define LOADMESH_H
 
#include "irrlicht.h"
 
class LoadMesh
{
 
    public:
        LoadMesh();
        void loadMesh(irr::scene::ISceneManager* smgr,irr::video::IVideoDriver* driver,const wchar_t* modelname,const wchar_t* texture);
        void RotateMesh(float *rotation,const irr::f32 frameDeltaTime);
 
    private:
        irr::scene::IMesh *mesh;
        irr::scene::IMeshSceneNode*node;
        irr::video::IVideoDriver* driver;
 
 
};
 
#endif // LOADMESH_H
 
LoadMesh.cpp

Code: Select all

#include "LoadMesh.h"
 
using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
using namespace io;
using namespace gui;
 
LoadMesh::LoadMesh()
{
    //constructor
}
 
void LoadMesh::loadMesh(ISceneManager* smgr,IVideoDriver* driver,const wchar_t* modelname,const wchar_t* texture)
{
     mesh = smgr->getMesh(modelname);
    node = smgr->addMeshSceneNode(mesh);
    if (node)
    {
        node->setMaterialFlag(EMF_LIGHTING, false);
        node->setMaterialTexture(0, driver->getTexture(texture));
    }
}
 
void LoadMesh::RotateMesh(float *rotation,const irr::f32 frameDeltaTime)
{
     *rotation-=50 * frameDeltaTime;
     node->setRotation(core::vector3df(0,*rotation,0));
}
 
 
 
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Classes for making mesh nodes

Post by CuteAlien »

Some notes about names... correct names do matter in programming. Your's are still a little bit confusing. You class is called LoadMesh - but it does do other stuff. Maybe something with "Model" would be more fitting. The other name that seems somewhat wrong is RotateMesh - because you actually do rotate a node, while the mesh stays unmodified. I once added a short glossary of terms for Irrlicht to the wiki, mabye it can help you: http://irrlicht3d.org/wiki/index.php?n= ... ommonTerms
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
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: Classes for making mesh nodes

Post by Asimov »

Hi CuteAlien,
Some notes about names... correct names do matter in programming. Your's are still a little bit confusing. You class is called LoadMesh - but it does do other stuff. Maybe something with "Model" would be more fitting. The other name that seems somewhat wrong is RotateMesh - because you actually do rotate a node, while the mesh stays unmodified. I once added a short glossary of terms for Irrlicht to the wiki, mabye it can help you: http://irrlicht3d.org/wiki/index.php?n= ... ommonTerms
Heh heh before I called it LoadMesh I called it Ghouly because it was the first name that came into my head. When I got it working I then changed it to something more appropriate.
However LoadMesh&CreateNodeAndRotateNode was a bit long. It will eventually do other functions too, so maybe I could call it LoadManager or something. The most important thing is that I know what it does. Very rarely if you look at other peoples programs that names will mean anything to anyone other than the programmer.

I realise I am rotating a node in my rotatemesh function, but the mesh is still rotating.

I have got a lot to learn about the engine yet. I haven't even started on my game yet, as still trying to work things out.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Classes for making mesh nodes

Post by CuteAlien »

Names are also useful for yourself if you take a look at it again half a year later. And good programmers think a lot about names and try rather hard to make them easy to read for others. You can read sources of experienced programmers often without much need for documentation because their names are that good. Making code understandable is the main reason to use higher-level languages like c++ in the first place. Your computer would be fine if you just type in the machine code numbers.
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
Asimov
Posts: 246
Joined: Thu Dec 04, 2014 7:41 pm
Contact:

Re: Classes for making mesh nodes

Post by Asimov »

Hi CuteAlien,
Names are also useful for yourself if you take a look at it again half a year later. And good programmers think a lot about names and try rather hard to make them easy to read for others. You can read sources of experienced programmers often without much need for documentation because their names are that good. Making code understandable is the main reason to use higher-level languages like c++ in the first place. Your computer would be fine if you just type in the machine code numbers.
I wasn't disagreeing with you at all. Yes I agree names are very important, but what triggers my memory might not be what triggers your memory.
What I might think is a good name might not mean anything to you. If I use someone elses convention of naming and look back at my code 6 months later, I might not have a clue, but if I use a name that triggers something in my mind, then it is better to use my own convention.

I am a little rusty with C++, but I have been programming in various languages since 1981. I was programming in C on the Amiga long before pcs had colour.
I wrote a full word processor in z80 machine code on the the zx spectrum 48k.

The reason I haven't done much program in the last few years is because I have been concentrating on my 3D work rather than the programming side of things.
I have also spent the last couple of years programming php and jquery for my job, so yes I know names are important.
Post Reply