Thread: So now...

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968

    So now...

    Now I have a working MS3D Model Loader, a Working Render Engine, though it may be a small and nearly featureless one, I got one that works.

    My next logical step is to create an Object class, and many derivedrens for each individual object I want to be in my world, Using proper inheritance I can make a powerfully object oriented game engine.

    Each object will contain information telling us where in 3d space each model is. I will create a Mobile class which inherits Object, that will also contain movement variables, e.g, How fast can this object move? How fast can it accelerate? How fast can it turn? Etc etc... Also an index to a model the Mobile will need to use... Or in case the object doesn't have a three dimensional object already created for it, We'll store a Texture ID or two as well as a pointer to where the model is defined (maybe a box, or something like that, that we don't have an MS3D file for)..

    I will also have a Statics class which inherits Object, this class will be essentially the same as mobiles, except for one key difference, these objects are "dummies", as in, they don't have their own movement variables, all they do is hold a location in space and maybe some extra information.. For instance,Things like resource type, resource amount... For resource production....


    So This is the stage in my project I am at right now.... After I do all this junk I will plan on making enemy AI... This is the tough part, we have to add flight sim mathematics in for each AI ship so that they can be a competent opponent...

    All this spacethemed dogfighting accompanied by a HOT techno metal track my friend made.... Will definately make for some intense space combat, on a very large scale!

    My vision is this, remember episode three, of star wars? The game will be an RTS, meaning you can control each ships individual orders, (or follow prebuilt attack plans you can make back at base), all while fighting along side your AI pilots, pwninating capital ships and battlecruisers, FREAKIN SWEET!!

    Any suggestions?
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Yeah don't use inheritance for your rendering system. I would only use it on GUI. At most, I would use one layer of inheritance on objects with very limited, if any, virtual functions.

    Perhaps some others here might want to expand on why.

  3. #3
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Well the only things the objects have to do with the Renderer is this, they are like a client to the render engine...

    Each individual object holds a pointer to an MS3D Model.

    An example of the inheritance I will use would be like this:

    Objects->Mobiles->Ship1


    the Ship1 class will hold a pointer to a ship1 Model, as well as location information, and among other things, speed variables, etc etc...

    Another function Loads all the models I tell it to (ship1.ms3d would be included)

    Now we pushback all the individual objects into a vector (only if the world class requests that they do so!!!), we use a nifty "AddObjectsToRenderer" function for this ...

    then we Draw all the models according to the vector we just made, changing the locations given by the objects (like Ship1)...


    It seems so ingenious, where could it go wrong bubba? Please enlighten

    Bubba the Pirate!

    As of now I will not be using any virtual functions in the Objects master class, there might be 1 or 2 virtual functions for mobiles (because they all move? right?) None for statics, I don't think...


    I feel like I'm sounding like a competant programmer alluva sudden, when did this happen?
    Last edited by Shamino; 12-13-2005 at 02:52 AM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  4. #4

    Join Date
    May 2005
    Posts
    1,042
    At most, I would use one layer of inheritance on objects with very limited, if any, virtual functions.
    Yeah, using inheritance can be useful only under certain conditions in my experience. As Bubba stated, I also try to stay away from multiple levels of inheritance. In my personal experience it just makes things turn into a mess much easier...it has made finding certain bugs harder, and in general I have stayed with a single level of inheritance. I suggest you experiment though. Other C++ type languages such as java have decided to sidestep the multiple inheritance aspect of the language altogether.

    This isn't to say, however, that I haven't had a single object derive from multiple other objects. A spacecraft may want to derive from a mobile class, from, oh, I dunno, a 'pathfinding class,' or some sort of AI class, as a palette for its entire functionality...but as long as each of the classes it derives from don't derive from anything else, then it's not multiple levels/layers of inheritance.
    One added thing, not that this is something you really care about at this stage in your game programming, but there are also hidden costs associated with making classes that are purely virtual. A virtual function is really just a function pointer. It takes about %30 longer to execute a function call through a function pointer. This is because it takes longer to access any variable through a pointer, the reason is that in order to access any sort of data through a pointer you must access two variables, first the pointer itself (which is a memory address) and then after that, access the data which resides at the memory address.

    I don't know if I should have even said this last bit, the worst thing you could do right now is change your design to avoid something that won't realistically be a problem, but it just gives you something to think about.
    I'm not immature, I'm refined in the opposite direction.

  5. #5
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    <--- not using any virtual functions as of now
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  6. #6
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    I suggest using a proper object oriented design with virtual functions as neccessary. Calling a virtual function is just an extra table look up.... the experience you'll gain from building a proper object oriented design is way more valuable than the tiny bit of performance you gain by not designing this way.

  7. #7
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Well, we're using inheritence hardcore throughout the project, we havn't found any uses for a virtual function though in defining our objects.. Yes all Mobiles->Objects have a speed, but those are variables, not functions, right?
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  8. #8
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    Well, we're using inheritence hardcore throughout the project, we havn't found any uses for a virtual function though in defining our objects.. Yes all Mobiles->Objects have a speed, but those are variables, not functions, right?
    I'm having a hard time thinking of when it would be necessary too. I haven't gotten into engine design yet so its hard to think. I'm sure all of you know what I'm talking about below, and even see how incorrect it is - which is sort of why I'm posting it. Sorry if this is a highjack, I'd like to know more about how to go about this. Its easier getting answers from gurus when you post a bunch of guesswork.

    Without a virtual function you wouldn't be able to access Object->Mobile.speed from say AddObjectsToRenderer(), because it takes Objects (for generics). Unless of course it was Object.speed, which would be pointless in design and inefficient space-wise. Then again you probably wouldn't need to access Object->Mobile.speed anyway, but Object.x/y/zCoord (normal accessor method) you would - which would have to be protected or public (for derived classes), so that doesn't even matter. Other Render methods or functions in the engine might really need that ability though. Which would mean virtual functions or possibly delegation (adds complexity) in the Ship/etc. mobiles would be useful?

    I guess if you wanted everything pointing to Ship1 to point to Jeep2 instead, it would be easier to do using an abstract (pure virtual) class. Simply changing the object of the abstract class to point to (a derived from) a Jeep2 object instead of a Ship1 object. Of course you could use a visitor design instead, or possibly void pointers.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  9. #9
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Ultimately what the grand scheme of things I'm trying to accomplish is this


    Objects (contains a location xyz)
    Mobiles (inherits objects, Contains physics variables common to all mobiles)
    Statics (inherits objects, more of a dummy object, doesn't move under its own power){

    Cross(inherits Mobiles, which inherits objects, holds a pointer to a model, simply put, might perform some function that will be figured out later)

    I'll take cross, and dynamically allocate it somewhere, so we can have multiple cross objects on the screen, if the user demands another cross is built, so be it, another cross is dynamically allocated..

    I don't see a use for virtual functions yet..

    I'll have a world class that determines what needs to be drawn in the world, where, when, and why...

    World sends this information to a function in the render engine that dynamically allocates all objects that world says is needed on the screen, (there will be like, an update function in Cworld, that determines what is drawn and what isnt, where, when, and why)

    which is sent to the draw function, bam, one call, whole scene is drawn..

    That is my grand master plan, it probably is stupid and buggy though...


    /////////////////////////////////////////////////////////////////////////////

    I really misunderstand what you're saying Dae, could you please try to clear it up?

    I know a few things, We will never need to access Object->x,y,z

    Inheritence makes it so we need to access Ship1->x,y,z

    I don't see why these objects would ever become unavailable for direct access like that..
    Last edited by Shamino; 12-13-2005 at 10:06 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  10. #10
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    I really misunderstand what you're saying Dae, could you please try to clear it up?
    Sorry if I was confusing because I'm sure you already know this.

    I know a few things, We will never need to access Object->x,y,z
    How exactly do you plan to have a Render function accepting generic Objects that can access x,y,z? Even though Ship1 derives from Object you need to have the variables/functions in the Object class, or use virtual functions to go down the heirarchy to the derived class (the one you're passing).

    I don't see why these objects would ever become unavailable for direct access like that..
    If you're making a vector of Object's for your Render class, then you would need to access Object->x,y,z. Of course Ship1 inherits that from Object if x,y,z are protected or public. If they weren't in Object, and were in Ship1, then you would not be able to access them unless you changed your Render function to accept Ship1's and not Object's.

    Inheritence makes it so we need to access Ship1->x,y,z
    You *could* access x,y,z through Ship1 because its inherits from Object and are actually stored there and could be accessed from there too (obviously).

    I don't know if I'm wrong - I could be and it wouldn't be the first time. I just wanted to get more ideas out of you guys.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I suggest using a proper object oriented design with virtual functions as neccessary. Calling a virtual function is just an extra table look up.... the experience you'll gain from building a proper object oriented design is way more valuable than the tiny bit of performance you gain by not designing this way.
    Usually I agree with you Perspective but not in this instance. Game programming is an entirely different breed, has entirely unique challenges that do not always have simple solutions and usually cannot be solved efficiently using pre-built mechanisms and/or the existing mechanism is not exactly suited to the task at hand.

    I stress this - It is NOT a good idea to use virtual functions and/or lots of inheritance in a game system.

    It IS a good idea to use aggregate data types by using pointers and/or creating objects on the stack.

    Virtual functions in themselves might not be a bad idea if you only have a few objects. But think about a game. Very easily you could have well over one thousand virtual function calls taking place at the same time. That multiplied by the 30% time differential that Bob posted will result in some major problems.

    GUI's are very well suited for multiple inheritance - but games are more suited to actually using C for the API and C++ to encapsulate it or use it. Most game APIs are written in C and/or C++. Most of them I've seen do not use a lot of inheritance. Several game programming books I've read also state this same fact. Game Coding Complete is written by someone who has developed games for Origin (Ultima series), Microsoft (aka Halo), and other game companies as well. The stuff he mentions in the book is exactly what I've found to be true in my own experience. This piece of advice to the OP will save him thousands upon thousands of lines of re-work. A game system is much different than any other program on earth and it HAS to run fast. That is it's lifeline, it HAS to run fast or it will die a horrible death. So, in games, every and I mean every CPU cycle and GPU cycle counts. 30% is a lot in a main render loop.

    So stick to 1 level of inheritance. It makes your objects easier to construct, easier to use, and much less confusing. It also allows you to destroy the objects a bit more efficiently instead of relying on destructor calls - which when it comes to COM do not do exactly what you might want them to. A specific ShutDown() and Init() function for all game objects is almost essential to properly destroying COM and/or releasing memory back to the system.

    There is more behind this whole theory, but I don't have the time or space to dive into it.

    Perspective has good advice there so don't get me wrong, it's just not applicable to game engine and/or game design in this instance.

    To render efficiently Shamino you must first think about what a render is:

    A render is simply drawing the vertices in a set order to create textured triangles through various hardware texture mapping algos.

    So a renderer only needs to know certain information about an object.

    1. It's local rotation
    2. It's world position (or translation relative to 0,0,0 which is the camera in world space)
    3. It's world rotation (if any)
    4. It's vertex data to include color(s), uv coord(s), etc.
    5. It's texture(s) and associated data

    The list could go on, but I leave that to you. So you need to send your renderer only pertinent information. Since each object in the world has vertex data, making a universal render function for all objects is actually fundamentally quite simple.

    The renderer doesn't care if it's drawing an uber-cool space ship, or a super-boring billboard sprite. It just renders. If you approach it like that, I think you might get a bit farther.
    The inheritance method as it is right now is NOT the correct approach. You are sending far too much data to the render function and losing efficiency. Keep it simple and to the point.
    Don't force your render to do one more lookup than it has to. Even if it's just looking at a pointer in the vtable. Build the function so it doesn't have to do that. The render function should not be a member of any object class and should be a member of the rendering system only. Transformation, frustrum culling, and visible object list creation should also be done by the render function. So send all relevant data to the function in order to properly, efficiently, and quickly render the scene. It can get quite complex.

    Remember in a 3D engine.....speed is everything

    I think that most of my friends and colleagues here will agree with most of what I've said here. We've all experienced this in one way or another when we attempted to "C++'ize" our engines by deriving from everything and realized.....something isn't right here.

    As for constructors - they should construct only.
    Do not attempt any operation that might fail or could fail. In other words don't open files, don't allocate memory, don't create COM objects, etc., etc. Make your constructors parameterless so that creating an object of that type is extremely easy.

    Do the bulk of the work in an init function that either returns an HRESULT from DX or perhaps a boolean result indicating success or failure. You can use exceptions although DX will NEVER EVER recover from an exception so a simple message and an immediate cleanup and exit will suffice.

    This is fine:

    Code:
    CGameEngine TheEngine;
    If:

    * The constructor for CGameEngine absolutely cannot ever fail

    Because:
    * If it can fail, you have no way of finding out if it failed or not except by using exceptions which will force an immediate exit and failure of the system


    I suggest purchasing Game Coding Complete 2nd edition for more information as well as Real Time Rendering.
    These are available on www.amazon.com.
    For reviews of books and recommendations go to www.gamedev.net and click on Books.

    For more information about do's and dont's and tips and tricks on how the pro's code - go to www.gamasutra.com.
    Last edited by VirtualAce; 12-14-2005 at 01:59 AM.

  12. #12
    ---
    Join Date
    May 2004
    Posts
    1,379
    Usually I agree with you Prelude
    It was Perspective
    But we know what you mean.

  13. #13
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Why do I always get them mixed up? I did this before in another thread here not too long ago. Doh!!!!

    ::konk::

    Anyways, I corrected it.

  14. #14
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034

    Exclamation

    Quote Originally Posted by Bubba
    Why do I always get them mixed up? I did this before in another thread here not too long ago. Doh!!!!

    ::konk::

    Anyways, I corrected it.
    Cough

    Prelude has good advice there so don't get me wrong, it's just not applicable to game engine and/or game design in this instance.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  15. #15
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    So, clear out all the inheritance I'm using, obviously, the render engine doesn't need to know my speed variables, etc etc, so I don't need to put all those information into my scene_objects class.. We don't want to pass any unecessary variables to the renderer that the renderer really doesn't need...

    So ultimately, will I have a Scene_Objects class that only handles location variables? What will handle all the speed variables and movement? Will each object use a physics class in the same way they use the renderer?
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

Popular pages Recent additions subscribe to a feed