📄 mgctubesurfaceg.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
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf
#include "MgcMultipleCurve3.h"
#include "MgcTubeSurfaceG.h"
//----------------------------------------------------------------------------
MgcTubeSurfaceG::MgcTubeSurfaceG (MgcMultipleCurve3* pkMedial,
RadialFunction oRadial, bool bClosed, unsigned int uiMedialSamples,
unsigned int uiSliceSamples, bool bSampleByArcLength, bool bWantNormals,
const MgcVector3* pkUpVector)
{
assert( pkMedial && oRadial );
m_pkMedial = pkMedial;
m_oRadial = oRadial;
m_bClosed = bClosed;
m_uiVertexQuantity = 0;
m_akVertex = 0;
m_akNormal = 0;
m_uiTriangleQuantity = 0;
m_auiConnect = 0;
// default tessellation
Tessellate(uiMedialSamples,uiSliceSamples,bSampleByArcLength,bWantNormals,
pkUpVector);
}
//----------------------------------------------------------------------------
MgcTubeSurfaceG::MgcTubeSurfaceG ()
{
m_pkMedial = 0;
m_oRadial = 0;
m_bClosed = false;
m_uiVertexQuantity = 0;
m_akVertex = 0;
m_akNormal = 0;
m_uiTriangleQuantity = 0;
m_auiConnect = 0;
}
//----------------------------------------------------------------------------
MgcTubeSurfaceG::~MgcTubeSurfaceG ()
{
delete m_pkMedial;
delete[] m_akVertex;
delete[] m_akNormal;
delete[] m_auiConnect;
}
//----------------------------------------------------------------------------
unsigned int MgcTubeSurfaceG::Index (unsigned short uiS, unsigned short uiM)
{
return uiS + (m_uiSliceSamples+1)*uiM;
}
//----------------------------------------------------------------------------
void MgcTubeSurfaceG::ComputeVertices ()
{
if ( m_bClosed )
m_uiVertexQuantity = (m_uiSliceSamples+1)*(m_uiMedialSamples+1);
else
m_uiVertexQuantity = (m_uiSliceSamples+1)*m_uiMedialSamples;
delete[] m_akVertex;
m_akVertex = new MgcVector3[m_uiVertexQuantity];
// Compute slice vertex coefficients. The first and last coefficients
// are duplicated to allow a closed cross section that has two different
// pairs of texture coordinates at the shared vertex.
MgcReal* afSin = new MgcReal[m_uiSliceSamples + 1];
MgcReal* afCos = new MgcReal[m_uiSliceSamples + 1];
unsigned int uiS;
for (uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
MgcReal fAngle = uiS*MgcMath::TWO_PI/m_uiSliceSamples;
afCos[uiS] = MgcMath::Cos(fAngle);
afSin[uiS] = MgcMath::Sin(fAngle);
}
afSin[m_uiSliceSamples] = afSin[0];
afCos[m_uiSliceSamples] = afCos[0];
// compute vertices
MgcReal fTMin = m_pkMedial->GetMinTime();
MgcReal fTRange = m_pkMedial->GetMaxTime() - fTMin;
MgcReal fTotalLength;
if ( m_bClosed )
fTotalLength = m_pkMedial->GetTotalLength();
else
fTotalLength = 0.0;
for (unsigned int uiM = 0, uiV = 0; uiM < m_uiMedialSamples; uiM++)
{
MgcReal fT;
if ( m_bClosed )
{
if ( m_bSampleByArcLength )
{
fT = m_pkMedial->GetTime(
uiM*fTotalLength/MgcReal(m_uiMedialSamples));
}
else
{
fT = fTMin + uiM*fTRange/MgcReal(m_uiMedialSamples);
}
}
else
{
if ( m_bSampleByArcLength )
{
fT = m_pkMedial->GetTime(
uiM*fTotalLength/MgcReal(m_uiMedialSamples-1));
}
else
{
fT = fTMin + uiM*fTRange/MgcReal(m_uiMedialSamples-1);
}
}
MgcReal fRadius = m_oRadial(fT);
// compute frame (position P, tangent T, normal N, binormal B)
MgcVector3 kP, kT, kN, kB;
if ( m_pkUpVector )
{
// Always use 'up' vector N rather than curve normal. You must
// constrain the curve so that T and N are never parallel. To
// build the frame from this, let
// B = Cross(T,N)/Length(Cross(T,N))
// and replace
// N = Cross(B,T)/Length(Cross(B,T)).
kP = m_pkMedial->GetPosition(fT);
kT = m_pkMedial->GetTangent(fT);
kB = kT.UnitCross(MgcVector3::UNIT_Z);
kN = kB.UnitCross(kT);
}
else
{
// use Frenet frame to create slices
m_pkMedial->GetFrame(fT,kP,kT,kN,kB);
}
// compute slice vertices, duplication at end point as noted earlier
unsigned int uiSave = uiV;
for (uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
m_akVertex[uiV] = kP + fRadius*(afCos[uiS]*kN + afSin[uiS]*kB);
uiV++;
}
m_akVertex[uiV] = m_akVertex[uiSave];
uiV++;
}
if ( m_bClosed )
{
for (uiS = 0; uiS <= m_uiSliceSamples; uiS++)
{
unsigned int uiI1 = Index(uiS,m_uiMedialSamples);
unsigned int uiI0 = Index(uiS,0);
m_akVertex[uiI1] = m_akVertex[uiI0];
}
}
delete[] afSin;
delete[] afCos;
}
//----------------------------------------------------------------------------
void MgcTubeSurfaceG::ComputeNormals ()
{
delete[] m_akNormal;
m_akNormal = new MgcVector3[m_uiVertexQuantity];
unsigned int uiSm, uiSp, uiMm, uiMp;
MgcVector3 kDir0, kDir1;
unsigned int uiS;
// interior normals (central differences)
for (unsigned int uiM = 1; uiM <= m_uiMedialSamples-2; uiM++)
{
for (uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
uiSm = ( uiS > 0 ? uiS-1 : m_uiSliceSamples-1 );
uiSp = uiS + 1;
uiMm = uiM - 1;
uiMp = uiM + 1;
kDir0 = m_akVertex[Index(uiSm,uiM)] - m_akVertex[Index(uiSp,uiM)];
kDir1 = m_akVertex[Index(uiS,uiMm)] - m_akVertex[Index(uiS,uiMp)];
m_akNormal[Index(uiS,uiM)] = kDir0.UnitCross(kDir1);
}
m_akNormal[Index(m_uiSliceSamples,uiM)] = m_akNormal[Index(0,uiM)];
}
// boundary normals
if ( m_bClosed )
{
// central differences
for (uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
uiSm = ( uiS > 0 ? uiS-1 : m_uiSliceSamples-1 );
uiSp = uiS + 1;
// m = 0
kDir0 = m_akVertex[Index(uiSm,0)] - m_akVertex[Index(uiSp,0)];
kDir1 = m_akVertex[Index(uiS,m_uiMedialSamples-1)] -
m_akVertex[Index(uiS,1)];
m_akNormal[uiS] = kDir0.UnitCross(kDir1);
// m = max
m_akNormal[Index(uiS,m_uiMedialSamples)] =
m_akNormal[Index(uiS,0)];
}
m_akNormal[Index(m_uiSliceSamples,0)] = m_akNormal[Index(0,0)];
m_akNormal[Index(m_uiSliceSamples,m_uiMedialSamples)] =
m_akNormal[Index(0,m_uiMedialSamples)];
}
else
{
// one-sided finite differences
// m = 0
for (uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
uiSm = ( uiS > 0 ? uiS-1 : m_uiSliceSamples-1 );
uiSp = uiS + 1;
kDir0 = m_akVertex[Index(uiSm,0)] - m_akVertex[Index(uiSp,0)];
kDir1 = m_akVertex[Index(uiS,0)] - m_akVertex[Index(uiS,1)];
m_akNormal[Index(uiS,0)] = kDir0.UnitCross(kDir1);
}
m_akNormal[Index(m_uiSliceSamples,0)] = m_akNormal[Index(0,0)];
// m = max-1
for (uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
uiSm = ( uiS > 0 ? uiS-1 : m_uiSliceSamples-1 );
uiSp = uiS + 1;
kDir0 = m_akVertex[Index(uiSm,m_uiMedialSamples-1)] -
m_akVertex[Index(uiSp,m_uiMedialSamples-1)];
kDir1 = m_akVertex[Index(uiS,m_uiMedialSamples-2)] -
m_akVertex[Index(uiS,m_uiMedialSamples-1)];
m_akNormal[uiS] = kDir0.UnitCross(kDir1);
}
m_akNormal[Index(m_uiSliceSamples,m_uiMedialSamples-1)] =
m_akNormal[Index(0,m_uiMedialSamples-1)];
}
}
//----------------------------------------------------------------------------
void MgcTubeSurfaceG::ComputeConnectivity ()
{
m_uiTriangleQuantity = 2*m_uiSliceSamples*m_uiMedialSamples;
delete[] m_auiConnect;
m_auiConnect = new unsigned int[3*m_uiTriangleQuantity];
unsigned int* puiConnect = m_auiConnect;
for (unsigned int uiM = 0, uiMStart = 0; uiM < m_uiMedialSamples; uiM++)
{
unsigned int uiI0 = uiMStart;
unsigned int uiI1 = uiI0 + 1;
uiMStart += m_uiSliceSamples + 1;
unsigned int uiI2 = uiMStart;
unsigned int uiI3 = uiI2 + 1;
for (unsigned int uiS = 0; uiS < m_uiSliceSamples; uiS++)
{
// TO DO. The ordering of the vertices assumes you want to view
// the tube from the inside. If you want a view from the outside
// or if you want a double-sided tube, this function must change.
*puiConnect++ = uiI0;
*puiConnect++ = uiI2;
*puiConnect++ = uiI1;
*puiConnect++ = uiI1;
*puiConnect++ = uiI2;
*puiConnect++ = uiI3;
uiI0++;
uiI1++;
uiI2++;
uiI3++;
}
}
}
//----------------------------------------------------------------------------
void MgcTubeSurfaceG::Tessellate (unsigned int uiMedialSamples,
unsigned int uiSliceSamples, bool bSampleByArcLength, bool bWantNormals,
const MgcVector3* pkUpVector)
{
m_uiMedialSamples = uiMedialSamples;
m_uiSliceSamples = uiSliceSamples;
m_bSampleByArcLength = bSampleByArcLength;
m_bWantNormals = bWantNormals;
m_pkUpVector = pkUpVector;
ComputeVertices();
if ( m_bWantNormals )
ComputeNormals();
ComputeConnectivity();
}
//----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -