Click here to Skip to main content
15,886,639 members
Articles / Desktop Programming / WPF

OpenGL for Both Native and .NET Environment

Rate me:
Please Sign up or sign in to vote.
4.92/5 (12 votes)
7 Jan 2013CPOL3 min read 36.2K   2.3K   50  
This article shows how you can bring OpenGL to both native and .NET environment.
////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002-2013 Computations & Graphics, Inc. 
// 
// All rights reserved.
//
// Author: Junlin Xu
//
//////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"

#include "gl/gl.h"
#include "gl/glu.h"
#include "gl/glaux.h"
#include "OpenGraph.h"
#include "Drawable.h"

#include <tchar.h>
#include <cmath>
#include <climits>
#include <algorithm>
#include <iterator>
#include <limits>
#include "DrawHelper.h"
#include "resource.h"
#include <atlimage.h>
#include "RubberBandTracker.h"
#include "DrawManager.h"
#include "MathHelper.h"

using namespace std;

extern HMODULE ghModule;
#define USE_DISPLAY_LIST 1;


namespace NSOpenGraphLib
{
const double gfZoomLimit = FLT_MAX;
const double gInitialZoom = 1.8;
const int gCursorSize = 10 / 2;


COpenGraph::COpenGraph(void)
{
    m_nCx = 0;
    m_nCy = 0;

    m_fTx = 0;
    m_fTy = 0;
    m_fRx = 0;
    m_fRy = 0;
    m_fRz = 0;
    m_fZoom = 1.0;
    m_fMax = 0.0;
    m_nMode = modeNONE;
    m_bShowAxes = true;

    m_hSelectCursor = ::LoadCursor(ghModule, MAKEINTRESOURCE(IDC_CURSOR_SELECT));
    m_hZoomCursor = ::LoadCursor(ghModule, MAKEINTRESOURCE(IDC_CURSOR_ZOOM));
    m_hPanCursor = ::LoadCursor(ghModule, MAKEINTRESOURCE(IDC_CURSOR_PAN));
    m_hRotateCursor = ::LoadCursor(ghModule, MAKEINTRESOURCE(IDC_CURSOR_ROTATE));
    m_hQueryCursor = ::LoadCursor(ghModule, MAKEINTRESOURCE(IDC_CURSOR_QUERY));

    m_pRubberBandTracker = new CRubberBandTracker();

    m_pDrawManager = new CDrawManager();
    m_bDirty = false;
}


COpenGraph::~COpenGraph(void)
{
    delete m_pRubberBandTracker;
    delete m_pDrawManager;
    ::DeleteObject(m_hSelectCursor);
    ::DeleteObject(m_hZoomCursor);
    ::DeleteObject(m_hPanCursor);
    ::DeleteObject(m_hRotateCursor);
    ::DeleteObject(m_hQueryCursor);

    DeleteObject(m_hSelectCursor);

    HDC hDC = GetDC(m_hGLWnd);
    wglMakeCurrent(hDC, m_hRC);

    DestroyRC(m_hRC);

}

void COpenGraph::ShowAxes(bool bShow)
{
    m_bShowAxes = bShow;
}

CIdentity COpenGraph::AddText(int id, int nFontId, CPointf pt, LPCTSTR text, COLORREF color,COLORREF colorSelected, int nAlignment, int nStatus)
{
    m_bDirty = true;
    return m_pDrawManager->AddText(id, nFontId, pt, text, color, colorSelected,nAlignment, nStatus);
}

int COpenGraph::AddFont(const TCHAR *typeface, int height, int weight, DWORD italic)
{
    // jxu: when adding font, we must have the opengl context ready
    HDC hDC = GetDC(m_hGLWnd);
    wglMakeCurrent(hDC, m_hRC);
    CGLFont2d* pFont2d = Font2dCreate(wglGetCurrentDC(), typeface, height, weight, italic);
    return m_pDrawManager->AddFont(pFont2d);
}

bool COpenGraph::Initialize(HWND hWnd)
{
    m_hGLWnd = hWnd;
    HDC hDC = GetDC(hWnd);

    if ( InitializePixelFormat(hDC) == false || CreateRC(m_hRC, hDC) == false )
    {
        return false;
    }
    AddFont(gstrArial, 16, 0, 0);   // built-in font
    

#ifdef USE_DISPLAY_LIST
    int nBase = glGenLists(END_LIST);	// generate display lists
    for(int i = nBase; i < nBase + END_LIST; i++)
    {
        m_nDisplayList[i-nBase] = i;
    }
#endif

    return true;
}

bool COpenGraph::InitializePixelFormat(HDC hDC)
{
    
    // define default desired video mode (pixel format)
    PIXELFORMATDESCRIPTOR pixelDesc;

    pixelDesc.nSize				= sizeof(PIXELFORMATDESCRIPTOR);
    pixelDesc.nVersion			= 1;
    pixelDesc.dwFlags	=		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE;  
    pixelDesc.iPixelType		= PFD_TYPE_RGBA;
    pixelDesc.cColorBits		= 32;	// with transparency support
    //pixelDesc.cColorBits		= 24;	// without transparency support
    pixelDesc.cRedBits			= 8;
    pixelDesc.cRedShift			= 16;
    pixelDesc.cGreenBits		= 8;
    pixelDesc.cGreenShift		= 8;
    pixelDesc.cBlueBits			= 8;
    pixelDesc.cBlueShift		= 0;
    pixelDesc.cAlphaBits		= 0;
    pixelDesc.cAlphaShift		= 0;
    pixelDesc.cAccumBits		= 64;	
    pixelDesc.cAccumRedBits		= 16;
    pixelDesc.cAccumGreenBits	= 16;
    pixelDesc.cAccumBlueBits	= 16;
    pixelDesc.cAccumAlphaBits	= 0;
    pixelDesc.cDepthBits		= 32;
    pixelDesc.cStencilBits		= 8;
    pixelDesc.cAuxBuffers		= 0;
    pixelDesc.iLayerType		= PFD_MAIN_PLANE;
    pixelDesc.bReserved			= 0;
    pixelDesc.dwLayerMask		= 0;
    pixelDesc.dwVisibleMask		= 0;
    pixelDesc.dwDamageMask		= 0;

    int nPixelIndex = ChoosePixelFormat( hDC, &pixelDesc);

    //nPixelIndex = 8;	// jxu: force the program to use ICD implementation
    //nPixelIndex = 22;	// jxu: force the program to use generic implementation
    ::DescribePixelFormat(hDC, nPixelIndex, pixelDesc.nSize, &pixelDesc);

    if (SetPixelFormat( hDC, nPixelIndex, &pixelDesc)==FALSE)
    {
        return false;
    }

    return true;
}

bool COpenGraph::CreateRC(HGLRC& hRC, HDC hDC)
{
    if ( (hRC = wglCreateContext(hDC)) == NULL ||
        wglMakeCurrent(hDC, hRC) == FALSE)
    {
        return false;
    }

    return true;
}

void COpenGraph::DestroyRC(HGLRC& hRC) 
{
    wglMakeCurrent(NULL, NULL) ; 
    if (hRC) 
    {
        wglDeleteContext(hRC) ;
        hRC = NULL ;
    }		

}

void COpenGraph::SetWindowSize(int cx, int cy) 
{
    if(m_nCx != cx || m_nCy != cy) {
        m_nCx = cx;
        m_nCy = cy;
        Render();
    }
}

void COpenGraph::ForceRender()
{
    m_bDirty = false;
    Render();
}

void COpenGraph::Render()
{
    try
    {
        OutputDebugString(_T("... COpenGraph::Render() .... "));

#ifdef USE_DISPLAY_LIST
        if(m_bDirty)
        {
            CreateLists();
        }
#endif

        HDC hDC = GetDC(m_hGLWnd);
        StartModel(hDC);
        CheckGLError();		// error checking
      

        GLfloat color_gl[3] = {0, 0, 0};
        glClearColor(color_gl[0], color_gl[1], color_gl[2], 0);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        if(m_bShowAxes)
        {
            DrawAxisCube();
        }

        SetupMatrix();  // 3D coordinates
        glDisable(GL_LIGHTING);
        DrawNodes();
        DrawLines();

        glEnable(GL_LIGHTING);
        DrawTriangles();
        DrawQuads();

        glDisable(GL_DEPTH_TEST);	
        glDisable(GL_LIGHTING);
        DrawTexts();

        SetupWindowMatrix();
        DebugDraw();
        glEnable(GL_DEPTH_TEST);	

        CheckGLError();		// error checking
        SwapBuffers(hDC);
        wglMakeCurrent(NULL, NULL) ;
        ::ReleaseDC (m_hGLWnd, hDC) ; 

    }	// end of: try
    catch(...){
        OutputDebugString(_T("Exception in COpenGraph::render"));
    }

}


void COpenGraph::StartModel(HDC hDC)
{
    wglMakeCurrent(hDC, m_hRC);

    // Anti-alias
    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glLineWidth(1.);

    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);	// hidden line removal

    // light setup
    GLfloat lmodel_ambient[] = {1.0, 1.0, 1.0, 1.0};
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);	// global ambient
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);	// two side model

    glCullFace( GL_BACK );
}	


void COpenGraph::SetupMatrix()
{
    // projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    double fSize = 2.0;
    if(m_fMax > 0) {
        fSize = m_fMax;
    }
    double fAspect = (double)m_nCy / (double)m_nCx;
    double fDepth = fSize * m_fZoom * 100.0;
    double fMaxZ = 2.0;
    fDepth = max(fDepth,  fMaxZ * m_fZoom * 2);

    m_fPixel2Log = 1.0;
    // orthogonal projection
    if(m_nCx <= m_nCy) {	
        glOrtho(-fSize, fSize, -fSize * fAspect, fSize * fAspect, -fDepth, fDepth);
        m_fPixel2Log = fSize / (m_nCx + 2);
    }
    else {
        glOrtho(-fSize / fAspect, fSize / fAspect, -fSize, fSize, -fDepth, fDepth);
        m_fPixel2Log = fSize / (m_nCy + 2);
    } 
    glViewport(-1, -1, m_nCx + 2, m_nCy + 2);	// m_viewport transformation


    // model view matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();


    glTranslated(m_fTx * fSize, m_fTy * fSize, 0);
    glScaled( m_fZoom, m_fZoom, m_fZoom );
    glRotated( m_fRx, 1.0, 0.0, 0.0 );
    glRotated( m_fRy, 0.0, 1.0, 0.0 );
    glRotated( m_fRz, 0.0, 0.0, 1.0 );

    glGetIntegerv(GL_VIEWPORT, m_viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, m_mvmatrix);
    glGetDoublev(GL_PROJECTION_MATRIX, m_projmatrix);


}	


void COpenGraph::CheckGLError()
{
    int nError = glGetError();
    switch (nError)
    {
    case GL_NO_ERROR:
        
        break;
    case GL_INVALID_ENUM:
        OutputDebugString(_T("GL_INVALID_ENUM"));
        break;
    case GL_INVALID_VALUE:
        OutputDebugString(_T("GL_INVALID_VALUE"));
        break;
    case GL_INVALID_OPERATION:
        OutputDebugString(_T("GL_INVALID_OPERATION"));
        break;
    case GL_STACK_OVERFLOW:
        OutputDebugString(_T("GL_STACK_OVERFLOW"));
        break;
    case GL_STACK_UNDERFLOW:
        OutputDebugString(_T("GL_STACK_UNDERFLOW"));
        break;
    case GL_OUT_OF_MEMORY:
        OutputDebugString(_T("GL_OUT_OF_MEMORY"));
        break;
    }

}


bool COpenGraph::TrackRect(HWND hWnd, POINT point)
{
    HDC hDC = GetDC(hWnd);
    m_pRubberBandTracker->SetContext(hDC, m_hRC);	// make sure we are not drawing rubber-band here
    return m_pRubberBandTracker->TrackRubberBand(m_hGLWnd, point, TRUE) == TRUE;
}

RECT COpenGraph::GetTrackRect()const
{
    return m_pRubberBandTracker->GetTrackRect();
}

BOOL COpenGraph::OnLButtonDown(RECT& rect, UINT nFlags, POINT point)
{
    HDC hDC = GetDC(m_hGLWnd);
    RECT rectClient;
    ::GetClientRect(m_hGLWnd, &rectClient);

    BOOL bReturn = FALSE;
    if(m_nMode == modeTRACK)
    {
        m_pRubberBandTracker->SetContext(hDC, m_hRC);	// make sure we are not drawing rubber-band here
        bReturn = m_pRubberBandTracker->TrackRubberBand(m_hGLWnd, point, TRUE);
        if(bReturn)
        {
            rect = GetTrackRect();
        }
    }
    else if(m_nMode == modeROTATE)	
    {
        m_ptOld = point;
    }	

    return bReturn;
}

void COpenGraph::OnMouseMove(UINT nFlags, POINT point) 
{
    if( nFlags & MK_LBUTTON)
    {
        if(m_nMode == modeROTATE)
        {
            m_fRy += 0.5f * (point.x-m_ptOld.x);
            m_fRx += 0.5f * (point.y-m_ptOld.y);
            m_ptOld = point;
            Render();
        }
    }

}


void COpenGraph::SetMode(int mode)
{
    m_nMode = mode;
    OnSetCursor();
}

HCURSOR COpenGraph::GetModeCursor()
{
    if(m_nMode == modeTRACK)
    {
        return (m_hSelectCursor);
    }
    else if(m_nMode == modeROTATE)
    {
        return (m_hRotateCursor);
    }
    else
    {   
        return (LoadCursor(0, IDC_ARROW));
    }
}

void COpenGraph::OnSetCursor()
{
    SetCursor(GetModeCursor());
}

void COpenGraph::DrawAxisCube()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glPushMatrix();
    double fSize = 1.0;
    double fAspect = (double)m_nCy / (double)m_nCx;
    // orthographic projection
    if(m_nCx <= m_nCy) {
        glOrtho(0, fSize, 0, fSize * fAspect, -fSize, fSize);
    }
    else {
        glOrtho(0, fSize / fAspect, 0, fSize, -fSize, fSize);
    } 
    glViewport(-1, -1, m_nCx + 2, m_nCy + 2);

    // MODELVIEW matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    double fTemp = min(m_nCx, m_nCy);
    glPushMatrix();
    // model view transformation
    //glTranslated(50. / fTemp , 50. / fTemp, 0);
    glTranslated(60. / fTemp , 60. / fTemp, 0);
    glRotated( m_fRx, 1.0, 0.0, 0.0 );
    glRotated( m_fRy, 0.0, 1.0, 0.0 );
    glRotated( m_fRz, 0.0, 0.0, 1.0 );
    CGLFont2d* pFont2d = m_pDrawManager->GetFont(0);    // built-in font
    CDrawHelper::DrawAxisCube(12. / fTemp, pFont2d);
    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

}

void COpenGraph::DrawNodes()
{
#ifdef USE_DISPLAY_LIST
     glCallList(m_nDisplayList[NODE_LIST]);   
#else
    const vector<CNodeBatch>& vBatchNodes = m_pDrawManager->GetNodeBatches();
    CDrawHelper::DrawNodes(vBatchNodes);
#endif
}

void COpenGraph::DrawLines()
{
#ifdef USE_DISPLAY_LIST
    glCallList(m_nDisplayList[LINE_LIST]);   
#else
    const vector<CLineBatch>& vBatchLines = m_pDrawManager->GetLineBatches();
    CDrawHelper::DrawLines(vBatchLines);
#endif
}

void COpenGraph::DrawTriangles()
{
#ifdef USE_DISPLAY_LIST
    glCallList(m_nDisplayList[TRIANGLE_LIST]);   
#else
    const vector<CTriangleBatch>& vBatchTriangles = m_pDrawManager->GetTriangleBatches();
    CDrawHelper::DrawTriangles(vBatchTriangles);
#endif
}

void COpenGraph::DrawQuads()
{
#ifdef USE_DISPLAY_LIST
    glCallList(m_nDisplayList[QUAD_LIST]);   
#else
    const vector<CQuadBatch>& vBatchQuads = m_pDrawManager->GetQuadBatches();
    CDrawHelper::DrawQuads(vBatchQuads);
#endif
}

void DrawTextsHelper(CDrawManager* pDrawManager, const vector<CText>& vText)
{
    for(int i = 0; i < (int)vText.size(); i++)
    {
        const CText& text = vText[i];
        CGLFont2d* pFont2d = pDrawManager->GetFont(text.nFontId);
        GLdouble color[3];
        if(text.nStatus & STATUS_SELECTED)
        {
            CDrawHelper::ConvertColors(color, text.colorSelected);
        }
        else
        {
            CDrawHelper::ConvertColors(color, text.color);
        }
        glColor3dv(color);
        Font2dPrintf(pFont2d, text.nAlignment, text.pt, text.strText);
    }
}

void COpenGraph::DrawTexts()
{
#ifdef USE_DISPLAY_LIST
    glCallList(m_nDisplayList[TEXT_LIST]);   
#else
    const vector<CText>& vText = m_pDrawManager->GetTexts();
    DrawTextsHelper(m_pDrawManager, vText);
#endif
}

void COpenGraph::DebugDraw()
{
    TCHAR szMsg[1234];
    _stprintf(szMsg, _T("Rx = %.2f, Ry = %.2f, Rz = %.2f"), m_fRx, m_fRy, m_fRz);
    CPointf ptBase(m_nCx - 10, m_nCy - 10, 0);
    const GLdouble color_x[3] = {1., 1.0, .0};
    glColor3dv(color_x);
    CGLFont2d* pFont2d = m_pDrawManager->GetFont(0);    // built-in font
    Font2dPrintf(pFont2d, ALIGN_TOP|ALIGN_RIGHT, ptBase, szMsg);

    CPointf ptBase1(10, m_nCy - 10, 0);
    CPointf ptBase2(10, m_nCy - 25, 0);
    Font2dPrintf(pFont2d, ALIGN_TOP|ALIGN_LEFT, ptBase1, _T("OpenGraph Library by Junlin Xu, Jan 2013"));
    Font2dPrintf(pFont2d, ALIGN_TOP|ALIGN_LEFT, ptBase2, _T("Computations & Graphics, Inc. (www.cg-inc.com)"));

}

void COpenGraph::Rotate(double fRx, double fRy, double fRz)
{
    m_fRx = fRx;
    m_fRy = fRy;
    m_fRz = fRz;
    Render();
}

void COpenGraph::GetTransformParameters(double& fTx, double& fTy, double& fRx, double& fRy, double& fRz, double& fZoom)
{
    fTx = m_fTx;
    fTy = m_fTy;
    fRx = m_fRx;
    fRy = m_fRy;
    fRz = m_fRz;
    fZoom = m_fZoom;
}

void COpenGraph::Clear()
{
    m_pDrawManager->Clear();
    m_bDirty = true;
}

CIdentity COpenGraph::AddNode(int id,CPointf pt, int nSize, COLORREF color,COLORREF colorSelected, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    return m_pDrawManager->AddNode(id,pt, nSize, color,colorSelected, nStatus, tag, userData );
}

void COpenGraph::AddNodes(CIdentity* pIdentity,int* pId,CPointf* pPt, int nNodes, int nSize, COLORREF color,COLORREF colorSelected, int nStatus, LPCTSTR tag, LPCTSTR userData)
{
    m_bDirty = true;
    return m_pDrawManager->AddNodes(pIdentity, pId, pPt, nNodes, nSize, color, colorSelected, nStatus, tag, userData);
}

CIdentity COpenGraph::AddLine(int id,CPointf pt1,CPointf pt2, int nThickness, COLORREF color,COLORREF colorSelected, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    return m_pDrawManager->AddLine(id, pt1, pt2, nThickness, color, colorSelected, nStatus, tag, userData);

}

void COpenGraph::AddLines(CIdentity* pIdentity, int* pId,CPointf* pPt1,CPointf* pPt2, int nLines, int nThickness, COLORREF color,COLORREF colorSelected, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    return m_pDrawManager->AddLines(pIdentity, pId, pPt1, pPt2, nLines, nThickness, color, colorSelected, nStatus, tag, userData);
}

CIdentity COpenGraph::AddTriangle(int id,CPointf pt1,CPointf pt2,CPointf pt3, COLORREF color,COLORREF colorSelected, float alpha, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    return m_pDrawManager->AddTriangle(id, pt1, pt2, pt3, color, colorSelected, alpha, nStatus, tag, userData);
}

void COpenGraph::AddTriangles(CIdentity* pIdentity, int* pId,CPointf* pPt1,CPointf* pPt2, CPointf* pPt3, int nTriangles, COLORREF color,COLORREF colorSelected,float alpha, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    m_pDrawManager->AddTriangles(pIdentity, pId, pPt1, pPt2, pPt3, nTriangles, color, colorSelected, alpha, nStatus, tag, userData);
}

CIdentity COpenGraph::AddQuad(int id,CPointf pt1,CPointf pt2,CPointf pt3,CPointf pt4, COLORREF color,COLORREF colorSelected, float alpha, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    return m_pDrawManager->AddQuad(id, pt1, pt2, pt3, pt4, color, colorSelected, alpha, nStatus, tag, userData);
}

void COpenGraph::AddQuads(CIdentity* pIdentity, int* pId,CPointf* pPt1,CPointf* pPt2, CPointf* pPt3,CPointf* pPt4, int nQuads, COLORREF color,COLORREF colorSelected,float alpha, int nStatus, LPCTSTR tag, LPCTSTR userData )
{
    m_bDirty = true;
    m_pDrawManager->AddQuads(pIdentity, pId, pPt1, pPt2, pPt3, pPt4, nQuads, color, colorSelected, alpha, nStatus, tag, userData);
}

void COpenGraph::FreeMemory(void * p)
{
    delete p;
}

void COpenGraph::FreeMemoryArray(void * p)
{
    delete []p;
}

void COpenGraph::CreateLists()
{
    OutputDebugString(_T("CreateLists()"));
    HDC hDC = GetDC(m_hGLWnd);
    wglMakeCurrent(hDC, m_hRC);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    {
        CGLNewListHelper helper(m_nDisplayList[NODE_LIST]);
        const vector<CNodeBatch>& vBatchNodes = m_pDrawManager->GetNodeBatches();
        CDrawHelper::DrawNodes(vBatchNodes);
    }

    {
        CGLNewListHelper helper(m_nDisplayList[LINE_LIST]);
        const vector<CLineBatch>& vBatchLines = m_pDrawManager->GetLineBatches();
        CDrawHelper::DrawLines(vBatchLines);
    }

    {
        CGLNewListHelper helper(m_nDisplayList[TRIANGLE_LIST]);
        const vector<CTriangleBatch>& vBatchTriangles = m_pDrawManager->GetTriangleBatches();
        CDrawHelper::DrawTriangles(vBatchTriangles);
    }

    {
        CGLNewListHelper helper(m_nDisplayList[QUAD_LIST]);
        const vector<CQuadBatch>& vBatchQuads = m_pDrawManager->GetQuadBatches();
        CDrawHelper::DrawQuads(vBatchQuads);
    }

    {
        CGLNewListHelper helper(m_nDisplayList[TEXT_LIST]);
        DrawTextsHelper(m_pDrawManager, m_pDrawManager->GetTexts());
    }

    m_bDirty = false;
    wglMakeCurrent(NULL, NULL) ;
}

void COpenGraph::SelectAll()
{
    m_pDrawManager->SelectAll();
    m_bDirty = true;
}

void COpenGraph::UnSelectAll()
{
    m_pDrawManager->UnSelectAll();
    m_bDirty = true;
}

void COpenGraph::ReverseSelectAll()
{
    m_pDrawManager->ReverseSelectAll();
    m_bDirty = true;
}

void COpenGraph::SetupWindowMatrix()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    double fSize = min(m_nCx, m_nCy);
    double fAspect = (double)m_nCy / (double)m_nCx;
    // orthographic projection
    if(m_nCx <= m_nCy) {
        glOrtho(0, fSize, 0, fSize * fAspect, -fSize, fSize);
    }
    else {
        glOrtho(0, fSize / fAspect, 0, fSize, -fSize, fSize);
    } 
    glViewport(-1, -1, m_nCx + 2, m_nCy + 2);

    // MODELVIEW matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}	

}

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
President Computations & Graphics, Inc.
United States United States
Junlin Xu is the founder of Computations & Graphics, Inc. (http://www.cg-inc.com). He is the author of Real3D finite element package, SolverBlaze finite element SDK, OpenGraph Library (OpenGL-based visualization and charting SDK for native and .NET environment), and double128 SDK (quad precision floating point math for C++ and .NET).

Junlin has 20+ years software development experiences in various industries. He has skills in Windows desktop and web application development using C++, C++/CLI, C#, Qt, MFC, STL, OpenGL, GLSL, COM/COM+, WinForms, MS SQL, MySQL, ASP.NET and .NET Core, CSS, jQuery and jQuery UI, Autodesk Revit API, Inno Setup. He is also an expert in mathematical, CAD and algorithmic software development.

Comments and Discussions