OpenGL screen savers

How to develop a fantastic 3D screen saver with OpenGL 1.1 Environment: VC5.0, Win95/98, NT4.0 This article just gives a description about how to use some new render functions in OpenGL 1.1 with a fantastic 3D screen saver. And give a practical method to solve the problem about how to instance the setting dialogbox successfully from windows system properties dialogbox both in Win95 and NT. The code also give a demo to use function pointer.

  1. Interleaved arrays and indices array for rendering. In OpenGl 1.1, there are some new functions quite different from old Version, which make rendering 3D picture faster and easily in coding.
  2. One of new methods in OpenGl 1.1 is that it can allow the developer to set the most important data , such as texture, colors, normals, vertexs, in an interleaved data structure body and build one vertex array. Besides that, an indices array is necessary for rendering. The two key functions in this realization are "glInterleavedArrays" and "glDrawArrays". The definition of vertex structure for "glInterleavedArrays" function depends on what format will be used in "glInterleavedArrays". The definition of the indices array also bases on what type of rendering index in "glDrawArrays" The following is the vertex structure and indices (with C++ template) in this demo.
    
    
    //Vertex value of the object
    template <class Typeclass vertex
    {
    public:
        Type m_texture[2];
        Type m_normal[3];
        Type m_vertex[3];
    
    public:
        vertex(){};
        ~vertex(){};
    
        void SetTexture(Type texture1, Type texture2)
        {
            m_texture[0] = texture1;
            m_texture[1] = texture2;
        };
    
        void GetTexture(Type* texture1, Type* texture2)
        {
            *texture1 = m_texture[0];
            *texture2 = m_texture[1];
        };
    
        void SetNormal(Type normal1, Type normal2, Type normal3)
        {
            m_normal[0] = normal1;
            m_normal[1] = normal2;
            m_normal[2] = normal3;
        };
    
        void GetNormal(Type* normal1, Type* normal2, Type* normal3)
        {
            *normal1 = m_normal[0];
            *normal2 = m_normal[1];
            *normal3 = m_normal[2];
        };
    
        void SetVertex(Type vertex1, Type vertex2, Type vertex3)
        {
            m_vertex[0] = vertex1;
            m_vertex[1] = vertex2;
            m_vertex[2] = vertex3;
        };
    
        void GetVertex(Type* vertex1, Type* vertex2, Type* vertex3)
        {
            *vertex1 = m_vertex[0];
            *vertex2 = m_vertex[1];
            *vertex3 = m_vertex[2];
        };
    };
    
    typedef vertex<float fVertex;
    
    //Indices value of the object
    template <class Typeclass indices
    {
    public:
        Type m_indice[2];
    
    public:
        indices(){};
        ~indices(){};
    
        void SetIndices(Type indice1, Type indice2)
        {
             m_indice[0] = indice1;
             m_indice[1] = indice2;
    
        };
    
        void GetIndices(Type* indice1, Type* indice2)
        {
             *indice1 = m_indice[0];
             *indice2 = m_indice[1];
    
        };
    };
    
    typedef indices<unsigned int uiIndice;
    
    The rendering implementation in code is
    
    class CSGObject : public CObject
    {
    //Attribute
    private:
    ............
        fVertex*    m_vertex;   //vertex array
        uiIndice*   m_indice;   //indices array
    ............
        float       m_x;        //x-coordinate of the center of object
        float       m_y;        //y-coordinate of the center of object
        float       m_z;        //z-coordinate of the center of object
    
        float       m_sx;       //scale in x-axis
        float       m_sy;       //scale in y-axis
        float       m_sz;       //scale in z-axis
    
        float       m_rx;       //rotating angle around x-axis
        float       m_ry;       //rotating angle around y-axis
        float       m_rz;       //rotating angle around z-axis
    
        BOOL        m_bWire;    //flag for showing wireframe or not
    public:
    ............
        void DrawObject(void);
    ............
    };
    
    void CSGObject::DrawObject(void)
    {
        int k;
        int i;
    
        if(m_bWire)
        {
             m_dvalue.SetValue(m_dMemvalue.m_dX*4, m_dMemvalue.m_dY*4, m_dMemvalue.m_dZ*4);
             m_size.SetValue((int)(m_Memsize.m_row*2.5), (int)(m_Memsize.m_col*2.5));
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        }
        else
        {
             m_dvalue.SetValue(m_dMemvalue.m_dX, m_dMemvalue.m_dY, m_dMemvalue.m_dZ);
             m_size.SetValue(m_Memsize.m_row*10, m_Memsize.m_col*10);
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }
    
        if(m_Oldsize.m_row != m_size.m_row || m_Oldsize.m_col != m_size.m_col)
        {
            if(m_vertex)
                 delete []m_vertex;
            if(m_indice)
                 delete []m_indice;
    
            m_vertex = new fVertex[(m_size.m_row+1) * (m_size.m_col+1)];
            m_indice = new uiIndice[m_size.m_row * (m_size.m_col+1)];
            (*FuncIndice)(m_indice, m_size);
            m_Oldsize.m_row = m_size.m_row;
            m_Oldsize.m_col = m_size.m_col;
        }
    
        (*FuncVertex)(m_vertex, m_size, m_factor, m_dvalue);
    
        SetTexture();
    
        glInterleavedArrays(GL_T2F_N3F_V3F, 0, m_vertex);
    
        glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
        glEnable(GL_COLOR_MATERIAL);
        glMatrixMode(GL_MODELVIEW);
        glTranslatef(m_x, m_y, m_z);
        glScalef(m_sx, m_sy, m_sz);
        glRotatef(m_rx, 1.0, 0.0, 0.0);
        glRotatef(m_ry, 0.0, 1.0, 0.0);
        glRotatef(m_rz, 0.0, 0.0, 1.0);
    
        for(i=0; i< m_size.m_row; i++)
        {
            k = i*(m_size.m_col+1);
            glDrawElements(GL_TRIANGLE_STRIP, 2*(m_size.m_col+1), GL_UNSIGNED_INT, &m_indice[k]);
        }
    
        glRotatef((float)(-1.0 * m_rz), 0.0, 0.0, 1.0);
        glRotatef((float)(-1.0 * m_ry), 0.0, 1.0, 0.0);
        glRotatef((float)(-1.0 * m_rx), 1.0, 0.0, 0.0);
        glScalef((float)(1.0f/m_sx), (float)(1.0f/m_sy), (float)(1.0f/m_sz));
        glTranslatef((float)(-1.0 * m_x), (float)(-1.0 * m_y), (float)(-1.0 * m_z));
    
    }
    
    
    
  3. Texture
    By the way of calling glEnable(GL_TEXTURE_2D), glTexImage2D(.........) and glInterleavedArrays(.........), the texture map can be realized.

  4. Fogs
    The fogs in rendering is implemented by the functions of glFog and glEnable(GL_FOG).

  5. Function pointer
    In this code, there is only one universal geometry object class. In this class, there is a pointer of geometry data calculation function. Signing different 3D geometry data generating function to this function pointer can create different geometry object.

  6. About triggering setting dialogbox from Windows properties dialog box.
    This sample gives a practical method to solve the problem of instancing the setting dialogbox. The key point is that the message for clicking setting button in Windows system properties dialogbox in Win95 is different from in NT. In Win95, command line __argv[1] for clicking setting dialogbox is "/c", but in NT, is "/c XXXXXX", XXXXXX is a number, may be the system dialogbox window handle or other window handle (I am not sure). So parsing the __argv[1] should be in single character not string. This part of code is shown following:
    
    
    
    BOOL CGlsaverApp::InitInstance()
    {
        // Standard initialization
        // If you are not using these features and wish to reduce the size
        //  of your final executable, you should remove from the following
        //  the specific initialization routines you do not need.
    
        Enable3dControls();
    
        enmCMDline cmdLine;
    
        cmdLine = getCMDline(__argv[1]);
    
    
        if (__argc == 1 || getCMDline(__argv[1]) == CMD_SETTING)
             DoSaverSetting();
        else if(getCMDline(__argv[1]) == CMD_PREVIEW)
        {
             DoSaverPreview();
             return TRUE;
        }
        else if(getCMDline(__argv[1]) == CMD_SAVER)
        {
             DoScreenSaver();
             return TRUE;
        }
    
        // Nothing happened, return FALSE so that we exit the
        //  application, rather than start the application's message pump.
        return FALSE;
    
    }
    
    enmCMDline CGlsaverApp::getCMDline(LPTSTR pszCmd)
    {
        if (pszCmd[0] == _T('-') || pszCmd[0] == _T('/'))
             pszCmd++;
    
        LPTSTR  pszChar = pszCmd;
    
        switch(*pszChar)
        {
            case _T('c'):
                  return CMD_SETTING;
            case _T('C'):
                  return CMD_SETTING;
            case _T('p'):
                  return CMD_PREVIEW;
            case _T('P'):
                  return CMD_PREVIEW;
            case _T('s'):
                  return CMD_SAVER;
            case _T('S'):
                  return CMD_SAVER;
            default:
                  return CMD_NONE;
        }
    }

Download source - 48KB

Date Posted: 03/17/99



Comments

  • I have a question.

    Posted by Legacy on 09/23/2002 12:00am

    Originally posted by: Hleg

    I have Window XP. Can I use OpenGL with XP? If yes, please show me step by step as to how to install and use it.

    Thank you very much in advance.

    • How to get font outline data with OpenGL

      Posted by SkyVistor on 06/02/2005 09:15pm

      We can get font data with wglUseFontOutlines (.....,agmf)function.
      but how to get real numerical data of font outline(i.e. (X,Y)data of outline) ??

      Reply
    Reply
  • The Preview and setup command aren't the same on win 95/98

    Posted by Legacy on 09/13/2000 12:00am

    Originally posted by: Fabio Ferretti

    Pay attention the "__argv[1]" isn't the same on windows 95/98.
    I don't remember exacly the command but if i remember good :

    preview : p,P,l,L

    full : s,S or nothing

    config : c,C


    Fabio
    http:\\ferretti.homepage.com

    Reply
  • Doesn't run with NT

    Posted by Legacy on 03/25/1999 12:00am

    Originally posted by: Carl Letourneau

    I get an application error (the memory couldn't be written). I have Windows NT 4.0 Server SP4 in english. Also I get this link error when I tried to compile the project :
    "LINK : warning LNK4075: ignoring /EDITANDCONTINUE due to /INCREMENTAL:NO specification". I am using VC++ 6.0. Do I have to update my video card drivers for supporting OpenGL 1.1? I have an ATI Rage 128.

    Reply
  • GLSaver

    Posted by Legacy on 03/17/1999 12:00am

    Originally posted by: Andrew Bryan


    I like it. You may want to increase the speed of the animation by changing the rendered screen size. The MS savers use a command 'ChangeDisplaySettings' (i think that is the cmd) to dynamically resize the screen to a lesser size. This improves the speed quite a bit. I am 1280x1024 and it appears kinda slow even with the fastest setting selected.

    Otherwise it is really nice work.


    Andrew

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 20, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds