Thread: What's a good Object Oriented Strategy for OpenGL/Graphics

  1. #1
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901

    What's a good Object Oriented Strategy for OpenGL/Graphics

    I'm learning from a book which has a good strategy of putting everything necessary to a scene in an object, and each object member corresponds to a certain duty that is necessary for opengl to show a scene such as one function for initializing all lights and another for preparing the objects for redrawing, one for resizing and one for rendering etc. I find this useful because I can move this object and use it more easily between different APIs such as windows and glut. I was wondering if anyone uses a different strategy for rendering an opengl scene than this one.

  2. #2
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,071
    I use a lot of nested inheritance in my setup. ASCII chart time ...

    EDIT: ASCII chart not working too well . I'll attach an image instead.

    EDIT EDIT: For windowing APIs and stuff, I generally just write an OpenGL "driver" that handles resizing and rendering. On it's rendering function, I call my engines run function, which makes calls to run the graphics, physics, AI, etc threads.
    Last edited by psychopath; 04-03-2007 at 09:52 AM.
    M.Eng Computer Engineering Candidate
    B.Sc Computer Science

    Robotics and graphics enthusiast.

  3. #3
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    A Scene Graph is a great way. Aside from that I generally model my entities in a Java-esque sort of way, but with 1 or 2 layers of abstraction instead of 9 or 10 Something like a top level "Object" or "GraphicObject", from which "AnimatedObject" or "Mesh" could be derived, then more specific things like "Terrain" etc...

  4. #4
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Cool stuff, going to bury my face in it when I finish with my dabbling. Here's an example of what I use, it's unfinished thought. I'm pretty much reproducing the structure of how the book does it though, but I like the way it structures it.

    Also, is it better to dynamically allocate the classes rather than create everything on the stack? The book dynamically allocates it but I don't assume I know why.

    Code:
    class CGfxOpenGL
    {
        public:
            CGfxOpenGL();
            virtual ~CGfxOpenGL();
    
            //sets up initial OpenGL states
            bool intialize();
    
            //projection function
            void setupProjection(int width, int height);
    
            //cleans up all OpenGL Internal states
            bool shutDown();
    
            //prepares the scene for rendering (if animation needed)
            void prepare();
    
            //renders the scene
            void render();
            
        //special functions
        void toggleFlashLight() { flashLightOn = !flashLightOn; }
    
        private:
            int windowWidth;
            int windowHeight;
    
            bool flashLightOn;
    };
    edit: psychopath I'm having a hard time visualizing your structure, could you maybe display a shell of the type of structure you're talking about?
    Last edited by indigo0086; 04-03-2007 at 10:16 AM.

  5. #5
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    I'm assuming psycho's diagram doesn't represent inheritance...

  6. #6
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,071
    Quote Originally Posted by Perspective
    I'm assuming psycho's diagram doesn't represent inheritance...
    Oh, but it does .

    Here's the basic setup that i'm talking about in code (albeit extremely condensed):
    Code:
    class C3dw{
    private:
        /*loader data here. arrays of structs and such*/
    
    public:
        int _3dwShaderID;
        /*other data here*/
    
    public:
        C3dw(){
            //init stuff
        }
        virtual ~C3dw(){
            //delete stuff
        }
    
        char Load3DW(std::string filename, /*other args here*/);
        void Render3DW(CTextureMgr *texMgr, CGlslMgr *glslMgr);
    };
    
    /* same idea for CMs3d and CQ3Bsp */
    
    class CModel : C3dw,CMs3d,CQ3Bsp{
    public:
        MODEL_TYPE type;
    
        Mat44 matrix;
        Vec3 position, rotation, scale;
        Vec3 min, max;
    
        bool selected;
        /*other data.*/
    
    public:
        void RenderModel(CTextureMgr *texMgr, CGlslMgr *glslMgr){
            if(MODEL_TYPE==MODEL_3DW){
                Render3DW(texMgr, glslMgr);
            }
        }
        /*other funcs for calulating normals, tangents and stuff. call child counterparts like the render func*/
    };
    
    class CObject : CModel{
    public:
        int ID;
        std::string name;
    
    public:
        void Position(Vec3 pos);
        /*other funcs for matrix manipulation here*/
        void Render(CTextureMgr *texMgr, CGlslMgr *glslMgr, Vec3 view){
            glMultMatrixf(/*args*/);
            RenderModel(texMgr, glslMgr);
        }
    };
    
    /*not much to the staticmesh. light entity includes additional values like diffuse colour and stuff*/
    class CStaticMesh : CObject{
    public:
        CStaticMesh(/*name, file, shader, texture, manager pointers, etc*/){
           /*based on MODEL_TYPE, load model. in this example, with Load3DW()*/
       }
    };
    
    class CWorld{
    public:
         int numObjects;
         std::vector<CObject*> objects;
    
         int numStaticMeshes;
         std::vector<CStaticMesh*> staticMeshes;
    
    public:
        CWorld(){ /*init stuff*/ }
        ~CWorld(){ /*delete stuff*/ }
    
        void Render(){
            /*for each object, call objects[i]->Render(); (and other GL stuff)*/
        }
        void UpdatePhysics();
    
        void AddStaticMesh(/*args*/){
            staticMeshes.push_back(new CStaticMesh(/*args*/));
            staticMeshes[numStaticMeshes]->ID = numStaticMeshes;
    
            objects.push_back(staticMeshes[numStaticMeshes]);
    
            numObjects++; numStaticMeshes++;
        }
    };
    
    class CWorldMgr{
    public:
        /*vector of worlds and stuff*/
    
    public:
        /*functions to create and delete a world, and get a world ID here*/
        void WorldGfx(CWorld *world, /*manager poninters*/){
            world->Render(/*args*/);
        }
        /*funcs for physics and logic here*/
    };
    That should be enough code. I have anther class called CGfxCtrl that calls CWorldMgr::WorldGfx, passing the current world (tracked in CEngine) as a parameter. CEngine is created by the main application, which in it's contructor creates CGfxCtrl, as well as controllers for physics and stuff. These "controllers" are used for threading of each engine componant. Then in the application loop, I just call something like engine->Run(); which continues down the heirarchy to gfxCtrl->Run(), and so on. Viewport setup and that sort of thing is handled outside of the engine.

    Needlessly complicated? Probably. But it works for me ;p.
    Last edited by psychopath; 04-03-2007 at 12:20 PM.
    M.Eng Computer Engineering Candidate
    B.Sc Computer Science

    Robotics and graphics enthusiast.

  7. #7
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    well, not really. A CWorldMngr is not a CWorld for example.. .only some of those lines represent inheritance.

    Also, does every CModel need all of the data from each of the inherited classes? This doesn't seem likely, flagging which type of class it is with a member variable is bad practice, you should have separate inherited classes for each type.

  8. #8
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,071
    well, not really. A CWorldMngr is not a CWorld for example.. .only some of those lines represent inheritance.
    Oh, yeah. Forgot about that part of it. Ok, so most of it is inheritance.

    Also, does every CModel need all of the data from each of the inherited classes? This doesn't seem likely, flagging which type of class it is with a member variable is bad practice, you should have separate inherited classes for each type.
    But does it really matter? With the current setup, somewhere along the way the three format classes either have to be inherited or have instances created on the CModel contructor, in which I'd still need to use member variable to figure out what to do.

    I could set up a centralized format I guess, that all the other formats are converted too. But the problem I beleive that creates, is if the formats are very different. I can see it getting quite difficult to make them all generic without losing their individual functionalities.

    IMO, with this inheritance scheme, it's easier to wrap each of the types. No, a 3dw doesn't need ms3d data, but if it doesn't need it then it doesn't use it anyway.
    M.Eng Computer Engineering Candidate
    B.Sc Computer Science

    Robotics and graphics enthusiast.

  9. #9
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    >No, a 3dw doesn't need ms3d data, but if it doesn't need it then it doesn't use it anyway.

    but when you create an instance of a CModel class, you get all of the members of each of the parent classes allocated.

  10. #10
    The Right Honourable psychopath's Avatar
    Join Date
    Mar 2004
    Location
    Where circles begin.
    Posts
    1,071
    but when you create an instance of a CModel class, you get all of the members of each of the parent classes allocated.
    Good point. For whatever reason, it didn't occur to me that the memory was still being used. In that case, it looks like I'll be changing this to avoid the format inheritance.
    M.Eng Computer Engineering Candidate
    B.Sc Computer Science

    Robotics and graphics enthusiast.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Object Oriented WinAPI
    By Uwar in forum Windows Programming
    Replies: 2
    Last Post: 05-27-2009, 11:18 PM
  2. new to object oriented!!!!
    By salmanriaz in forum C++ Programming
    Replies: 2
    Last Post: 03-12-2009, 07:43 AM
  3. Linked List Templates and Object Types
    By ventolin in forum C++ Programming
    Replies: 10
    Last Post: 06-16-2004, 12:05 PM
  4. OBJECT ORIENTED VS C STYLE for small projects
    By Shadow12345 in forum C++ Programming
    Replies: 17
    Last Post: 01-15-2003, 03:50 PM
  5. C better than C++? (POLL)
    By Lynux-Penguin in forum A Brief History of Cprogramming.com
    Replies: 28
    Last Post: 05-03-2002, 03:34 PM