Click here to Skip to main content
Click here to Skip to main content
Articles » Multimedia » DirectX » General » Downloads
 
Add your own
alternative version

A New Perspective on Viewing

, 6 Oct 2009 CPOL
Simple yet comprehensive viewing code for OpenGL and Direct3D.
// GfxOpenGL.cpp
//
// Implements all the OpenGL graphics functionality for the "NewView" demo
// as declared in Gfx.h.
//
// Copyright (C) 2009 John Hilton
//
// Implements the CGfxOpenGL class which implements the IGfx interface for
// graphics transformations and drawing.
//
// CGfxOpenGL
//      (is a): IGfx      - general graphics interface
//      (has a) m_pImpl->   CGfxOpenGLImpl - helper class for CGfxDirect3D

#include "stdafx.h"
#include "wingdi.h"
#include "gl/gl.h"
#pragma comment( lib, "opengl32.lib" )
#include "Gfx.h"
#include "GfxSubclass.h"
#include "GeneralView.h"

template< typename T >
class CGfxOpenGLImpl
    : public CGfxSubclass<T>
{
public:
    typename IGfx<T>::ICallbacks*   m_pCallbacks;
    IGfx<T>*            m_pGfx;
    HDC                 m_hDC;
    HGLRC               m_hRC;

    CGfxOpenGLImpl(typename IGfx<T>::ICallbacks& Callbacks, IGfx<T>& Gfx)
        : m_pCallbacks(&Callbacks)
        , m_pGfx(&Gfx)
        , m_hRC(NULL)
    {
    }

    ~CGfxOpenGLImpl()
    {
        if (m_hWnd)
        {
            DestroyRC();
            UnsubclassWindow();
        }
    }

    virtual void /*CWindowImpl*/ OnFinalMessage( HWND hWnd )
    {
        m_pCallbacks->OnFinalMessage( hWnd ); // may delete this
    }

    void Attach( HWND hWnd )
    {
        if (!m_hWnd && hWnd)
        {
            // Create
            ATLVERIFY(SubclassWindow(hWnd));
            m_hDC = GetDC();
            ASSERT(m_hDC);
            CreateRC(m_hDC);
        }
        else if (m_hWnd && !hWnd)
        {
            // Destroy
            DestroyRC();
            ReleaseDC(m_hDC);
            m_hDC = NULL;
            UnsubclassWindow();
        }
        else if (m_hWnd)
        {
            // Change
            UnsubclassWindow();
            SubclassWindow( hWnd );
        }
    }

    // create the OpenGL rendering context
    void CreateRC( HDC hDC )
    {
        int nPixelFormat;

        static PIXELFORMATDESCRIPTOR pfd = {
                sizeof(PIXELFORMATDESCRIPTOR),
                1,                              // structure version
                PFD_DRAW_TO_WINDOW |
                PFD_SUPPORT_OPENGL |
                PFD_DOUBLEBUFFER,
                PFD_TYPE_RGBA,
                24,                             // 24 bit
                0,0,0,0,0,0,
                0,0,
                0,0,0,0,0,
                32,                             // depth buffer bits
                0,
                0,
                PFD_MAIN_PLANE,
                0,
                0,0,0 };

        // Choose and set the pixel format
        nPixelFormat = ChoosePixelFormat(hDC, &pfd);
        ATLVERIFY(SetPixelFormat(hDC, nPixelFormat, &pfd));

        // Create the rendering context, make it current, initialize and deselect it
        m_hRC = wglCreateContext(hDC);
        ATLVERIFY(wglMakeCurrent(hDC,m_hRC));
        ConfigureRC();
        wglMakeCurrent(NULL,NULL);

        // Ensure a non-palette mode is selected
        DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
        if(pfd.dwFlags & PFD_NEED_PALETTE)
        {
            MessageBox( _T("Cannot run with a palette graphics mode."), _T(__FILE__), MB_OK );
            exit(1);
        }
    }

    void DestroyRC()
    {
        if (m_hRC)
        {
            // Destroy the OpenGL rendering context
            wglDeleteContext(m_hRC);
            m_hRC = NULL;
        }
    }

    void ConfigureRC()
    {
        // Light values and coordinates
        GLfloat ambientLight[] = { 0.4f, 0.4f, 0.4f, 1.0f };
        GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
        GLfloat specular[]     = { 0.9f, 0.9f, 0.9f, 1.0f };
        GLfloat lightPos[]     = { -50.0f, 200.0f, 200.0f, 1.0f };
        GLfloat specref[]      = { 0.6f, 0.6f, 0.6f, 1.0f };

        glEnable(GL_DEPTH_TEST);    // Hidden surface removal

        // Enable lighting
        glEnable(GL_LIGHTING);

        // Setup light 0
        glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);
        glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
        glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
        glLightfv(GL_LIGHT0,GL_SPECULAR,specular);

        // Position and turn on the light
        glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
        glEnable(GL_LIGHT0);

        // Enable color tracking
        glEnable(GL_COLOR_MATERIAL);
        
        // Set Material properties to follow glColor values
        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

        // All materials hereafter have full specular reflectivity
        // with a moderate shine
        glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
        glMateriali(GL_FRONT,GL_SHININESS,64);

        // Trigger a redraw
        Invalidate();
    }

    void ClearBackground()
    {
        // background
        glClearColor( 20.0f/255, 20.0f/255, 100.0f/255, 1.0f );
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }

    LRESULT OnSize(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        nMsg; wParam; bHandled;

        int cx = LOWORD(lParam);
        int cy = HIWORD(lParam);

        if (!m_hWnd || !cy) return 0L;
        HDC hDC = GetDC();
        ASSERT(hDC);
        VERIFY(wglMakeCurrent( hDC, m_hRC ));
        glViewport( 0, 0, cx, cy );
        VERIFY(ReleaseDC(hDC));
        return 0L;
    }

    LRESULT OnPaint(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        nMsg; wParam; lParam; bHandled;

        BOOL bRet = wglMakeCurrent( m_hDC, m_hRC );
        ASSERT(bRet); bRet;
        ClearBackground();
        m_pCallbacks->OnPaint( *m_pGfx );
        glFlush();
        V(SwapBuffers( m_hDC ));
        V(wglMakeCurrent( NULL, NULL ));
        V(ValidateRect( NULL ));
        return 0L;
    }

    void Draw( DWORD* pItem, int length )
    {
        int count;
        while (length > 0)
            switch (*pItem & 0xff000000)
            {
            case gfxColor:
                glColor3f( ((*pItem>>16)&0xff)/255.0f,
                           ((*pItem>> 8)&0xff)/255.0f,
                           ((*pItem    )&0xff)/255.0f );
                pItem++;
                length--;
                break;
            case gfxTriangleStrip:
                count = *pItem & 0x00000fff;
                ASSERT(count);
                glDisable( GL_CULL_FACE );
                GLboolean cullface;
                glGetBooleanv( GL_CULL_FACE, &cullface );
                glBegin( GL_TRIANGLE_STRIP );
                for (int i=0; i<count+2; i++)
                    glVertex3f( *(GLfloat*) (pItem+1+3*i),
                                *(GLfloat*) (pItem+2+3*i),
                                *(GLfloat*) (pItem+3+3*i) );
                glEnd();
                pItem += 1+3*(count+2);
                length -= 1+3*(count+2);
                break;
            default:
                ASSERT(0);
                return;
            }
    }
};

#pragma region CGfxOpenGL

template< typename T >
CGfxOpenGL<T>::CGfxOpenGL(IGfx<T>::ICallbacks& Callbacks)
{
    m_pImpl = new CGfxOpenGLImpl<T>(Callbacks, *this);
    ASSERT( m_pImpl );
}

template< typename T >
CGfxOpenGL<T>::~CGfxOpenGL(void)
{
    if (m_pImpl) delete m_pImpl;
}

template< typename T >
HWND CGfxOpenGL<T>::Hwnd()
{
    return m_pImpl ? m_pImpl->m_hWnd : NULL;
}

template< typename T >
void CGfxOpenGL<T>::Attach( HWND hWnd )
{
    m_pImpl->Attach( hWnd );
}

template< typename T >
void CGfxOpenGL<T>::ConfigureView( T ViewVolume[7], T ViewToWorld[4][3] )
{
    ConfigureView_OpenGL( ViewVolume, ViewToWorld );
}

template< typename T >
void CGfxOpenGL<T>::Push()
{
    glMatrixMode( GL_MODELVIEW );
    ::glPushMatrix();
}

template< typename T >
void CGfxOpenGL<T>::Pop()
{
    glMatrixMode( GL_MODELVIEW );
    ::glPopMatrix();
}

template< typename T >
void CGfxOpenGL<T>::Rotate( T Angle, T Axis[3] )
{
    if (sizeof(T) == sizeof(float))
        glRotatef( Angle, Axis[0], Axis[1], Axis[2] );
    else
        glRotated( Angle, Axis[0], Axis[1], Axis[2] );
}

template< typename T >
void CGfxOpenGL<T>::Rotate( T Matrix[3][3] )
{
    if (sizeof(T) == sizeof(float))
    {
        GLfloat m[4][4] = {
            { Matrix[0][0], Matrix[0][1], Matrix[0][2], 0 },
            { Matrix[1][0], Matrix[1][1], Matrix[1][2], 0 },
            { Matrix[2][0], Matrix[2][1], Matrix[2][2], 0 },
            {            0,            0,            0, 1 }
        };
        glMultMatrixf( m[0] );
    }
    else
    {
        GLdouble m[4][4] = {
            { Matrix[0][0], Matrix[0][1], Matrix[0][2], 0 },
            { Matrix[1][0], Matrix[1][1], Matrix[1][2], 0 },
            { Matrix[2][0], Matrix[2][1], Matrix[2][2], 0 },
            {            0,            0,            0, 1 }
        };
        glMultMatrixd( m[0] );
    }
}

template< typename T >
void CGfxOpenGL<T>::Translate( T x, T y, T z )
{
    if (sizeof(T) == sizeof(float))
        glTranslatef( x, y, z );
    else
        glTranslated( x, y, z );
}

template< typename T >
void CGfxOpenGL<T>::Scale( T factor )
{
    if (sizeof(T) == sizeof(float))
        glScalef( factor, factor, factor );
    else
        glScaled( factor, factor, factor );
}

template< typename T >
void CGfxOpenGL<T>::Scale( T xyz[3] )
{
    if (sizeof(T) == sizeof(float))
        glScalef( xyz[0], xyz[1], xyz[2] );
    else
        glScaled( xyz[0], xyz[1], xyz[2] );
}


template< typename T >
void CGfxOpenGL<T>::Render( DWORD* pItem, int length )
{
    m_pImpl->Draw( pItem, length );
}


// Instantiate the class
template CGfxOpenGL<float>;
#pragma endregion


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

John Hilton
Founder Spatial Freedom
Australia Australia
Software engineer, mechanical engineer, electronics engineer, inventor, manager, entrepreneur, husband, father, friend.
B.Sc. B.E.(Hons) M.Eng.Sc.
Some things I've done
- Invented the Spaceball(R)/1983 and Astroid(R)/2002 3D mice
- Patents: 3D mouse, data compression, acoustic transducer
- Wrote animation software in mid 1980s for TV commercials
- Wrote a basic CAD drawing program in 1980s
- Lived in Boston, Massachusetts for 11 years
- Architected and managed full custom ASIC chip
- Reviewed bionic eye technology for investment purposes
- Product development on CPR aid for heart attacks
- Developed an electronic sports whistle
- Was actually stranded on a deserted Pacific island
- Software: lots - embedded, device driver, applications
Some things I want to do
- Develop more cool hardware/software products
- Solve the 3D mouse software barrier to proliferate 3D mice
- Help bring 3D to the masses
- Help others

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 6 Oct 2009
Article Copyright 2009 by John Hilton
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid