www.pudn.com > cad3d.zip > SurfButterfly.cpp
/***************************************************************************
SurfButterfly.cpp: implementation of the CSurfButterfly class.
-------------------
begin : 2001
copyright : (C) 2001 by Martin Marinov
email : martin_marinov@hotmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "Surfaces/stdafx.h"
#include "Surfaces/SurfButterfly.h"
#include "Surfaces/ButtTri.h"
#include "TypeIds.h"
#include "Helpers/IntProperty.h"
#include "Helpers/DoubleProperty.h"
#include "Topology/VmAlgorithms.h"
class CButtVertex : public C3DPoint
{
public:
CButtVertex(math_real x = 0,math_real y = 0, math_real z = 0, math_real w = 1)
: C3DPoint (x, y, z, w) {}
CButtVertex(const C3DPoint& rPt)
: C3DPoint (rPt) {}
CButtVertex* GetVVertexPtr() { return this; }
};
//////////////////////////////////////////////////////////////////////
#define MAX_SUBDIV_LEVEL 6
const char pszButterflyMaxLevel[] = "Subdivision Level";
char pszButterflyWeight[] = "Tension parameter";
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSurfButterfly::CSurfButterfly(int nMaxLevel)
: m_nMaxLevel(nMaxLevel), m_nTris(0), m_nVerts(0)
{
SetName(GetTypeNameSt());
InitProperties();
}
CSurfButterfly::~CSurfButterfly()
{
}
void CSurfButterfly::InitProperties()
{
m_properties.push_back(new CIntProperty(&m_nMaxLevel, *this, pszButterflyMaxLevel, false, true, 0, MAX_SUBDIV_LEVEL));
m_properties.push_back(new CDoubleProperty(&NativeFace::m_dTension , *this, pszButterflyWeight));
m_properties.push_back(new CIntProperty(&m_nTris, *this, "Total Triangles", true, false));
m_properties.push_back(new CIntProperty(&m_nVerts, *this, "Total Vertices", true, false));
}
//////////////////////////////////////////////////////////////////////
//IObject implementation
//////////////////////////////////////////////////////////////////////
const char* CSurfButterfly::GetTypeNameSt()
{
return "Butterfly Scheme";
}
const char* CSurfButterfly::GetTypeName() const
{
return GetTypeNameSt();
}
uint CSurfButterfly::GetTypeId() const
{
return SURF_BUTTERFLY;
}
//////////////////////////////////////////////////////////////////////
// CControlMesh overrides
//////////////////////////////////////////////////////////////////////
bool CSurfButterfly::IsValencySupported(top_int nVertsCount) const
{
return nVertsCount == 3;
}
top_int CSurfButterfly::GetMaxValency() const
{
return 3;
}
top_int CSurfButterfly::GetMinValency() const
{
return 3;
}
/////////////////////////////////////////////////////////////////////
//IControled implementation
//////////////////////////////////////////////////////////////////////
void CSurfButterfly::ConvertToNative(NvArray& rVerts, NfArray& rTris)
{
int j;
VerticesIter iCpt = m_vertices.begin();
VerticesIter iCptEnd = m_vertices.end();
for (j = 0; iCpt != iCptEnd; ++iCpt, ++j)
{
iCpt->SetId(j);
rVerts[j] = NativeVertex(*iCpt);
}
FacesIter iFace = m_faces.begin();
FacesIter iFaceEnd = m_faces.end();
for (j = 0; iFace != iFaceEnd; ++iFace, ++j)
{
iFace->SetId(j);
rTris[j].SetVertices(*iFace, rVerts.begin());
}
iFace = m_faces.begin();
for (j = 0; iFace != iFaceEnd; ++iFace, ++j)
{
rTris[j].SetLinks(*iFace, rTris.begin());
}
}
void CSurfButterfly::Calculate()
{
if ( m_faces.empty() )
return;
DeleteVisualMesh();
int nTris = m_faces.size();
int nVerts = m_vertices.size();
int nMaxTris = (int)pow(4, m_nMaxLevel)*nTris;
int nTempTris = nMaxTris/4;
int nTempOdd = m_nMaxLevel % 2;
NfArray* pMainTris = new NfArray(nTempOdd == 0 ? nMaxTris : nTempTris);
NfArray* pTempTris = new NfArray(nTempOdd == 1 ? nMaxTris : nTempTris);
int nMaxVerts = nTris*(int)(3 + 3*((pow(4,m_nMaxLevel) - 1)/3 + pow(2, m_nMaxLevel) - 1)/2) + nVerts;
NvArray vertices(nMaxVerts);
ConvertToNative(vertices, *pMainTris);
NativeVertex* pTempVertices = vertices.begin() + nVerts;
for (int k = 0; k < m_nMaxLevel; ++k)
{
NativeFace* i = pMainTris->begin();
NativeFace* iEnd = i + nTris;
NativeFace::_MyType* pNextTri = pTempTris->begin();
for (; i != iEnd; ++i)
{
i->SubDivide(pTempVertices, pNextTri);
}
nTris <<= 2;//nTris *= 4;
std::swap(pMainTris, pTempTris);
}
nVerts = pTempVertices - vertices.begin();
delete pTempTris;
CVmAlgorithms(*this, pMainTris->begin(), nTris,
vertices.begin(), nVerts).CreateVisualMesh();
delete pMainTris;
m_bValid = true;
}