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

📄 mgcgprenderer.cpp

📁 《3D游戏引擎设计》的源码
💻 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 "MgcGPRenderer.h"

MgcImplementRTTI(MgcGPRenderer,MgcRenderer);
MgcImplementStream(MgcGPRenderer);

//---------------------------------------------------------------------------
MgcGPRenderer::MgcGPRenderer (int iWidth, int iHeight)
    :
    MgcRenderer(iWidth,iHeight)
{
    m_fWidth = MgcReal(iWidth);
    m_fHeight = MgcReal(iHeight);
    m_fXScale = 0.5*(m_fWidth - 1.0);
    m_fYScale = 0.5*(m_fHeight - 1.0);

    // edge buffers for scan line rasterizing
    int i;
    m_aiXMin = new int[m_iHeight];
    m_aiXMax = new int[m_iHeight];
    m_aafLinAttrMin = new MgcReal*[m_iHeight];
    m_aafLinAttrMax = new MgcReal*[m_iHeight];
    m_aafPerAttrMin = new MgcReal*[m_iHeight];
    m_aafPerAttrMax = new MgcReal*[m_iHeight];
    for (i = 0; i < 3; i++)
    {
        m_aafLinAttr[i] = new MgcReal[m_iHeight];
        m_aafPerAttr[i] = new MgcReal[m_iHeight];
    }
    for (i = 0; i < m_iHeight; i++)
    {
        m_aafLinAttrMin[i] = new MgcReal[MAX_ATTRIBUTES];
        m_aafLinAttrMax[i] = new MgcReal[MAX_ATTRIBUTES];
        m_aafPerAttrMin[i] = new MgcReal[MAX_ATTRIBUTES];
        m_aafPerAttrMax[i] = new MgcReal[MAX_ATTRIBUTES];
    }
}
//---------------------------------------------------------------------------
MgcGPRenderer::MgcGPRenderer ()
{
}
//---------------------------------------------------------------------------
MgcGPRenderer::~MgcGPRenderer ()
{
    int i;
    for (i = 0; i < 3; i++)
    {
        delete[] m_aafLinAttr[i];
        delete[] m_aafPerAttr[i];
    }
    for (i = 0; i < m_iHeight; i++)
    {
        delete[] m_aafLinAttrMin[i];
        delete[] m_aafLinAttrMax[i];
        delete[] m_aafPerAttrMin[i];
        delete[] m_aafPerAttrMax[i];
    }
    delete[] m_aiXMin;
    delete[] m_aiXMax;
    delete[] m_aafLinAttrMin;
    delete[] m_aafLinAttrMax;
    delete[] m_aafPerAttrMin;
    delete[] m_aafPerAttrMax;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::ProjectVertices ()
{
    unsigned int uiV, uiVMax = m_kMesh.GetVerticesUsed();

    if ( ZBufferActive() )
    {
        // TO DO.  Map depths to 16-bit, assert on integer values rather
        // than float values.  Remove clipping epsilon.
        MgcReal fDepthCoeff = GetCamera()->GetFarDivideFarMinusNear();
        for (uiV = 0; uiV < uiVMax; uiV++)
        {
            if ( m_kMesh.GetVertexVisible(uiV) )
            {
                MgcVector3& rkVertex = m_kMesh.Vertex(uiV);
                MgcReal fInverseW = 1.0/rkVertex.z;
                rkVertex.x = m_fXScale*(rkVertex.x*fInverseW + 1.0);
                rkVertex.y = m_fYScale*(rkVertex.y*fInverseW + 1.0);
                m_kMesh.Depth(uiV) = fDepthCoeff*(1.0 - fInverseW);
#ifdef _DEBUG
                int iX = int(rkVertex.x);
                int iY = int(rkVertex.y);
                assert( 0 <= iX && iX < m_iWidth );
                assert( 0 <= iY && iY < m_iHeight );
                assert( m_kMesh.Depth(uiV) >= -0.0001
                    &&  m_kMesh.Depth(uiV) <= 1.0001 );
#endif
            }
        }
    }
    else
    {
        for (uiV = 0; uiV < uiVMax; uiV++)
        {
            if ( m_kMesh.GetVertexVisible(uiV) )
            {
                MgcVector3& rkVertex = m_kMesh.Vertex(uiV);
                MgcReal fInverseW = 1.0/rkVertex.z;
                rkVertex.x = m_fXScale*(rkVertex.x*fInverseW + 1.0);
                rkVertex.y = m_fYScale*(rkVertex.y*fInverseW + 1.0);
#if _DEBUG
                int iX = int(rkVertex.x);
                int iY = int(rkVertex.y);
                assert( 0 <= iX && iX < m_iWidth );
                assert( 0 <= iY && iY < m_iHeight );
#endif
            }
        }
    }
}
//---------------------------------------------------------------------------
void MgcGPRenderer::Draw (const MgcGPTriMesh& rkTriMesh)
{
    // copy trimesh to local memory
    m_kMesh.Copy(rkTriMesh);

    // determine status of vertex colors, lights, and materials
    m_kMesh.GetLightingStatus(m_pkLightState,m_pkMaterialState,
        m_pkVertexColorState,rkTriMesh.GetColors());

    // transform camera to model space
    const MgcVector3& rkWorldTranslate = rkTriMesh.WorldTranslate();
    const MgcMatrix3& rkWorldRotate = rkTriMesh.WorldRotate();
    MgcReal fWorldScale = rkTriMesh.WorldScale();
    MgcVector3 kDiff = m_spkCamera->GetLocation() - rkWorldTranslate;
    m_kMesh.m_kCameraModelLocation = (kDiff*rkWorldRotate)/fWorldScale;

    // back face cull triangles (normals assumed to point outwards)
    bool bAllTrianglesCulled = true;
    for (unsigned int uiT = 0; uiT < rkTriMesh.GetTrianglesUsed(); uiT++)
    {
        const MgcPlane& rkFacetPlane = rkTriMesh.GetFacetPlane(uiT);
        if ( rkFacetPlane.DistanceTo(m_kMesh.m_kCameraModelLocation) > 0.0 )
        {
            // triangle is front facing, tag front facing vertices and edges
            bAllTrianglesCulled = false;
            m_kMesh.m_abTriangleVisible[uiT] = true;
            MgcGPTriMesh::TriangleRecord& rkTri = m_kMesh.Triangle(uiT);
            for (int i = 0; i < 3; i++)
            {
                m_kMesh.m_abVertexVisible[rkTri.Vertex(i)] = true;
                m_kMesh.m_abEdgeVisible[rkTri.Edge(i)] = true;
            }
        }
    }

    if ( bAllTrianglesCulled )
        return;

    // composition of model-to-world and world-to-view
    MgcMatrix3 kMVMat;
    MgcVector3 kMVTrn;
    GetCamera()->ComputeModelToViewTransform(rkWorldRotate,rkWorldTranslate,
        fWorldScale,kMVMat,kMVTrn);

    // save model space vertices for deferred lighting calculations
    if ( m_kMesh.m_bHasModelVertices )
    {
        memcpy(m_kMesh.GetModelVertices(),m_kMesh.GetVertices(),
            m_kMesh.m_uiVerticesUsed*sizeof(MgcVector3));
    }

    // transform vertices
    unsigned int uiOldVerticesUsed = m_kMesh.m_uiVerticesUsed;
    unsigned int uiV;
    for (uiV = 0; uiV < uiOldVerticesUsed; uiV++)
    {
        if ( m_kMesh.m_abVertexVisible[uiV] )
        {
            MgcVector3 kVertex = m_kMesh.Vertex(uiV);
            m_kMesh.Vertex(uiV) = kMVMat*kVertex + kMVTrn;
        }
    }

    // clip triangles against view frustum.
    if ( Clip() )
    {
        // trimesh is completely culled
        return;
    }

    // compute attributes for lighting and for clip vertices
    m_kMesh.ComputeVertexAttributes(uiOldVerticesUsed);

    ProjectVertices();

    if ( m_pkWireframeState->Enabled() )
        RasterizeEdges();
    else
        RasterizeTriangles();
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetAlphaState (MgcAlphaState* pkState)
{
    m_pkAlphaState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetDitherState (MgcDitherState* pkState)
{
    m_pkDitherState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetFogState (MgcFogState* pkState)
{
    m_pkFogState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetLightState (MgcLightState* pkState)
{
    m_pkLightState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetMaterialState (MgcMaterialState* pkState)
{
    m_pkMaterialState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetShadeState (MgcShadeState* pkState)
{
    m_pkShadeState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetTextureState (MgcTextureState* pkState)
{
    m_pkTextureState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetVertexColorState (MgcVertexColorState* pkState)
{
    m_pkVertexColorState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetWireframeState (MgcWireframeState* pkState)
{
    m_pkWireframeState = pkState;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::SetZBufferState (MgcZBufferState* pkState)
{
    m_pkZBufferState = pkState;
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcGPRenderer::Factory (MgcStream& rkStream)
{
    // MgcGPRenderer is abstract, Factory never called.
    return 0;
}
//---------------------------------------------------------------------------
void MgcGPRenderer::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcRenderer::Load(rkStream,pkLink);
}
//---------------------------------------------------------------------------
void MgcGPRenderer::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcRenderer::Link(rkStream,pkLink);
}
//---------------------------------------------------------------------------
bool MgcGPRenderer::Register (MgcStream& rkStream)
{
    return MgcRenderer::Register(rkStream);
}
//---------------------------------------------------------------------------
void MgcGPRenderer::Save (MgcStream& rkStream)
{
    MgcRenderer::Save(rkStream);
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

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