Thread: I believe I've found an official Answer to my Problem (Object Factories)

  1. #16
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    There we go, thats what you want eh Shamino.

    Well, I've told you why thats unnecessary, as Bubba, Gamedev, and CornedBee have. Just to remind you if its accepting all Monsters, then shouldn't all Monsters have this data? Then simply have getters/setters for this data. You shouldn't need anymore than this data in your Render functions.

    First solution: but if you do need data some other special subclass has that others dont, then you could just use virtual functions in Monster.

    Second solution: I've said this already, but you can just make the function for Render a template so it can accept any class. The thing is that you would have to use an if statement in order to determine its this special subclass - so why not just overload the function for this special subclass instead. Templates are like overloading, so either way works, but templates reduce the amount of code.

    Those are the two simple solutions that DO work.
    Last edited by Dae; 12-17-2005 at 06:12 PM.
    Warning: Have doubt in anything I post.

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

  2. #17
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Well, I've told you why thats unnecessary, as Bubba, Gamedev, and CornedBee have. Just to remind you if its accepting all Monsters, then shouldn't all Monsters have this data? Then simply have getters/setters for this data. You shouldn't need anymore than this data in your Render functions.
    NO, all monsters shouldn't have that data because not ALL monsters are alike, yet theyre ALL STILL CALLED MONSTERS!

    Think of this like a real life situation....

    we can call all mammals mammals because they give birth to live babies...

    But even though a dog might have fur and a whale might have a blowhole, doesn't make them not mammals...

    Therefore when we ask wtf is a mammal, we can say a whale is a mammal, we can say a dog is a mammal, even though they do completely different things....

    Second solution doesnt work, well it does, but its clunky and would ultimately become unmanageable...

    Solution one, thats the same as having 100 virtual functions in a monster baseclass, not happening!
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  3. #18
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    NO, all monsters shouldn't have that data because not ALL monsters are alike, yet theyre ALL STILL CALLED MONSTERS!

    Think of this like a real life situation....

    we can call all mammals mammals because they give birth to live babies...

    But even though a dog might have fur and a whale might have a blowhole, doesn't make them not mammals...

    Therefore when we ask wtf is a mammal, we can say a whale is a mammal, we can say a dog is a mammal, even though they do completely different things....

    Second solution doesnt work, well it does, but its clunky and would ultimately become unmanageable...

    Solution one, thats the same as having 100 virtual functions in a monster baseclass, not happening!
    Not all Mammals have mass and velocity, etc.?

    What kind of REAL example of information that Render would need that not all Mammals share?

    The second solution is for RARE cases, as I've stated too many times, and therefor would not be unmanageable. If you used it for all subclasses of Object you could avoid virtual functions and since its used for all subclasses of Object it would not be unmanageable, it would just be one method. The problem with that is its going to create a function for every different class (in the background).

    100 virtual functions? What kind of Render function do you have that needs to call 100 different functions from a generic type? Only in rare cases can I see Render needing specific information from subclasses of Object than Object does not contain, so there would be less than 5 at most.

    "Object should contain all the information it needs to be rendered." - quote by 100 million people across the world. Somewhat similar to Bubba, CornedBee (who recommends RenderableObject instead), and Gamedev have said.

    I think its you now thats asking too much, Shamino.
    Warning: Have doubt in anything I post.

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

  4. #19
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Whoa, we're not talking about just a render function anymore...

    Ogremonster has to become a client to any engine I wish it to!

    ONE CLIENT, for the physics engine to handle, for the renderengine to handle, for the sound engine to handle...

    On top of that, each client instance has to be able to call functions specific to the client I.E ogremonster..

    Okay,

    You did clear up one thing in my muddled head of thoughts...


    Okay, sure, you could virtualize render info, you could virtualize physics information, you could virtualize sound info...

    but you can't virtualize per say, a blowhole function and a fur function...

    there are tooooo many differences between each objects specific abilities to virtualize them all

    That is where I'm getting 100 virtual functions..
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  5. #20
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Alright, why do Sound/Render/Physics need to call these blowhole or fur methods?
    Last edited by Dae; 12-17-2005 at 06:47 PM.
    Warning: Have doubt in anything I post.

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

  6. #21
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Quote Originally Posted by Dae
    Alright, why would you want to virtualize a blowhole or fur method?

    Why do Sound/Render/Physics need to know this information?
    They don't.... But what would be the harm of giving them this information anyways? Would it slow us down?

    But you virtualize, because every new instance of OgreMonster must be able to use its specifically designed, bashyourfreakinheadoff() function, or its specifically designed pickyouupandthrowyou() function....

    And remember, if we're sending an ogremonster as an *Object, we would have to virtualize those specifically designed functions..
    UNLESS

    You pass pointers to those functions declared specifically in Ogremonster in ogremonsters constructor, therefore when you create the *Object you have access to those functions through pointers..

    Wait wait, you're mixing me up...

    WE DON'T want to virtualize the blowhole or the fur! And thats the problem! Because unless we don't, we can't access blowhole from the final *Object
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  7. #22
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    They don't.... But what would be the harm of giving them this information anyways? Would it slow us down?
    It wouldn't slow you down unless your implimentation did (which some of your previous ideas would a bit). But if they don't need this information than there is no harm, so why continue looking for a solution to a problem that doesn't exist.

    You pass pointers to those functions declared specifically in Ogremonster in ogremonsters constructor, therefore when you create the *Object you have access to those functions through pointers..
    Different subclasses of Object have different amount of methods, so you would have to be able to have an undeterminable amount of function pointers in your subclass - which I don't see happening. On top of that I don't see you being able to reroute those to the base Object class so they can be used to access the GoblinObject's methods. Furthermore the creation of an instance would include one hell of a long parameter (for the virtual functions) - 100 I think you stated. Lastly I don't see this as a logical solution.
    Warning: Have doubt in anything I post.

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

  8. #23
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    WE DON'T want to virtualize the blowhole or the fur! And thats the problem! Because unless we don't, we can't access blowhole from the final *Object
    I realized that and editted my original post exactly before you posted.
    Warning: Have doubt in anything I post.

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

  9. #24
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Ok guys let me add my two cents here and that's probably what it will be worth.

    First
    This design is already so complicated that you cannot even discuss it correctly.
    Therefore - scrap it. It won't add to speed, graphics, gameplay, or even manage objects well. What it will do as evidenced by this thread is confuse the hell out of ya.
    Scrap it.
    Using one function as an overall function for rendering is a great idea, however, you are approaching it incorrectly.

    Now pay attention because this is what Dae and CornedBee and Bob and all of us are saying. The ONLY common portion of any graphical object to be rendered are:

    • Vertex data
    • Texture data
    • Physics data


    Here is my suggestion. Throw templates out the window and throw the class inheritance virtual function thingy out the window. Too complicated. The problem with C++ inheritance is that when you look at your code you cannot tell at a glance what is happening because the inheritance is so deep.

    Get my drift here. I don't like virtual functions because they obfuscate the code quite easily with more than 1 derivation w/o adding that much flexibility to the engine.

    I don't like this:

    Code:
    class Base
    {
    
      virtual void Render()=0;
    }
    class Derived1:public Object
    {
      void Render();
    }
    
    class Derived2:public Object
    {
      void Render();
    }
    
    class Derived3:public Object
    {
      void Render();
    }

    Way too many renders for something that can be done in one function.

    Here is what I do like:

    1. Each object allocates it's vertex memory from a huge pool.
    2. The pool manager will return a starting index and an ending index for the data.
    3. Texture coord data is contained within the pool.
    4. Physics data is contained within the pool.

    Like this - ALL objects will have the following information, but not ALL objects will use every field in the structures. Texture coord data is contained in the VertexData struct I'll show this using vectors for now, later you would change to a static array IF your framerates suffered. I doubt they will.

    Code:
    struct PhysicsData
    {
    };
    
    class PhysicsContainer
    {
    }
    
    struct VertexData
    {
    };
    
    class VertexContainer
    {
    };
    
    
    struct PositionData
    {
    };
    
    class PositionContainer
    {
    };
    
    class MatrixData
    {
    };
    
    class MatrixContainer
    {
    };
    
    class TextureData
    {
    };
    
    class TextureContainer
    {
    };
    
    
    struct ObjectInfo
    {
      DWORD dwStartIndex;
      DWORD dwEndIndex;
      DWORD dwID;
      DWORD *dwTextureIDs;
    };
    
    
    class Object
    {
       ObjectInfo ObjectData;
    
       //One object may have more matrices
       //This is for transformation
       MatrixContainer        Matrices;
    
    };
    
    class ResourceCache
    {
      PhysicsContainer   Physics;
      VertexContainer    Vertices;
      PositionContainer  Positions;
      TextureContainer  Textures;
    };
    
    class RenderList
    {
      ResourceCache  *RenderData;
      std::vector<DWORD>  ObjectIDs;
    };

    So now all the main areas of information are encapsulated for each object and the rendering list simply has a vector that can be added to in order to create the render list. I would try to use a static array but the render list is built every frame so it's a bit tedious and time consuming.


    The final render list simply holds a list of IDs that are indices into the other containers for that object. So.

    Everything is based on IDs. The final result is that everything amounts to:

    1 function call, 1 lookup.

    If you make the arrays or vectors public in the container classes, then you don't even have to do the function call.

    This is a bit complex, but in the end it is very easy to use - it's just hard to setup.

    Sounds would use the same idea. All sounds reside in a sound container and can be accessed via their ID number.

    The final render list is simply a huge list of IDs of the objects that are visible in the current frame. The transformation engine then just iterates through this list, grabs the vertex and position information for that ID, grabs the matrix stack (if applicable) from the object, and transforms the object. Then the renderer will grab the texture data, etc, etc.

    This is a work in progress so there is still stuff to work out, but I hope you get what I'm saying here.
    Last edited by VirtualAce; 12-17-2005 at 07:02 PM.

  10. #25
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Har har, Dae

    In Robert Geiman's object factory, do you understand what those incredibly ugly hacked macro functions do?

    They create template support for up to 15 parameters, and you can easily change a single number in your code to add support for more...


    Therefore, I can pass in OgreMonsters constructor, up to 15 parameters, (or more, depending on how much i feel we need)...


    OMG its a perfect machine! I was right to begin with, with some modification this object factory is the holy grail...

    On top of that I don't see you being able to reroute those to the base Object class so they can be used to access the GoblinObject's methods.
    Its a function pointer, it points to the function definition in the origional declaration of OgreMonsters class, which is sent to the templated Monster1...

    So finally, and ultimately..

    We can go Monster1->bashyourfreakinheadoff();

    Okay cool bubba, but what happens when we need to send multiple objects to each engine? Each of them have different information based upon what the user gives them...

    And then on top of that what about giving each object their own specific functions?

    Each new instance of the object (if declared as an *Object), remember, Ogremonster is an *Object, but OgreMonster will have info declared only in ogremonster...

    So therefore we need the template that creates the *Object to know how to access those specific things, so we put function pointers in the constructor so that the new *Object (Monster1)

    can do this:

    Monster1->Bashyourfreakingheadoff();'

    or this

    Monster1->getrenderdata();

    or this

    Monster1->getphysicsdata();

    or this

    Monster1->getsounddata();

    You can view the PLAYER OF THE GAME as its own engine, this is where the need to access monster1->bashyourfreakinheadoff(); would be.

    And this way, the render engine will get only render information by calling Monster1-> getrenderdata();, and render it...

    Monsters only get registered if they are called by the user, or the gameworld (gameworld would have to create a map with no user interaction)....
    Last edited by Shamino; 12-17-2005 at 07:20 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  11. #26
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Hey Bubba,

    I'm sure you hate how people ask you a bunch of questions whenever you post, but..

    How does your std::vector<DWORD> ObjectIDs; work? Like how do you get the ObjectData from the object instance associated with the ID's in the RenderList? A manager with a map holding the IDs and a pointer to their instance?

    Thanks for the help BTW

    Its a function pointer, it points to the function definition in the origional declaration of OgreMonsters class, which is sent to the templated Monster1...

    So finally, and ultimately..

    We can go Monster1->bashyourfreakinheadoff();
    I dont understand how that works out, but alright. If you get that to work I would love to see.
    Last edited by Dae; 12-18-2005 at 03:42 AM.
    Warning: Have doubt in anything I post.

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

  12. #27
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Code:
    I dont understand how that works out, but alright. If you get that to work I would love to see.
    Hm, well remember, I'm theorizing here...

    And I theorize, the reason we couldn't access functions specific to OgreMonster from monster1 is because we lost the data, to remedy this, we send a pointer to the data, simple as that.

    I asked, I thought you could send the object factory up to 15 arguements?

    But, as Robert Geiman has just told me....

    It does, but not variable parameters. That is, you can declare the object factory to accept 5 constructor parameters, but then you must pass 5 parameters for ALL monster classes. You can't pass 5 to OgreMonster and 4 to TrollMonster.

    ARHG, back to drawing board...
    Last edited by Shamino; 12-17-2005 at 07:48 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  13. #28
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    we send a pointer to the data, simple as that.
    Well the reason I don't see it working is because it seems like you're forgetting something.

    Sure, you could find a way to accept n (any amount) of parameters (you dont even need macro magic, just use ...), and sure you could pass n amount of function pointers (of a subclass) to the base class, BUT theres a problem in the next step.

    Its a function pointer, it points to the function definition in the origional declaration of OgreMonsters class, which is sent to the templated Monster1...

    So finally, and ultimately..

    We can go Monster1->bashyourfreakinheadoff();
    You say it would be Monster1->bashyourfreakinheadoff();, but Monster1 doesn't just get extra functions because you passed it a function pointer. You would have to store that function pointer in Monster1, and then call a function that Monster1 has which calls the function pointer.

    The problem is that Monster1 would have to have n amount of function pointers in this class, and n amount of functions to call that redirect to the function pointers. Your idea may work for one function pointer, but how in the hell do you plan to make it so Monster1 can have n amount of function pointer stored, and have functions for each one to boot.

    I'd help you figure it out if I could see it happening at all. I'm very new to all of this, and don't know advanced C++ either, so its logical that I don't see anything working.
    Warning: Have doubt in anything I post.

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

  14. #29
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    But, as Robert Geiman has just told me....

    It does, but not variable parameters. That is, you can declare the object factory to accept 5 constructor parameters, but then you must pass 5 parameters for ALL monster classes. You can't pass 5 to OgreMonster and 4 to TrollMonster.
    Yeah, thats the part that was confusing me. I couldn't figure out how you were going to get a class to have n amount (any amount based on the subclass) of function pointers.
    Warning: Have doubt in anything I post.

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

  15. #30
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Read my edit, first of all this wouldn't work at all...

    But, to answer your question, as if this would work...

    if something points to something, it always points to it, no matter where you put it or send it...

    if we pass bashyourheadoff pointer to the monster1 thingy..

    and then call monster1->bashyourheadoff

    simply all we're doing is referring back to the origional definition of bashyourfreakinheadoff, which is in ogremonster only... we can activate the function through the pointer, which now happens to belong to monster1...

    but unfortunately, read what rob told me...

    If we were to make this work we'd be the da vinci's of programming, but i don't see it happening.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. using this as synchronization object
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 03-22-2008, 07:49 AM
  2. problem with answer going to default?
    By Patrick1234 in forum C++ Programming
    Replies: 4
    Last Post: 10-02-2002, 09:11 AM
  3. slight problem just can't see the answer
    By anthonye in forum C++ Programming
    Replies: 1
    Last Post: 07-05-2002, 08:45 AM
  4. I've ran into a problem
    By Mike Jones in forum C Programming
    Replies: 1
    Last Post: 03-27-2002, 04:08 PM
  5. code help :)
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 02-28-2002, 01:12 PM