📄 conformalmapping.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 + -