Irrlicht design + oop question

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Irrlicht design + oop question

Post by PI »

Hello guys,

I've got two stupid questions:

1)
I've been staring at the Irrlicht sources and I couldn't find the answer:
How scenenodes get included on the lists of the scene manager?
I mean, the scene meanager does need to have a list of the scenenodes to render, right?
I've checked the add_ commands and the constructors of some of the scene nodes, but I still don't know. And after being created, it gets dropped.

2)
Say I've got 3 interfaces:
IClassBase, IClassA, IClassB

And 3 classes:
CClassBase, CClassA, CClassB

What I'd like to do is:

Code: Select all

class IClassBase
{
  virtual void baseFunction() = 0;
}

class IClassA : IClassBase
{
  virtual void additionalFunctionA() = 0;
}

class IClassB : IClassBase
{
  virtual void additionalFunctionB() = 0;
}

class CClassBase : IClassBase
{
  void baseFunction() { do something; }
  void otherFunc1() { something; }
  void otherFunc2() { something; }
}

class CClassA : CClassBase, IClassA
{
  void additionalFunctionA() { do something; }
}

class CClassB : CClassBase, IClassB
{
  void additionalFunctionB() { do something; }
}
And what I'd like to see is:

Code: Select all

IClassBase base;
base.baseFunction();

IClassA a;
a.baseFunction();
a.additionalFunctionA();

IClassB b;
b.baseFunction();
b.additionalFunctionB();
But it doesn't seem to work, it's ambiguous.
Any tips?

Thanks in advance!
PI
Nalin
Posts: 194
Joined: Thu Mar 30, 2006 12:34 am
Location: Lacey, WA, USA
Contact:

Post by Nalin »

1)

If I recall correctly, it all happens in the ISceneNode. When you create a new scene node, you pass in the parent. When the scene tries to render, it starts with the root scene node and works its way through all of its children.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

The irritating part is that the constructor calls addChild internally (which is something I also don't like). So it's like Nalin posted and there is one root and all other scenenodes form a tree below that.

And for rendering each node registeres itself. Basically works that way:

CSceneManager::drawAll calls OnRegisterSceneNode on itself as the scenemanager is the root scenenode. That resolves to ISceneNode::OnRegisterSceneNode which calls recursively OnRegisterSceneNode for all nodes in the tree.

All classes derived from ISceneNode overload OnRegisterSceneNode and register themselves in that function to the scenemanager with registerNodeForRendering. That puts them in a list for the corresponding render-pass.

All nodes registered for each render-pass are then rendered (still in CSceneManager::drawAll).
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
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Post by PI »

1) Thanks for the clarification!

2) Solved, the magic word is "virtual".

3) I've got a new question!

So now I've got nice (pure virtual) interfaces for the user.
However, some other classes cannot be created until they get a normal class with real content.
I've tried to use CSomeClass *test = instanceOfISomeClass; but the compiler didn't really like it.
So now I use dynamic_cast<CSomeClass*> for this purpose, and it seems to work fine.
However, I'm worried about it: do I loose data this way? Is this the right way doing this? (See, CSomeClass has some functions that it's interface "ISomeClass" does not have.)

What do you say?

Cheers,
PI
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

What type is instanceOfISomeClass? Better make a concrete example (that preferably can compiled) for such questions. Describing code with words... just confuses everyone ;-)
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
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Post by PI »

Nevermind, I've solved it :) Thanks anyway!
Insomniacp
Posts: 288
Joined: Wed Apr 16, 2008 1:45 am
Contact:

Post by Insomniacp »

you should read up on inheritance in c++ that should solve all of the questions you have about how classes combine using inheritance like irrlicht uses.
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Post by PI »

It's not really being a problem I just haven't ever added user interfaces to my classes yet. I also wanted to make these just like Irrlicht does, plus the base classes to inherit from IReferenceCounted. Now it seems to be all OK.
zet.dp.ua
Posts: 66
Joined: Sat Jul 07, 2007 8:10 am

Post by zet.dp.ua »

virtual functions and virtual inheritance are very useful sometimes, but you have to remember that virtual function is an additional pointer in vtable and virtual inheritance is an additional pointer to virtual parent class instance.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

virtual inheritance

Post by Ulf »

I think you already have the answer but I'll elaborate anyway.

When you are using multiple inheritance the compiler needs to know which version of the parent class to use.

For example, below, class CClassA inherits from CClassBase and IClassA.
But both CClassBase and IClassA inherit from IClassBase.

A call to CClassA::baseFunction() would be ambiguous. Because of the way C++ works the compiler doesn't know whether to use the function inherited from CClassBase or IClassA, even though they are the same!

So that is why you need to use "virtual" in the inheritance.
It means that only one copy of IClassBase will be used.

Code: Select all

class IClassBase
{
  virtual void baseFunction() = 0;
}

class IClassA : public virtual IClassBase
{
  virtual void additionalFunctionA() = 0;
}

class IClassB : public virtual IClassBase
{
  virtual void additionalFunctionB() = 0;
}

class CClassBase : public virtual IClassBase
{
  void baseFunction() { do something; }
  void otherFunc1() { something; }
  void otherFunc2() { something; }
}

class CClassA : public virtual CClassBase, public virtual IClassA
{
  void additionalFunctionA() { do something; }
}

class CClassB : public virtual CClassBase, public virtual IClassB
{
  void additionalFunctionB() { do something; }
}
And what I'd like to see is:
Code:
IClassBase base;
base.baseFunction();

IClassA a;
a.baseFunction();
a.additionalFunctionA();

IClassB b;
b.baseFunction();
b.additionalFunctionB();
You cannot instantiate a virtual class.
If there are any virtual functions then you cannot create an instance.
You have to create a CClassBase.
But an IClassBase pointer can point to an instance of a CClassBase as follows:

Code: Select all

IClassBase * pClassBase = new CClassBase();
The pointer is capable of calling any functions declared in IClassBase.
It will correctly call the functions implemented in CClassBase.

Any "implemented" child classes of IClassBase, such as CClassA, can also be pointed to by an IClassBase pointer, e.g.

Code: Select all

IClassBase * pClassBase = new CClassA();
When using the pointer, it will correctly call the functions overloaded in CClassA. Any functions not overloaded will be called from CClassBase or IClassBase.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Post by PI »

Thanks guys for the infos / examples!

I've already managed to implement the interfaces, and also the classes inherit from IReferenceCounted.

Although everything works now, and there are no warnings with MinGW, VC++ compiler throws many "dominance" warnings according to Shadowslair, who has tested the code.

Unfortunately I don't have VC++, so I cannot compile it only with MinGW.
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

To turn off the dominance warnings in Visual Studio, go to the Project Properties.

Open "Configuration Properties" -> "C/C++" -> "Advanced"

In the "Disable Specific Warnings" field insert the value 4250.

That will disable the dominance warnings.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

I guess this warning is due to the non-implemented function of the IBaseClass. Better ignore this for now, or use a different inheritance scheme. The code as given would never occur in reality (I hope :wink: )
PI
Posts: 176
Joined: Tue Oct 09, 2007 7:15 pm
Location: Hungary

Post by PI »

Thanks for the tips, guys! Yes, there are some classes I need to clean up... Hopefully these warnings will be gone :)
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

I guess this warning is due to the non-implemented function of the IBaseClass.
Yes in a sense.
More specifically it's because there are multiple definitions of the virtual function in IBaseClass. (since CClassA "virtually" inherits from IBaseClass twice )
The compiler is able to detect which version is implemented and it works. But MSVC gives warnings (4250).
You can just disable them as I said.
Better ignore this for now, or use a different inheritance scheme.
Don't ignore it. Disable the warnings if you are using MSVC.
The code as given would never occur in reality (I hope Wink )
I understand it's complex, but Why not?
Things like that occur in my code.
I am using a slightly elaborate inheritance scheme but it works for me.

It comes down to the battle between Delegation and Inheritance.

It is a problem of semantics.
I use inheritance whenever the parent class is a generalization of the descending class. For example, a car can't inherit from a wheel. A car contains wheels.
In this case you use delegation.

If it makes sense to say "derived class" IS a "parent class", you inherit, otherwise you include the other class inside yours.
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
Post Reply