⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mgcoglrenderer.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#include "MgcOglRenderer.h"
#include "MgcPolyline.h"
#include "MgcTriMesh.h"

MgcImplementRTTI(MgcOglRenderer,MgcRenderer);
MgcImplementStream(MgcOglRenderer);

//----------------------------------------------------------------------------
MgcOglRenderer::MgcOglRenderer (HWND hWnd, int iWidth, int iHeight)
    :
    MgcRenderer(iWidth,iHeight)
{
    CreateRenderer(hWnd);
}
//----------------------------------------------------------------------------
MgcOglRenderer::MgcOglRenderer ()
{
}
//----------------------------------------------------------------------------
MgcOglRenderer::~MgcOglRenderer ()
{
    if ( m_hWindowRC )
        wglDeleteContext(m_hWindowRC);

    if ( m_hWindowDC )
        ReleaseDC(m_hWnd,m_hWindowDC);
}
//----------------------------------------------------------------------------
void MgcOglRenderer::CreateRenderer (HWND hWnd)
{
    assert( m_iWidth > 0 && m_iHeight > 0 );

    m_hWnd = hWnd;
    m_hWindowDC = GetDC(m_hWnd);

    // select format for drawing surface
    PIXELFORMATDESCRIPTOR kPFD;
    memset(&kPFD,0,sizeof(PIXELFORMATDESCRIPTOR));
    kPFD.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    kPFD.nVersion = 1;
    kPFD.dwFlags =
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_GENERIC_ACCELERATED |
        PFD_DOUBLEBUFFER;
    kPFD.iPixelType = PFD_TYPE_RGBA;
    kPFD.cColorBits = 16;  // 16-bit colors for front/back buffers
    kPFD.cDepthBits = 16;  // 16-bit depth buffer
    
    // set the pixel format for the rendering context
    int iPixelFormat = ChoosePixelFormat(m_hWindowDC,&kPFD);
    if ( iPixelFormat == 0 )
    {
        m_bConstructed = false;
        return;
    }
    BOOL bSuccess = SetPixelFormat(m_hWindowDC,iPixelFormat,&kPFD);
    if ( !bSuccess )
    {
        m_bConstructed = false;
        return;
    }

    // create an OpenGL context
    m_hWindowRC = wglCreateContext(m_hWindowDC);
    if ( !m_hWindowRC )
    {
        m_bConstructed = false;
        return;
    }

    bSuccess = wglMakeCurrent(m_hWindowDC,m_hWindowRC);
    if ( !bSuccess )
    {
        m_bConstructed = false;
        return;
    }

    m_bConstructed = true;

    GetDriverInformation();
    InitializeState();
}
//----------------------------------------------------------------------------
void MgcOglRenderer::GetDriverInformation ()
{
    // get OpenGL extensions
    char* acVendor = (char*) glGetString(GL_VENDOR);
    char* acRenderer = (char*) glGetString(GL_RENDERER);
    char* acVersion = (char*) glGetString(GL_VERSION);
    char* acGluVersion = (char*) gluGetString(GLU_VERSION);

    char* acExtensions =
        new char[strlen((const char*)glGetString(GL_EXTENSIONS))+1];
    strcpy(acExtensions,(const char*)glGetString(GL_EXTENSIONS));

    // create message buffer (include space for prefixs and null terminator)
    int iMaxLength = strlen(acVendor);
    int iLength = strlen(acRenderer);
    if ( iLength > iMaxLength )
        iMaxLength = iLength;
    iLength = strlen(acVersion);
    if ( iLength > iMaxLength )
        iMaxLength = iLength;
    iLength = strlen(acGluVersion);
    if ( iLength > iMaxLength )
        iMaxLength = iLength;
    iLength = strlen(acExtensions);
    if ( iLength > iMaxLength )
        iMaxLength = iLength;
    iMaxLength += 16;

    char* acMessage = new char[iMaxLength];

    sprintf(acMessage,"Vendor: %s\n",acVendor);
    OutputDebugString(acMessage);

    sprintf(acMessage,"Renderer: %s\n",acRenderer);
    OutputDebugString(acMessage);

    sprintf(acMessage,"Version: %s\n",acVersion);
    OutputDebugString(acMessage);

    sprintf(acMessage,"GLU Version: %s\n",acGluVersion);
    OutputDebugString(acMessage);

    OutputDebugString("Extensions:\n");

    char* acToken = strtok(acExtensions," \t\r\n");
    while ( acToken )
    {
        sprintf(acMessage,"  %s\n",acToken);
        OutputDebugString(acMessage);
        acToken = strtok(0," \t\r\n");
    }

    delete[] acExtensions;
    delete[] acMessage;
}
//----------------------------------------------------------------------------
void MgcOglRenderer::SetBackgroundColor (const MgcColor& rkColor)
{
    MgcRenderer::SetBackgroundColor(rkColor);
    glClearColor(rkColor.r,rkColor.g,rkColor.b,1.0f);
}
//---------------------------------------------------------------------------
void MgcOglRenderer::ClearBackBuffer ()
{
    glDisable(GL_DITHER);
    glEnable(GL_SCISSOR_TEST);
    glScissor(0,0,m_iWidth,m_iHeight);
    glClear(GL_COLOR_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);
    glEnable(GL_DITHER);
}
//----------------------------------------------------------------------------
void MgcOglRenderer::DisplayBackBuffer ()
{
    glFlush();
    SwapBuffers(m_hWindowDC);
}
//----------------------------------------------------------------------------
void MgcOglRenderer::ClearZBuffer ()
{
    glDisable(GL_DITHER);
    glEnable(GL_SCISSOR_TEST);
    glScissor(0,0,m_iWidth,m_iHeight);
    glClear(GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);
    glEnable(GL_DITHER);
}
//----------------------------------------------------------------------------
void MgcOglRenderer::ClearBuffers ()
{
    glDisable(GL_DITHER);
    glEnable(GL_SCISSOR_TEST);
    glScissor(0,0,m_iWidth,m_iHeight);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);
    glEnable(GL_DITHER);
}
//----------------------------------------------------------------------------
void MgcOglRenderer::InitializeState ()
{
    MgcRenderer::InitializeState();

    // do back face culling (front faces are counterclockwise ordered)
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glFrontFace(GL_CCW);

    // vertices always exist
    glEnableClientState(GL_VERTEX_ARRAY);

    // no global ambient lighting
    GLfloat afBlack[4] = { 0.0, 0.0, 0.0, 1.0 };
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,afBlack);
}
//----------------------------------------------------------------------------
void MgcOglRenderer::Draw (const MgcTriMesh& rkMesh)
{
    // set world matrix
    const MgcMatrix3& rkRot = rkMesh.WorldRotate();
    const MgcVector3& rkTrn = rkMesh.WorldTranslate();
    MgcReal fScale = rkMesh.WorldScale();
    GLfloat afModelToWorld[16] =
    {
        fScale*rkRot[0][0], fScale*rkRot[1][0], fScale*rkRot[2][0], 0.0f,
        fScale*rkRot[0][1], fScale*rkRot[1][1], fScale*rkRot[2][1], 0.0f,
        fScale*rkRot[0][2], fScale*rkRot[1][2], fScale*rkRot[2][2], 0.0f,
        rkTrn.x,            rkTrn.y,            rkTrn.z,            1.0f
    };

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glMultMatrixf(afModelToWorld);

    // render the object
    GLfloat* afVertices = (GLfloat*) rkMesh.Vertices();
    glVertexPointer(3,GL_FLOAT,0,afVertices);

    GLfloat* afNormals = (GLfloat*) rkMesh.Normals();
    if ( afNormals )
    {
        glEnableClientState(GL_NORMAL_ARRAY);
        glNormalPointer(GL_FLOAT,0,afNormals);
    }
    else
    {
        glDisableClientState(GL_NORMAL_ARRAY);
    }

    GLfloat* afColors = (GLfloat*) rkMesh.Colors();
    if ( afColors )
    {
        glEnableClientState(GL_COLOR_ARRAY);
        glColorPointer(3,GL_FLOAT,0,afColors);
    }
    else
    {
        glDisableClientState(GL_COLOR_ARRAY);
    }

    GLfloat* afTextures = (GLfloat*) rkMesh.Textures();
    if ( afTextures )
    {
        glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
        glTexCoordPointer(2,GL_FLOAT,0,afTextures);
    }
    else
    {
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }

    glDrawElements(GL_TRIANGLES,3*rkMesh.GetTriangleQuantity(),
        GL_UNSIGNED_INT,rkMesh.Connectivity());

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}
//----------------------------------------------------------------------------
void MgcOglRenderer::Draw (const MgcPolyline& rkLine)
{
    // set world matrix
    const MgcMatrix3& rkRot = rkLine.WorldRotate();
    const MgcVector3& rkTrn = rkLine.WorldTranslate();
    MgcReal fScale = rkLine.WorldScale();
    GLfloat afModelToWorld[16] =
    {
        fScale*rkRot[0][0], fScale*rkRot[1][0], fScale*rkRot[2][0], 0.0f,
        fScale*rkRot[0][1], fScale*rkRot[1][1], fScale*rkRot[2][1], 0.0f,
        fScale*rkRot[0][2], fScale*rkRot[1][2], fScale*rkRot[2][2], 0.0f,
        rkTrn.x,            rkTrn.y,            rkTrn.z,            1.0f
    };

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glMultMatrixf(afModelToWorld);

    // render the object
    glBegin(GL_LINES);

    // draw line
    const MgcVector3* akVertex = rkLine.Vertices();
    unsigned int uiL;
    if ( rkLine.Colors() )
    {
        const MgcColor* akColor = rkLine.Colors();
        for (uiL = 0; uiL < rkLine.GetVertexQuantity() - 1; uiL++)
        {
            glColor3fv((GLfloat*)akColor++);
            glVertex3fv((GLfloat*)akVertex++);
            glColor3fv((GLfloat*)akColor++);
            glVertex3fv((GLfloat*)akVertex++);
        }
        
        // close the polyline
        if ( rkLine.Closed() )
        {
            glColor3fv((GLfloat*)akColor);
            glVertex3fv((GLfloat*)akVertex);
            glColor3fv((GLfloat*)rkLine.Colors());
            glVertex3fv((GLfloat*)rkLine.Vertices());
        }
    }
    else
    {
        for (uiL = 0; uiL < rkLine.GetVertexQuantity() - 1; uiL++)
        {
            glVertex3fv((GLfloat*)akVertex++);
            glVertex3fv((GLfloat*)akVertex++);
        }
        
        // close the polyline
        if ( rkLine.Closed() )
        {
            glVertex3fv((GLfloat*)akVertex);
            glVertex3fv((GLfloat*)rkLine.Vertices());
        }
    }

    glEnd();

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}
//----------------------------------------------------------------------------

//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcOglRenderer::Factory (MgcStream& rkStream)
{
    MgcOglRenderer* pkObject = new MgcOglRenderer;
    MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//---------------------------------------------------------------------------
void MgcOglRenderer::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcRenderer::Load(rkStream,pkLink);
}
//---------------------------------------------------------------------------
void MgcOglRenderer::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcRenderer::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcOglRenderer::Register (MgcStream& rkStream)
{
    return MgcRenderer::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcOglRenderer::Save (MgcStream& rkStream)
{
    MgcRenderer::Save(rkStream);
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// debugging
//---------------------------------------------------------------------------
bool MgcOglRenderer::OperationOkay ()
{
    GLenum eCode = glGetError();
    if ( eCode == GL_NO_ERROR )
        return true;

    char acMsg[128];
    sprintf(acMsg,"Error: %s\n",gluErrorString(eCode));
    OutputDebugString(acMsg);
    return false;
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -