New camera type without changing Irrlicht

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.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Hah, there's a reason I'm posting in the beginners forum-- not quite smart enough to be answering questions in the advanced forum. :)
ElectroDruid
Posts: 23
Joined: Thu Oct 21, 2004 3:55 pm

Post by ElectroDruid »

Cool, I'm glad I've got the general concept of having a class which passes Irrlicht events onto my game. I'm still not convinced about deriving my camera class from ICameraSceneNode rather than wrapping it though.

Arguments against deriving from ICameraSceneNode

1 - I would have to supply an implementation of every function in ICameraSceneNode (what with it being an abstract class). Firstly, that involves writing more code than is necessary, which introduces potential maintenance problems, and secondly it means I have to expose functionality to my game which I really don't want to expose.

2 - If I upgrade to (say) Irrlicht 1.2 if/when it's released, and ICameraSceneNode has changed its interface, I have to change my camera's interface as well (even though, as I said, I don't even want most of the interface available to the rest of my game in the first place)

3 - The more classes I derive from Irrlicht interfaces, the more my codebase becomes tied to Irrlicht. I'm not looking to change to another renderer at any point, but if I did then I'd find the job a LOT easier if I was wrapping rather than deriving. It's a fairly standard cross-platform thing (in my day job I make console games, which are generally architected so that platform-specific renderers can be switched over easily)

4 - I would have to either change the scene manager to have a function to create a new camera scene node for my camera, or I'd have to use Vitek's solution, which wraps ICameraSceneNode anyway (seems a bit odd to derive from an interface and then also contain a member which is a pointer to the interface).

Arguments for deriving from ICameraSceneNode

1 - It's "proper" OOP. I derive from the interface to show that my camera "Is A" camera. I'm aware that although wrapping would be cleaner and more convenient, it's not the "right" thing to do according to OOP guidelines.

2 - It saves me having to write a class to receive messages from Irrlicht and pass them on to my own game-side event system (assuming that nothing else in my game wants to have Irrlicht messages passed on - although it seems likely that several parts of the game will be interested in input in some form). This would provide me with a (tiny) performance improvement.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

So you want to wrap a CCameraSceneNode class, as opposed to creating a new camera and deriving from ICameraSceneNode?
Image
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

ElectroDruid wrote: 1 - It's "proper" OOP. I derive from the interface to show that my camera "Is A" camera. I'm aware that although wrapping would be cleaner and more convenient, it's not the "right" thing to do according to OOP guidelines.
This is wrong. OOP != inheritence. Inheritence is one tool among many. It is by far the most overused tool. Sorry, if this sounds like a rant(which it is) but I have seen this misconception so often already...

This is not an Is-A-relationship. The camera control is not a camera. Just because a driver sits in a car to steer it, the driver is not a car and it is not melted with the car, he/she is still a human being and can still go out of the car.

Inheritence used in this case intermingles the two aspects user control and scene camera for no reason.

Just because Irrlicht does it in this way, doesn't mean it is good OO design. ;) The way cameras get their input in Irrlicht atm is a design flaw imho. How the SceneManager has to be responsible for input, and then only in a narrow case, is beyond me. Seems to be a hack.

IMHO you should not inherit the Irrlicht C/ICameraSceneNode. And wrapping is maybe the wrong word. Wrapping sounds like writing an adapter, but the actual OO term here is composition or aggregation. The controller simply holds a reference to the controlled camera node. That's it. The controller class, which inherits from IEventReceiver then can decide how user input affects the camera it controls.

This has no disadvantages I am aware of (educate me, if you can think something up). It has the advantage of added flexibility and streamlined control flow in your application.
Added flexibilty: A camera controller inside a camera can control only the camera (duh). An outside controller can control whatever it controls. If you change to a 3rd person cam, user input basically controls two scene nodes. The mesh node of the character itself and the camera. With just a camera controller you had to change the design.
Streamlined control flow: Instead of letting the camera magically receiving input through the SceneManager and using your own EventReceiver for everything else you can have your own explicit control flow.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

If you actually look at the source, CCameraSceneNode is true camera. You could create a camera and then "control" it, by manipulating the Projection and View matrices however you want, with position/target pairing, quaternions, whatever.

CCameraSceneNodeFPS should be more of a CFPSCameraController, and it really takes on that roll. It doesn't redefine the camera functions, it just adds the OnPostRender functionality to receive user inputs.

I think problems do exist in the input/event system, but not really in the camera relationships.

Anyways, I hate OO buzzwords. IMHO, OO is just guidelines. You'll make yourself absolutely nuts( and usually also make inefficient code ) by adhereing strictly to OO standards.
Image
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

seems a bit odd to derive from an interface and then also contain a member which is a pointer to the interface
Have a look at the proxy and decorator design patterns.
ElectroDruid
Posts: 23
Joined: Thu Oct 21, 2004 3:55 pm

Post by ElectroDruid »

@Saturn Hehe, I know the difference between OO and inheritance, but thanks for clarifying anyway :wink:

In that context, by "proper OO" I meant arranging classes in such a way that they reflected the classes identity and purpose. In this case, the way that the the cameras were all derived to overload functionality implied that a CCameraSceneNodeFPS "is a" CCameraSceneNode (as opposed to something which controls ("has a") CCameraSceneNode). So, assuming Irrlicht is true, the "proper" thing would be to derive. If, as you're saying and as I suspected, the way Irrlicht does that is actually a bit suspect, then I guess the "proper" thing is to aggregate (or wrap it, as I have wrongly called it, and will continue to call it because I'm stubborn :wink: )
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

[quote="ElectroDruid...then I guess the "proper" thing is to aggregate (or wrap it, as I have wrongly called it, and will continue to call it because I'm stubborn :wink: )[/quote]

YAY. Call it what you want, we get the point!
Image
ElectroDruid
Posts: 23
Joined: Thu Oct 21, 2004 3:55 pm

Post by ElectroDruid »

Cool, I'm nearly there now. Got my class to pass on events, got my camera controller class containing an ICameraSceneNode, got a bunch of logic running every time I get input I'm interested in... And I've got some questions about things which are missing from the Irrlicht API. Namely:

- vector2d has no method getLengthSQ()

- ICameraSceneNode has no method setViewMatrix()

- Irrlicht in general seems to have no matrix3 class. Although this isn't exactly a crime in itself, I would imagine a fully-featured 3D engine would have a matrix3 class for expressing rotations in a way which takes up less memory and is quicker for certain operations than a matrix4 class.

In these cases, I've figured it's best to bite the bullet and implement them in Irrlicht. I know I said I didn't want to touch Irrlicht code if I could help it, but it seems really odd that it's missing these few fundamental things. They're missing for no good reason that I can fathom, and they're things I will be wanting to use more in future. My questions at this point are

1 - Does anyone know why this stuff is missing? Is there a good reason which I'm unaware of?

2 - If there's no good reason for it being missing, what is the process for requesting that this stuff makes it into the next Irrlicht release? It shouldn't be a big job to add any of it.
Nitecon
Posts: 2
Joined: Wed Oct 11, 2006 2:24 am
Contact:

Post by Nitecon »

Just out of curiosity wouldn't you want want your game in general to react in the following way? Simply because it will optimize it it in general. I'm only asking because all of the opengl and direct3d books i've read on engine programming always point the same thing out...

..........Shutdown ------> NO
.....................................^
.....................................||
Initialization --------> Continue Game? ----> Yes
........^.......................................................||
........||.......................................................\/
Synchronization...............................Interface with Windows
........^.......................................................||
........||.......................................................\/
Play Sound Effects............................Acquire User Input
........^........................................................||
........||........................................................\/
.......Render Graphics......................Update Character Positions
.................^...............................................||
.................||...............................................\/
..................========Game Logic=======

1. First your start your initialization...
2. Check if the user has put input to continue or quit?
3. If user wants to quit, perform shutdown, else continue.
4. Interface with windows.
5. Acquire user Input
6. Update Character Positions ( Camera updating )
7. Game logic.
8. Render Graphics.
9. Play Sound Effects.
10. Synchronization.

Check if user wants to quit or continue at 4.

Now granted this was a simple example and taken out of zen of direct3d book. But it might explain a lot to some of the beginners, and even though irrlicht takes care of a lot of the steps, keeping those in mind might make it easier to sort things out easier.

Thus always first check for input events before your camera is updated?
Post Reply