Click here to Skip to main content
15,884,237 members
Articles / Multimedia / DirectX

A New Perspective on Viewing

Rate me:
Please Sign up or sign in to vote.
4.93/5 (44 votes)
6 Oct 2009CPOL16 min read 109.4K   2.6K   90  
Simple yet comprehensive viewing code for OpenGL and Direct3D.
// Gfx.h    - graphics interface
//
// Copyright (C) 2009 John Hilton
//
// Declares
//      IGfx            - the general graphics interface
//      CGfxOpenGL      - implements IGfx using OpenGL
//      CGfxDirect3D    - implements IGfx using Direct3D
//
// Also provides declarations for a simple object definition based on a
// list of DWORDs for specifying color and triangle strips.
//
// The IGfx property 'Hwnd' attaches a window to the IGfx derived object.
// To trigger a redraw used the Win32 Invalidate() call.
// The IGfx callback 'OnPaint' is called by IGfx's WM_PAINT handler.
//
// To change the size or the window use the Win32 MoveWindow() call.
//
// In the OnPaint callback first use IGfx::ConfigureView() then 
// transformation and rendering calls to render the scene.

#pragma once

// Declare a general graphics interface
template< typename T >
struct IGfx
{
    // types
    struct ICallbacks
    {
        virtual void OnPaint( IGfx<T>& Gfx ) = 0;
        virtual void OnFinalMessage( HWND hWnd ) = 0;
    };

    virtual HWND Hwnd() = 0;
    virtual void Attach( HWND hwnd ) = 0;   // NULL will detach

    virtual void ConfigureView( T ViewVolume[7], T ViewToWorld[4][3] ) = 0;
    virtual void Push() = 0;
    virtual void Pop() = 0;
    virtual void Rotate( T Angle, T Axis[3] ) = 0;
    virtual void Rotate( T Matrix[3][3] ) = 0;
    virtual void Translate( T x, T y, T z ) = 0;
    virtual void Scale( T factor ) = 0;
    virtual void Scale( T xyz[3] ) = 0;

    virtual void Render( DWORD* pItem, int length ) = 0;
};

template< typename T > class CGfxOpenGLImpl;

template< typename T >
class CGfxOpenGL
    : public IGfx<T>
{
    class CGfxOpenGLImpl<T>* m_pImpl;
public:
    // construction
    CGfxOpenGL(ICallbacks& Callbacks);
    ~CGfxOpenGL();

    virtual HWND Hwnd();
    virtual void Attach( HWND hwnd );

    virtual void ConfigureView( T ViewVolume[7], T ViewToWorld[4][3] );
    virtual void Push();
    virtual void Pop();
    virtual void Rotate( T Angle, T Axis[3] );
    virtual void Rotate( T Matrix[3][3] );
    virtual void Translate( T x, T y, T z );
    virtual void Scale( T factor );
    virtual void Scale( T xyz[3] );

    virtual void Render( DWORD* pItem, int length );
};
typedef CGfxOpenGL<float> CGfxOpenGLf;
typedef CGfxOpenGL<double> CGfxOpenGLd;

template< typename T > class CGfxDirect3DImpl;

template< typename T >
class CGfxDirect3D : public IGfx<T>
{
    CGfxDirect3DImpl<T>* m_pImpl;
public:
    CGfxDirect3D(typename IGfx<T>::ICallbacks& Callbacks);
    ~CGfxDirect3D();

    virtual HWND Hwnd();
    virtual void Attach( HWND hwnd );

    virtual void ConfigureView( T ViewVolume[7], T ViewToWorld[4][3] );
    virtual void Push();
    virtual void Pop();
    virtual void Rotate( T Angle, T Axis[3] );
    virtual void Rotate( T Matrix[3][3] );
    virtual void Translate( T x, T y, T z );
    virtual void Scale( T factor );
    virtual void Scale( T xyz[3] );

    virtual void Render( DWORD* pItem, int length );
};
typedef CGfxDirect3D<float> CGfxDirect3Df;
typedef CGfxDirect3D<double> CGfxDirect3Dd;

// Hopefully the compiler will perform f2dw at compile-time rather than run-time
inline DWORD f2dw(float f) { return *(DWORD*)&f; }

enum TGfxItem { gfxColor=(DWORD)0x81<<24, gfxTriangleStrip=(DWORD)0x82<<24, gfxForceDWORD=0x7fffffff };
#define GFXCOLOR(r,g,b) \
        (DWORD) (gfxColor | \
        ((DWORD)(min(abs((float)r),1.0f)*255)<<16) | \
        ((DWORD)(min(abs((float)g),1.0f)*255)<< 8) | \
         (DWORD)(min(abs((float)b),1.0f)*255))
#define GFXTRIANGLESTRIP(TriangleCount) \
        (DWORD) (gfxTriangleStrip | (TriangleCount & 0x00000fff))
#define GFXV(x,y,z) \
        f2dw((float)x), \
        f2dw((float)y), \
        f2dw((float)z)

// Although not used in the interfaces above provide TViewVolume
template< typename T > union TViewVolume {
    T v7[7];
    struct { float hw, hh, zn, zf, iez, tsx, tsy; };
};
typedef TViewVolume<float> TViewVolumef;
typedef TViewVolume<double> TViewVolumed;

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)


Written By
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

Comments and Discussions