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

📄 conformalmapping.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
#include "ConformalMapping.h"
#include "WmlConformalMap.h"
#include "WmlMeshCurvature.h"

#include <algorithm>
#include <fstream>
using namespace std;

ConformalMapping g_kTheApp;

//----------------------------------------------------------------------------
ConformalMapping::ConformalMapping ()
    :
    Application("ConformalMapping",0,0,640,480,ColorRGB(0.5f,0.0f,1.0f))
{
}
//----------------------------------------------------------------------------
bool ConformalMapping::OnInitialize ()
{
    if ( !Application::OnInitialize() )
        return false;

    // set up camera
    ms_spkCamera->SetFrustum(0.1f,100.0f,-0.055f,0.055f,0.04125f,-0.04125f);
    Vector3f kCLoc(0.0f,0.0f,-6.5f);
    Vector3f kCLeft(1.0f,0.0f,0.0f);
    Vector3f kCUp(0.0f,1.0f,0.0f);
    Vector3f kCDir(0.0f,0.0f,1.0f);
    ms_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);

    // load brain mesh
    Stream kInfile;
    kInfile.Load("brain.mgc");
    m_spkMesh = (TriMesh*)kInfile.GetObjectAt(0);

    // give it vertex colors
    m_spkMesh->Reconstruct(
        m_spkMesh->GetVertexQuantity(),
        m_spkMesh->Vertices(),
        m_spkMesh->Normals(),
        new ColorRGB[m_spkMesh->GetVertexQuantity()],
        m_spkMesh->Textures(),
        m_spkMesh->GetTriangleQuantity(),
        m_spkMesh->Connectivity());

    // use pseudocoloring based on mean curvature
    PseudocolorVertices();

    // Numerical preconditioning for computing the conformal map.  The choice
    // of fExtreme is based on knowledge of the size of the vertices in the
    // input mesh m_spkMesh.
    float fExtreme = 10.0f;
    ScaleToCube(fExtreme);

    DoMapping();

    // set up scene graph
    m_spkScene = new Node(2);
    m_spkWireframe = new WireframeState;
    m_spkWireframe->Enabled() = false;
    m_spkScene->SetRenderState(m_spkWireframe);
    ZBufferState* pkZBuffer = new ZBufferState;
    pkZBuffer->Enabled() = true;
    pkZBuffer->Writeable() = true;
    pkZBuffer->Compare() = ZBufferState::CF_LEQUAL;
    m_spkScene->SetRenderState(pkZBuffer);

    // subtree for mesh
    m_spkMeshTree = new Node;
    m_spkMeshTree->Translate() = Vector3f(2.0f,0.0f,0.0f);
    m_spkMeshTree->Scale() = 1.0f/fExtreme;
    m_spkScene->AttachChild(m_spkMeshTree);
    Node* pkMeshParent = new Node;
    m_spkMeshTree->AttachChild(pkMeshParent);
    pkMeshParent->AttachChild(m_spkMesh);
    pkMeshParent->Translate() = -m_spkMesh->ModelBound().Center();

    // subtree for sphere
    m_spkSphereTree = new Node;
    m_spkSphereTree->Translate() = Vector3f(-2.0f,0.0f,0.0f);
    m_spkScene->AttachChild(m_spkSphereTree);
    Node* pkSphereParent = new Node;
    m_spkSphereTree->AttachChild(pkSphereParent);
    pkSphereParent->AttachChild(m_spkSphere);
    pkSphereParent->Translate() = -m_spkSphere->ModelBound().Center();

    // initial update of objects
    ms_spkCamera->Update();
    m_spkScene->UpdateGS(0.0f);
    m_spkScene->UpdateRS();

    m_spkMotionObject = m_spkScene;
    m_bTurretActive = true;
    SetTurretAxes();
    m_fTrnSpeed = 0.01f;
    m_fRotSpeed = 0.01f;

    return true;
}
//----------------------------------------------------------------------------
void ConformalMapping::OnTerminate ()
{
    m_spkScene = NULL;
    m_spkWireframe = NULL;
    m_spkMeshTree = NULL;
    m_spkSphereTree = NULL;
    m_spkMesh = NULL;
    m_spkSphere = NULL;
    Application::OnTerminate();
}
//----------------------------------------------------------------------------
void ConformalMapping::OnIdle ()
{
    if ( !ms_spkRenderer )
        return;

    MeasureTime();

    MoveCamera();
    if ( MoveObject() )
        m_spkScene->UpdateGS(0.0f);

    ms_spkRenderer->ClearBuffers();
    if ( ms_spkRenderer->BeginScene() )
    {
        ms_spkRenderer->Draw(m_spkScene);
        DrawFrameRate(8,GetHeight()-8,ColorRGB::WHITE);
        ms_spkRenderer->EndScene();
    }
    ms_spkRenderer->DisplayBackBuffer();

    UpdateClicks();
}
//----------------------------------------------------------------------------
void ConformalMapping::OnKeyDown (unsigned char ucKey, int, int)
{
    if ( ucKey == 'q' || ucKey == 'Q' || ucKey == KEY_ESCAPE )
    {
        RequestTermination();
        return;
    }

    switch ( ucKey )
    {
    case 'w':
        m_spkWireframe->Enabled() = !m_spkWireframe->Enabled();
        break;
    case 'm':
        m_spkMotionObject = m_spkMeshTree;
        break;
    case 's':
        m_spkMotionObject = m_spkSphereTree;
        break;
    case 'r':
        m_spkMotionObject = m_spkScene;
        break;
    }
}
//----------------------------------------------------------------------------
void ConformalMapping::ScaleToCube (float fExtreme)
{
    // Uniformly scale the cube to [-extreme,extreme]^3 for numerical
    // preconditioning for the conformal mapping.

    int iVQuantity = m_spkMesh->GetVertexQuantity();
    Vector3f* akPoint = m_spkMesh->Vertices();

    float fMin = akPoint[0].X(), fMax = fMin;
    int i;
    for (i = 0; i < iVQuantity; i++)
    {
        if ( akPoint[i].X() < fMin )
            fMin = akPoint[i].X();
        else if ( akPoint[i].X() > fMax )
            fMax = akPoint[i].X();

        if ( akPoint[i].Y() < fMin )
            fMin = akPoint[i].Y();
        else if ( akPoint[i].Y() > fMax )
            fMax = akPoint[i].Y();

        if ( akPoint[i].Z() < fMin )
            fMin = akPoint[i].Z();
        else if ( akPoint[i].Z() > fMax )
            fMax = akPoint[i].Z();
    }
    float fHalfRange = 0.5f*(fMax - fMin);
    float fMult = fExtreme/fHalfRange;

    Vector3f kOne(1.0f,1.0f,1.0f);
    for (i = 0; i < iVQuantity; i++)
        akPoint[i] = -fExtreme*kOne + fMult*(akPoint[i] - fMin*kOne);

    m_spkMesh->UpdateModelBound();
}
//----------------------------------------------------------------------------
void ConformalMapping::PseudocolorVertices ()
{
    // color the vertices according to mean curvature

    int iVQuantity = m_spkMesh->GetVertexQuantity();
    const Vector3f* akPoint = m_spkMesh->Vertices();
    ColorRGB* akColor = m_spkMesh->Colors();
    int iTQuantity = m_spkMesh->GetTriangleQuantity();
    const int* aiConnect = m_spkMesh->Connectivity();

    MeshCurvaturef kMC(iVQuantity,akPoint,iTQuantity,aiConnect);
    const float* afMinCurv = kMC.GetMinCurvatures();
    const float* afMaxCurv = kMC.GetMaxCurvatures();
    float fMinMeanCurvature = afMinCurv[0] + afMaxCurv[0];
    float fMaxMeanCurvature = fMinMeanCurvature;
    float* afMeanCurvature = new float[iVQuantity];
    int i;
    for (i = 0; i < iVQuantity; i++)
    {
        afMeanCurvature[i] = afMinCurv[i] + afMaxCurv[i];
        if ( afMeanCurvature[i] < fMinMeanCurvature )
            fMinMeanCurvature = afMeanCurvature[i];
        else if ( afMeanCurvature[i] > fMaxMeanCurvature )
            fMaxMeanCurvature = afMeanCurvature[i];
    }

    for (i = 0; i < iVQuantity; i++)
    {
        if ( afMeanCurvature[i] > 0.0f )
        {
            akColor[i].r = 0.5f+0.5f*afMeanCurvature[i]/fMaxMeanCurvature;
            akColor[i].g = akColor[i].r;
            akColor[i].b = 0.0f;
        }
        else if ( afMeanCurvature[i] < 0.0f )
        {
            akColor[i].r = 0.0f;
            akColor[i].g = 0.0f;
            akColor[i].b = 0.5f+0.5f*(-afMeanCurvature[i]/fMinMeanCurvature);
        }
        else
        {
            akColor[i] = ColorRGB::BLACK;
        }
    }

    delete[] afMeanCurvature;
}
//----------------------------------------------------------------------------
void ConformalMapping::DoMapping ()
{
    int iVQ = m_spkMesh->GetVertexQuantity();
    Vector3f* akVertex = m_spkMesh->Vertices();
    ColorRGB* akColor = m_spkMesh->Colors();
    int iTQ = m_spkMesh->GetTriangleQuantity();
    const int* aiConnect = m_spkMesh->Connectivity();

    // color the punctured triangle red
    akColor[aiConnect[0]] = ColorRGB(1.0f,0.0f,0.0f);
    akColor[aiConnect[1]] = ColorRGB(1.0f,0.0f,0.0f);
    akColor[aiConnect[2]] = ColorRGB(1.0f,0.0f,0.0f);

    // conformally map mesh to plane, sphere, and cylinder
    ConformalMapf kCMap(iVQ,akVertex,iTQ,aiConnect);

    // create a representation of the conformal sphere
    Vector3f* akSVertex = new Vector3f[iVQ];
    ColorRGB* akSColor = new ColorRGB[iVQ];
    int* aiSConnect = new int[3*iTQ];
    memcpy(akSVertex,kCMap.GetSphereCoordinates(),iVQ*sizeof(Vector3f));
    memcpy(akSColor,akColor,iVQ*sizeof(ColorRGB));
    memcpy(aiSConnect,aiConnect,3*iTQ*sizeof(int));
    m_spkSphere = new TriMesh(iVQ,akSVertex,NULL,akSColor,NULL,iTQ,
        aiSConnect);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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