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;
}