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

Hybrid View

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

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

    Searching, searching, searching...

    Always I had a few questions, how the heck do I create new instances of objects without writing 30 lines of code (probably a hundred or so in some cases).


    How do I pass an "Object" to a function that simply pushes the object into a vector, while being able to send all of the class "Object" derivedrens unique? Ultimately, Passing *Object to the function while *Object might be a space ship, a wall, a planet, an asteroid, a tree, etc etc...

    The answer is an Object Factory. An Object factory that creates other Object Factories, a super factory to manage -EVERY- object in your entire program. This "Object Factory" would be at the very very very VERY tip top of your Include files, included once into the entire project, but used and weaved in throughout, in amazingly seemless OOP.

    I believe this is the HOLY GRAIL of oop, the pinnacle of C++ as an object oriented language, and to boot, not that difficult to understand the outlying structure of the whole thing.


    I will include an example of a simple Object Factory below..

    The article was written by Robert Geiman and is on www.GameDev.net .

    Props
    Last edited by Shamino; 12-16-2005 at 06:05 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #2
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    The actual OO part of that design is pretty standard and not to the max at all (theres tons of design patterns, and standard OO features (multiple inheritance, etc) that it doesnt use. It is definetly close to the max it could go on this feature for sure (macro magic, templates, classes, oo, maps, etc.). God, I hate when macro magic is necessary..

    The point of this is so that it returns the right subclass type, so it shouldnt be assigned to the base class Monster, it should be assigned to the subclass. So it should actually be this:

    Code:
       GoblinMonster *monster1 = monster_factory.Create(GOBLIN_MONSTER, 34.5f, 63.0f, 7.7f);
       OgreMonster *monster2 = monster_factory.Create(OGRE_MONSTER, 83.0f, 14.2f, 54.4f);
    You should be using monster1.UnRegister(GOBLIN_MONSTER); too.

    Your examples kind of fail to show why this is useful at all. Of course you have a system to handle all objects (thats obvious). However instead of returning the base class Object, you can return the correct subclass. You've found the article on how to do that. In order to utilize this you would have to have to do sort of what the Create() method does, and search for the correct subclass by id, but instead of returning NULL, when you find it you return the subclass. So then simply add a new method to class ObjectFactory:

    Code:
    BaseClassType *Find(UniqueIdType unique_id)
          {                                                                                                     
             Iterator iter = m_object_creator.find(unique_id);         
                                             
             if (iter == m_object_creator.end())                                                                
                return NULL;        
                                                                                
             return (*iter).second;
    }
    BTW since these objects have to be searched for, the have an overhead of O(log n) instead of O(1).

    The reason you're seeing the constructor for the OgreMonster is because it actually does exist in the map in the ObjectFactory, but when you assign it to Monster you arent going to be able to access functions that OgreMonster has but Monster does not. Try it out and please let me know if I'm wrong, because that would be great if I was wrong - the problem would be solved.

    I can't figure out how it would work. Of course you can get the subclass you want, but you could do that anyway - that isn't the problem. The problem is the recieving end of a function. Now that you see you cant assign it to the Monster class, that should be apparent. You would have to know what class to assign it to (OgreMonster or GoblinMonster) in the function you are passing say the ID or object to. Which is the whole problem in the first place and that makes this factory pointless as a solution (its a nice factory, but I dont see it being a solution to this problem). You could template a function accept the Ogre type.

    But thats just annoying and I'd rather just stick all of the information CRender, CWorld, and CPhysics need in Object and be done with this problem.

    EDIT: I can't compile it to test anyhow, what compiler do you use?

    EDIT: You could do the most valuable test by keeping monster1/2 as type Monster. Then simply give OgreMonster and GoblinMonster two different functions, and then calling monster1->function1(), and monster2->function2(), and see if the compiler tells you monster1/2 don't contain those functions (like it normally would).
    Last edited by Dae; 12-16-2005 at 08:50 PM.
    Warning: Have doubt in anything I post.

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

  3. #3
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    The template class uses function pointers, therefore you can access the functions of the derived classes...


    Code:
    class WalkForwardCommand : public Command
    {
    public:
       WalkForwardCommand() {}
       virtual ~WalkForwardCommand() {}
    
       virtual void Execute()
       {
          std::cout << "\nWalking forward...\n" << std::endl;
       }
    };
    You can call Execute just fine, and I'm going to assume you can access any variables held in the walk forward command, why would it be any different?

    Oh wait, command has a virtual Execute function, let me think on this one...

    I think this is where you're asking too much Dae. (someone correct me if I am wrong)

    What needs to access which functions in your classes?

    A render function needs to access model data, therefore you create a Scene_Object class, which handles nothing but pictures.

    A Game world needs to access physics and collision detection, therefore you create a Physics_Object class, the reason you can't combine Scene_Objects and Physics_Object is because the renderer doesn't need to know physics data and functions, it just needs to know a final result (x, y, z changes)

    Having one class that does it all, simply isnt the essense of OO.. Think, A Goblin doesn't have physics, physics effect Goblins.

    You, unfortunately Dae, cannot create a super Object class unless you use 100 virtual functions for everything any object might use, even if they don't use it... (correct me if I am wrong, someone)

    I might be talking way over my head of knowledge, but you would think if you've been searching for any amount of time at all, and no one could answer your question efficiently, it simply can't happen, I've seen your posts, they make perfect sense...

    I'm going to email the creator a few times and ask him questions.

    Code:
    class OgreMonster : public Monster
    {
    public:
       OgreMonster(float x, float y, float z)
       {
          std::cout << "Ogre monster created at coordinate: " << x << ", " << y << ", " << z << std::endl;
       }
    };
    When the OgreMonster is created, xyz is returned... OgreMonster is a function (constructor really)..... I guess that doesn't count. Is there a such thing as nested functions? Perhaps a function def inside the constructor ?

    OR:

    You could create an OgreMonster factory, with a couple functions specific to OgreMonster... I think that would become redundant, because that would be narrowing down our thing we wanna return, we wanna be able to return a pointer to a general monster while keeping all that data... Hmmm

    FINALLY:

    I think I have the answer, its function pointers, simple as that, easy as pie. Instead of having the Constructor of OgreMonster have just an x,y,z arguement, give it more arguements, one pointer for each function. This way those function pointers would be created in the new Monster object, reay to use. (right? )
    Last edited by Shamino; 12-16-2005 at 10:11 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  4. #4
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    No, your monster1/2 would not be able to access Ogre/Goblin specific functions because you're casting them to the base class Monster.

    The template class uses function pointers, therefore you can access the functions of the derived classes...
    The function pointer is so that you can create the subclass, and its stored in a map along with an id.

    I reread the article and completely understand now. It is not meant to resolve my or your issue. I was actually wrong and it doesn't even store the instances. However it does create them and then return them, so thats why your constructor for Ogre/Goblin was being called. I believe he simply casted the returned class to the base class as an example, which would be file for interfaces. Rereading the intro in that article I can't believe I spent so much time looking at it. I've decided to stop reading these specific design patterns for a while, at least until I finish the prereq Design Patterns.

    You, unfortunately Dae, cannot create a super Object class unless you use 100 virtual functions for everything any object might use, even if they don't use it... (correct me if I am wrong, someone)
    I realized that, and thats why I was seeking a different way. There are many ways to do one thing yeah know.

    Sorry if I was the one that got you hung up on my goal to make it so there was no dataloss when recieving an Object as a parameter. I've decided I've probably been overdoing it and yeah, expecting too much. So I've decided to simply put all information (mass, velocity, coords, etc) that CPhysics, CWorld, or CRender might need for Object's in Object.

    I think this is where you're asking too much Dae. (someone correct me if I am wrong)
    However, I talked to some people at EFnet, and there is a way to accomplish want I wanted. The very simple way is to make a templated method. I could then pass it any class, problem solved. The only reason I wont do this, unless for some rare reason, is because obviously thats going to make multiple copies of the function for each class and its a bit more complicated. Plus I hear they might be the devil.

    I think I have the answer, its function pointers, simple as that, easy as pie. Instead of having the Constructor of OgreMonster have just an x,y,z arguement, give it more arguements, one pointer for each function. This way those function pointers would be created in the new Monster object, reay to use. (right? )
    I've got to say thats overdoing it more than me.

    When the OgreMonster is created, xyz is returned... OgreMonster is a function (constructor really)..... I guess that doesn't count. Is there a such thing as nested functions? Perhaps a function def inside the constructor ?
    Yeah it doesn't count, because of what I said two times. Nope, theres no nested functions in C++.

    A Game world needs to access physics and collision detection, therefore you create a Physics_Object class, the reason you can't combine Scene_Objects and Physics_Object is because the renderer doesn't need to know physics data and functions, it just needs to know a final result (x, y, z changes)
    Well, you can combine them actually. The thing is, whats your point? CRender takes a pointer so it doesnt matter if the object has extra data it doesnt need to use, it just doesnt use it. My problem was that I thought there would be some variables that CPhysics, or CWorld might require in a generic function that not all Objects shared and therefor should not be put as high up as in the Object class. I cant think of any examples, but I was trying to think ahead. As I've said I've decided I cant think of any reason not to, and will not put velocity, mass, coords, etc. that CRender, CPhysics, and CWorld may need in Object.

    Having one class that does it all, simply isnt the essense of OO.. Think, A Goblin doesn't have physics, physics effect Goblins.
    I did not mean for a class that does it all, what I meant for was a function that was generic (and I cant believe I didnt realize to use a templated method because thats a generic function) so it could accept any subclass of Object. BTW physics may effect Goblins, but Goblin still needs to know its mass, velocity, etc. and then physics uses that data to change Goblins position. Simple.
    Last edited by Dae; 12-17-2005 at 02:07 AM.
    Warning: Have doubt in anything I post.

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

  5. #5
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    The only arguement I have is about Goblin Knowing its mass and velocity, Goblin doesn't need to know those things, some other higher power does, (a physics engine)..

    But for the most part you are right.

    Although, You mean we could solve the problem with function pointers in the constructors parameters, so they would be passed to the template class?

    If theyre the devil, they sure allow you to do a beautiful thing.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  6. #6
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Few words from Robert Geiman

    first, Dae is correct, you don't want to convert the pointer returned from the Create() function into the derived class (ie, OgerMonster *m = f.Create<OGER_MONSTER>(). If you already know the derived class type then you don't need the object factory class.

    Second, I'm not sure I fully understand your problem.

    Normally when you're in a situation where you want to use the object factory class, you'd create multiple instances for specific groups of classes. In other words, you don't derive every class in your game from a BaseClass type and create one BaseFactory class.

    Instead you create seperate factory classes, one for each group of common classes. For example, a MonsterFactory instance for all monsters, or a RenderFactory instance for OpenGL and DirectX renderers. This way each derived class should already contain the same generic functions.

    As far as accessing data that's specific to each derived class, that can be done by the class itself. For instance:

    Code:
    class Monster
    {
    public:
       virtual void Execute() = 0;
    };
    Code:
    class OgreMonster 
    {
    private:
       std::string ogre_name;
    
    public:
       void Execute() { std::cout << "Private ogre name s: " << ogre_name << std::endl; }
    };
    Code:
    class TrollMonster
    {
    private:
       bool is_cave_troll;
    
    public:
       void Execute() { std::cout << "Private cave troll value is: " << is_cave_troll << std::endl; }
    };
    If this doesn't help you, perhaps you could give me more specifics on what exactly you're trying to accomplish.

    Rob Geiman
    I responded like this

    Code:
    class Monster
    {
    public:
       virtual void Execute() = 0;
    };
    
    class OgreMonster 
    {
    private:
       std::string ogre_name;
    
    public:
       void Execute() { std::cout << "Private ogre name s: " << ogre_name << std::endl; } 
     
       void Newfunction
       {
            std::cout << "new function" << std::endl; // we wanna be able to access
        }  // this function in every new instance of OgreMonster  (
    
    };
    We want to be able to create functions specific to only OgreMonster that don't need to be virtualized in OgreMonsters Base class (Monster)

    So when we basically create a new monster with your factory, we wanna be able to access functions specific to every single individual monster as well (I.E, no data loss)

    I though function pointers were a good idea, pass a pointer to a function specific to the individual monster, therefore you could access them easy as pie in the new templated class.

    Any suggestions?
    Last edited by Shamino; 12-17-2005 at 04:31 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  7. #7
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Then what did this mean? It implies you dont want Goblin to know its own information.

    Quote Originally Posted by Shamino
    The only arguement I have is about Goblin Knowing its mass and velocity, Goblin doesn't need to know those things, some other higher power does, (a physics engine)..
    What you said in your last post, about it knowing its information and using it as a client, is exactly what I'm doing.

    I think I get what you mean in your last post (even though your previous posts go against it), that you want the data to be in Goblin and not in Object? Is that what you mean? It couldnt be, because Goblin derives from Object and therefor has that data.

    Your code works fine, just put MS3DModel *Model1; in Object, I mean what Object's couldn't be Rendered anyway? If there are some you can think of, just use CornedBee's advice and make a class RenderableObject and put MS3DModel *Model1; in that, and derive Goblin from that, and pass Goblin to CRender, which has parameter RenderableObject*.

    I don't see you having any problem doing that Shamino.

    usage would be ultimately simple.
    You don't even need a class factory to do what you want to, which requires you to have a few complex files, and register classes, and create classes, and adding it so you can add virtual functions for reach function is like you just agreed going to make it more complex. Besides that, I don't think the usage would be simple. When registering would you not have to pass a virtual function for each function your class contains? Wouldnt that be like up to 20 parameters, which could change if your classes functions change names or get removed or added. The class factory would also need to be able to accept any amount of parameters of virtual functions (...) too, so that would be fun to impliment. That is unless you made a function to add a virtual function one at a time, ie if your class had 15 virtual functions thats 15 function calls. On top of all of that, you do all of this simply to avoid a vtable lookup for each function when you're only doing this for Objects where they arent being called millions of times a second anyway (where it becomes a problem). I don't see where the complexity ends.
    Warning: Have doubt in anything I post.

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

  8. #8
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    That's quite simply not possible in the static typing system of C++. In order to call a function on an object, you need to have a reference or pointer to that object that is of a type that actually contains the function. Therefore, to call an OgreMonster-specific function, you need an OgreMonster* to the object. If the object is currently only available as a Monster*, you have to do a downcast, which means you also need to find out if the runtime object is of type OgreMonster (or derived). This is possible using dynamic_cast or some other RTTI mechanism, but it always involes an if().

    You have to see it this way. Given an object factory
    unspecified create(Tag type);
    and a variable
    Tag tag;
    the call
    Monster *p = create(tag);
    is for the compiler completely opaque (usually). tag might be OGRE_TAG or GARGOYLE_TAG, but there's not way to know that at compile time. Who knows, the value of tag could have been created like this:
    tag = rand() % 2 ? OGRE_TAG : GARGOYLE_TAG;
    The best you can supply for 'unspecified' therefore is Monster*, meaning you lose some type information.

    On the other hand, one of Dae's basic requirements in this debate is flawed:
    My problem was that I thought there would be some variables that CPhysics, or CWorld might require in a generic function that not all Objects shared and therefor should not be put as high up as in the Object class. I cant think of any examples, but I was trying to think ahead. As I've said I've decided I cant think of any reason not to, and will not put velocity, mass, coords, etc. that CRender, CPhysics, and CWorld may need in Object.
    What you're doing here is overdoing genericity. Or perhaps not, in a way. What it comes down to is this: CRender renders RenderableObject, CPhysics affects PhysicalObject and CWorld contains WorldObject. Whatever's not in these classes (or interfaces, more likely) is of absolutely no interest to these classes. Should you find that your CPhysics needs to access a property that's specific to OgreMonster, your class design is flawed and you need to rethink it.

    There's another interesting topic here, and that's where you draw the line of additional subclasses. Take Blizzard's Diablo 2, for example. (It's a good example, because I know for a fact that it's written in C++.) Do you think they wrote a Skeleton class, a Ghoul class, a Sabercat class, and an Andariel class? Or to go further, did they write classes for BurningDead, Horror, Returned and all the other classes of skeletons you encounter?
    They did not. There might be a Monster class deriving from Character, though I wouldn't even bet on that, and that Monster class is then configured solely by properties: which monster type it is, which model therefore is to be used, what class it is, what level, what special properties it has. There's behaviour scripts attached, and action scripts (e.g. those nasty oversized bugs that cast lightning every time they're hit). All that comes from data files - even the scripts. It's called data-driven design.

    I'm just mentioning this because separate classes for Ogres and Goblins seem too specific for me.
    But it's also a question of extensibility vs effort. It's easier to write a few specific classes than to write the environment that allows extensibility a la Total Annihilation.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  9. #9
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by CornedBee
    What you're doing here is overdoing genericity. Or perhaps not, in a way. What it comes down to is this: CRender renders RenderableObject, CPhysics affects PhysicalObject and CWorld contains WorldObject. Whatever's not in these classes (or interfaces, more likely) is of absolutely no interest to these classes. Should you find that your CPhysics needs to access a property that's specific to OgreMonster, your class design is flawed and you need to rethink it.
    You're right. I cant think of a case where that problem does exist, and I guess if it does occur then you're right I should rethink it rather than overloading methods. But I'll save that for when I actually encounter that problem.

    BTW that was a typo, I meant:

    As I've said I've decided I cant think of any reason not to, and WILL put velocity, mass, coords, etc. that CRender, CPhysics, and CWorld may need in Object.
    Shamino, don't you think that would be supremely complex?

    Would you mind giving us an example of your ideal Object and derived classes so we can see why exactly you're avoiding putting velocity, mass, etc. in Object so much? Thats what EFnet and Gamedev recommended to do. I don't see any problem with that, the only reason I brought it up was because I was thinking ahead.

    Oh yeah I forgot, thanks for the reminder CornedBee, I was planning on splitting it up into something like PhysicalObject, Renderable, nonRenderable, etc. as I read half an article about this months ago. Yeah that is an interesting topic, I wouldnt mind reading up on how to do that, haha.
    Warning: Have doubt in anything I post.

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

  10. #10
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    968
    Shamino, don't you think that would be supremely complex?

    You're saying that we cant have Base class (templated) A = to a Derivedren B, C, D, or E?

    We want to be able to pass a single *Object to a function, rather than a B, or a C, or a D, or an E...
    Maybe in the actual creation of the system, yes, quite possibily, but the usage would be ultimately simple.



    Also, in case you might be misunderstanding me, I would like to have OgreMonster control all of its own data, I don't want to split it up into a million classes, I <DO> want OgreMonster to have its own functions, its own data, so that everything can use OgreMonster correctly, I want the renderengine, the physics engine, the sound engine, everything, to be able to use OgreMonster as a client....

    I ultimately wanna be able to do this (pulls up his project)


    Code:
    class Object
    {
    public:
    
    	bool MarkedForDeletion;
    
    	struct Location
    	{
    		float locx;
    		float locy;
    		float locz;
    	};
    
    };
    
    class Cross : public Object
    {
    public:
    
    	MS3DModel *Model1;
    
    };


    Then Ultimately..

    Code:
        if (Obj != NULL)
        {
    		Scene_Object_Manager::AddScene_Object(Obj);
        }
    As you can see, I'd like to be able to push an Obj into the vector.... Not have to put a cross in there, or an OgreMonster, or a GoblinMonster, etc etc etc....

    Then after that

    we'll have a draw function in the render class simply file through that container of scene objects, grab their model data, and draw it accordingly...

    Robert Geiman told me this

    You really want to be totally ignorant of the actual derived class type as possibe. Any class specific work should be done from within the class itself. For instance, in Quake 1 (which used C not C++) every game object had an Update() function pointer. This function pointer was called every game loop on ALL game objects, and this function pointer would just point to a class specific function for each class type. The same thing would be true of C++, except you'd have a virtual Update() function that each derived class type overrides.
    Now that sounds like a plan.......
    Last edited by Shamino; 12-17-2005 at 05:45 PM.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  11. #11
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Quote Originally Posted by Shamino
    Robert Geiman told me this



    Now that sounds like a plan.......
    Thats a great idea.

    Only one vtable lookup (which I've said two times now isn't a problem unless you're calling it many times a second) thats pretty powerful.

    I don't think I'll worry too much about virtual functions for my Objects. Especially when its only a few.
    Warning: Have doubt in anything I post.

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

  12. #12
    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.

  13. #13
    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

  14. #14
    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.

  15. #15
    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

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