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

📄 mesh.cpp

📁 此代码主要用于汽车车身的优化
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  implementation of the Mesh class.
//Mesh.cpp:网格类的执行
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Subdiv.h"
#include "Mesh.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#include "Vertex.h"
#include "Face.h"
#include <afx.h>
#include <iostream>
//#include <stdio.h>
//#include <stdlib.h>
#include <io.h>

Mesh::Mesh()
{
	m_pVertexes = new VERTEXSET;
	m_pSubdivVertexes = NULL;
}

Mesh::~Mesh()
{
	reset();
	delete m_pVertexes;
	// 
}

void Mesh::reset()
{
	if(m_pVertexes)
	{
		FOR_EACH_VERTEX(itr)
		{
			itr->reset();
		}
		m_pVertexes->clear();
	}
	if(m_pSubdivVertexes)	// be sure that whenever a new subdiv-mesh is made 
	{						// and vertexes is moved, set m_pSubdivVertexes = NULL
		FOR_EACH_SUBVERTEX(itr)
		{
			itr->reset();
		}
		m_pSubdivVertexes->clear();
		delete m_pSubdivVertexes;
		m_pSubdivVertexes = NULL;
	}
	FOR_EACH_EDGE(eitr)
	{
		eitr->reset();
	}
	m_edges.clear();
	FOR_EACH_FACE(fitr)
	{
		fitr->reset();
	}
	m_faces.clear();
}


inline int Mesh::addVertex(double x, double y, double z)
{
	Vertex v(x,y,z, m_pVertexes->size());
	m_pVertexes->push_back( v );
	return m_pVertexes->size()-1;
}

inline int Mesh::addVertex(Vector3d & d)
{
	Vertex v(d, m_pVertexes->size());
	m_pVertexes->push_back( v );
	return m_pVertexes->size()-1;
}


inline int Mesh::addSubdivVertex(Vector3d & d)
{
	Vertex v(d, m_pSubdivVertexes->size());
	m_pSubdivVertexes->push_back( v );
	return (m_pSubdivVertexes->size()-1);

}
// 对每个面只能调用一次。否则会多加
int Mesh::addFace(vector<int> & faceVertexsIdx)//增加面
{
	Mesh::EDGEPOS vp;
	Vector3d fedgevec1, fedgevec2;
	int fi = m_faces.size();		// index of the face to insert添加面的索引
	Face f(faceVertexsIdx, fi);
	int bvidx, evidx;
	int vnum = faceVertexsIdx.size();
	for(int i = 0; i < vnum; i ++)	// for each vertex of face
	{
		bvidx = faceVertexsIdx[i];
		evidx = faceVertexsIdx[(i+1)%vnum];
		
		//		cout << "faceVertexsIdx:" << bvidx << " " << evidx << endl;
		//		cout << "m_pVertexes:" << (*m_pVertexes).size() << endl;
		vp = findAndInsertEdgePos(bvidx, evidx);
		vp->addAdjFace(fi);								// add adj face for edge
		f.addEdge(vp);									// add edge for face
		// 保存的边的idx对应face中的idx的点,是出边。
		// 这样沿着面和这个点的idx对应的棱找出的邻面是按顺时针方向(法向向内)

		(*m_pVertexes)[bvidx].addAdjEdge(vp);			// add adj edge for vertex
		(*m_pVertexes)[evidx].addAdjEdge(vp);			// not add the reverse edge!! get rid of the edge-repetition check!
		
		// if ((*m_pVertexes)[bvidx].m_adjFaceIdx.size() > 1 ) ..
		(*m_pVertexes)[bvidx].addAdjFace(fi);			// add adj face for vertex
		//(*m_pVertexes)[bvidx].dump();
	}

	// calc face normal:计算法向量
	fedgevec1 = (*m_pVertexes)[faceVertexsIdx[1]].m_v - (*m_pVertexes)[faceVertexsIdx[0]].m_v;
	fedgevec2 = (*m_pVertexes)[faceVertexsIdx[2]].m_v - (*m_pVertexes)[faceVertexsIdx[1]].m_v;
	f.m_normal = Cross(fedgevec1, fedgevec2).normalize();//
	m_faces.push_back(f);	// as 
	return fi;
}

Mesh::EDGEPOS Mesh::findAndInsertEdgePos(int bgVertexIdx, int edVertexIdx)//查找和插入边
{
//	m_edges.find()
	Edge e(bgVertexIdx, edVertexIdx);
	return m_edges.insert(e).first;	// if not exist, insert it.
}

inline Vertex& Mesh::getVertex(int idx)//获取点的索引
{
	return (*m_pVertexes)[idx];
}

inline Edge& Mesh::getEdge(Mesh::EDGEPOS ep)//获取边的索引
{
	return *ep;
}

inline Face& Mesh::getFace(int idx)//获取面的索引
{
	return m_faces[idx];
}

// get adjacent face of f, both of which have the same edge e
//  if edge only have one adj face, then return -1;
int Mesh::getAdjFace(int fidx, const Edge &e)//获取边的临界面
{
//	e.dump();

	ASSERT(e.m_adjFaceIdxSet.size() <= 2 && e.m_adjFaceIdxSet.size() >= 1);		// manifold? at least one adjacent?
	if( e.m_adjFaceIdxSet.size() == 1 )
	{
		ASSERT(e.m_adjFaceIdxSet[0] == fidx);			// at least one adjacent?
		return -1;
	}
	ASSERT(e.m_adjFaceIdxSet[0] == fidx || e.m_adjFaceIdxSet[1] == fidx);		// adjacent?
	
	return (e.m_adjFaceIdxSet[0] == fidx ? e.m_adjFaceIdxSet[1] : e.m_adjFaceIdxSet[0] );	
}
/*
Face* Mesh::getAdjFace(const Face &f, const Edge &e)
{
	ASSERT(e.m_adjFaceIdxSet.size() <= 2 && e.m_adjFaceIdxSet.size() >= 1);		// manifold? at least one adjacent?
	if( e.m_adjFaceIdxSet.size() == 1 )
	{
		ASSERT(e.m_adjFaceIdxSet[0] == f.m_index);			// at least one adjacent?
		return NULL;
	}
	ASSERT(e.m_adjFaceIdxSet[0] == f.m_index || e.m_adjFaceIdxSet[1] == f.m_index);		// adjacent?
	
	return (e.m_adjFaceIdxSet[0] == f.m_index ? &getFace(e.m_adjFaceIdxSet[1]) : &getFace(e.m_adjFaceIdxSet[0]) );	
}*/

//以中心为新顶点,n边的面划分为n个面
Mesh* Mesh::splitTriangleMesh()//分割成三角网格
{
	// split all faces into triangles
	// 1  find a face
	// 2  change the face into triangle
	// 3  add the left part of the face as triangls...
	// Simple solution:
	//   add all splited faces without deleting already exist info..
	//   then mark the be-splited faces entry to be no use...
	
	Mesh *p = new Mesh();
	
	// copy only the vertex position and index
	for( int i = 0; i < m_pVertexes->size(); i ++ )
	{
		Vertex v((*m_pVertexes)[i].m_v, (*m_pVertexes)[i].m_index);
		p->m_pVertexes->push_back(v);
	}

//	p->dump();
//	cout << endl;
	int fnum = m_faces.size();
	vector<int> newSplitFacesIdx;
	for ( int fi = 0; fi < fnum; fi ++ )
	{
		if( m_faces[fi].m_vertexIdxSet.size() > 3)
		{	// get central point first
			Vector3d v;
			int k = m_faces[fi].m_vertexIdxSet.size();
			for( int j = 0; j < k; j ++ )	// k vertices => k-2 triangles
				v += getVertex(m_faces[fi].m_vertexIdxSet[j]).m_v;
			v /= k;
			int centralvi = p->addVertex(v);
			// then split face into n faces with same vertex : the central point
			for( j = 0; j < k; j ++ )	// k vertices => k edges ==> k new faces
			{ 
				newSplitFacesIdx.push_back(centralvi);
				newSplitFacesIdx.push_back(m_faces[fi].m_vertexIdxSet[j]);
				newSplitFacesIdx.push_back(m_faces[fi].m_vertexIdxSet[(j+1) % k]);

				p->addFace(newSplitFacesIdx);
				newSplitFacesIdx.clear();
			}
		}
		else p->addFace(m_faces[fi].m_vertexIdxSet);
	}
	return p;
}

void Mesh::prepareLoopSubdivMesh()//以下是对新顶点位置的计算
{
	if(m_pSubdivVertexes)
	{
		m_pSubdivVertexes->clear();
		delete m_pSubdivVertexes;
	}
	m_pSubdivVertexes = new VERTEXSET;
	
	// for each vertex, calc a new Vertex对于每一个顶点产生一个新顶点
	double beta[20];
	for( int i = 1; i < 20; i ++ )
	{
		beta[i] = 1.0 / i * ( 5. / 8 - pow(3. / 8 + 1. / 4 * cos(2 * 3.1415926 / i), 2 ) );
	//beta[i] =(3-2*cos(2*3.1415/i))/9/i;
	}
	//proposed by Warren
/*	for( i = 3; i < 20; i ++ )
	{
		if(i == 3)
			beta[i] = 3. / 16;
		else 
			beta[i] = 3. / 8. / i;
	}*/
	FOR_EACH_VERTEX(vitr)//求新顶点
	{
		int k = vitr->m_adjEdgePosSet.size();
		ASSERT( k < 20 );//断言函数,返回一个布尔值
		if( ! vitr->isOnBoundary() )			// if not on boundary如果不是边界的话
		{
			Vector3d newV(vitr->m_v * ( 1. - k * beta[k]));
			for( int i = 0; i < k; i ++ )
			{
				int vi = getEdge(vitr->m_adjEdgePosSet[i]).getCounterVertex(vitr->m_index);
				newV += (getVertex(vi).m_v * beta[k]);
			}
			vitr->m_newVertexPointIdx = addSubdivVertex(newV);
		} 
		else if ( vitr->m_adjEdgePosSet.size() == 3 && vitr->m_adjFaceIdxSet.size() == 2 )
		{
			vitr->m_newVertexPointIdx = addSubdivVertex(vitr->m_v);
		}
		else if ( vitr->m_adjEdgePosSet.size() >= 2 )
		{
			// find the boundary edge:寻找边界边
			int benum = 0;
			Vector3d newV(vitr->m_v * 3. / 4);
			for (int i = 0; i < vitr->m_adjEdgePosSet.size(); i ++)
			{
				if (vitr->m_adjEdgePosSet[i]->isOnBoundary())
				{
					int vi = getEdge(vitr->m_adjEdgePosSet[i]).getCounterVertex(vitr->m_index);
					newV += (getVertex(vi).m_v / 8);
					benum ++;
				}
			}
			vitr->m_newVertexPointIdx = addSubdivVertex(newV);
			ASSERT(benum == 2);		// only two boundary edges connected to an extraordinary vertex
		}
		else 
		{
			cout << "Unused Vertex: ";
			vitr->dump();
		}
	}
	FOR_EACH_EDGE(vp)//求新边点
	{
		Vector3d newV = (getVertex(vp->m_bgVertexIdx).m_v + getVertex(vp->m_edVertexIdx).m_v) * 3. / 8.;//3/8(v0+v1)
		// find other two vertex on edge's two faces
		if ( vp->m_adjFaceIdxSet.size() == 2 )//如果邻接面有两个
		{
			Face &f = getFace(vp->m_adjFaceIdxSet[0]);
//			ASSERT(f.m_vertexIdxSet.size() == 3);
			for( int i = 0; i < f.m_edgePosSet.size(); i ++)
				if(vp == f.m_edgePosSet[i])		// vertex[i], vertex[i+1] is the index of the edge. vertex[i+2] is the point we search for
				{
					newV += ( getVertex(f.m_vertexIdxSet[(i+2) % f.m_vertexIdxSet.size()]).m_v / 8 );
					break;
				}
			Face &f2 = getFace(vp->m_adjFaceIdxSet[1]);
//			ASSERT(f2.m_vertexIdxSet.size() == 3);
			for( i = 0; i < f2.m_edgePosSet.size(); i ++)
				if(vp == f2.m_edgePosSet[i])		// vertex[i], vertex[i+1] is the index of the edge. vertex[i+2] is the point we search for
				{
					newV += ( getVertex(f2.m_vertexIdxSet[(i+2) % f2.m_vertexIdxSet.size()]).m_v / 8 );
					break;
				}
			vp->m_newEdgePointIdx = addSubdivVertex(newV);
		}
		else if ( vp->isOnBoundary() )//如果是边界边
		{	// extraordinary point
			 newV = getVertex(vp->m_bgVertexIdx).m_v + getVertex(vp->m_edVertexIdx).m_v;
			vp->m_newEdgePointIdx = addSubdivVertex(newV / 2);
		}
		else 
		{
			cout << "None manifold: ";
			vp->dump();
		}
	}

}

// 切分为三角片,再loop
Mesh* Mesh::calcLoopSubdivMesh(bool divBeforeLoop)
{
	if( divBeforeLoop )
	{
		FOR_EACH_FACE(fitr)
		{
			Mesh *p, *q;
			if(fitr->m_vertexIdxSet.size() > 3)
			{
				p = splitTriangleMesh();
//				p->dump();
				q = p->calcLoopSubdivMeshSep();
				p->reset();
				delete p;		// delete temp triangle-mesh删除临时的三角面片
				return q;
			}
		}
	}
	// fall through if no face to div:
	return calcLoopSubdivMeshSep();
}	
	
Mesh* Mesh::calcLoopSubdivMeshSep()// loop细分开始
{
	prepareLoopSubdivMesh();
	bool blFound;
	Mesh *pSubMesh = new Mesh();
	// link(copy) vertexes data
	pSubMesh->m_pVertexes = this->m_pSubdivVertexes;

//	FOR_EACH_FACE(fitr)		// Faces may changes when looping
	int fnum = m_faces.size();
	for( int i = 0; i < fnum; i ++ )
	{
		vector<int> innerFaceVertex;//内部顶点
		vector<int> cornerFaceVertex;//

		int k = m_faces[i].m_vertexIdxSet.size();
		for( int j = 0; j < k; j ++)
		{
		
			innerFaceVertex.push_back( (m_faces[i].m_edgePosSet[j])->m_newEdgePointIdx );
			//连接三个新边点新边点
			
			cornerFaceVertex.push_back( getVertex(m_faces[i].m_vertexIdxSet[j]).m_newVertexPointIdx );//插入新顶点
			cornerFaceVertex.push_back( m_faces[i].m_edgePosSet[j]->m_newEdgePointIdx );
			cornerFaceVertex.push_back( m_faces[i].m_edgePosSet[(j+k-1) % k]->m_newEdgePointIdx );
			//角上的三个三角形
			pSubMesh->addFace(cornerFaceVertex);
			cornerFaceVertex.clear();
		}
		pSubMesh->addFace(innerFaceVertex);
		innerFaceVertex.clear();
	}
	
	this->m_pSubdivVertexes = NULL;
	pSubMesh->printMeshInfo();
	return pSubMesh;
}


/*
// two old edition of Catmull.  errors a lot in somewhere ...

// first calc all edge's middle point, face's central point
// then calc all new edge point, and new vertex point (face point is ready)
void Mesh::prepareCatmullSubdivData()
{
	if(m_pSubdivVertexes)
	{
		m_pSubdivVertexes->clear();
		delete m_pSubdivVertexes;
	}
	m_pSubdivVertexes = new VERTEXSET;

	// edge mid point:
	FOR_EACH_EDGE(vp)
	{
		vp->setMidPoint( (getVertex(vp->m_bgVertexIdx).getVertex3d() + 
							getVertex(vp->m_edVertexIdx).getVertex3d()) / 2 );
	}
	// face central point:
	FOR_EACH_FACE(fitr)
	{
		Vector3d v;
		for( int j = 0; j < fitr->m_vertexIdxSet.size(); j ++ )
			v += getVertex(fitr->m_vertexIdxSet[j]).getVertex3d();

		fitr->m_newFacePointIdx = addSubdivVertex(v / fitr->m_vertexIdxSet.size());
	}

	
	// new edgepoint: two adj face point + 2 * midpoint / 4
	Vector3d v2;
	for( vp = m_edges.begin(); vp != m_edges.end(); vp ++)
	{
		ASSERT(vp->m_adjFaceIdxSet.size() <= 2);		// deals with manifold only
		ASSERT(vp->m_adjFaceIdxSet.size() > 0);			// all edges are built from faces
		
		// view otherside as a very slim face, that is, a line covering the edge
		if( vp->m_adjFaceIdxSet.size() == 2 )	
		{
			Vector3d v;
			v =	(vp->m_midPoint * 2 + \
				 ( (*m_pSubdivVertexes)[ getFace( vp->m_adjFaceIdxSet[1] ).m_newFacePointIdx] ).m_v +
				 ( (*m_pSubdivVertexes)[ getFace( vp->m_adjFaceIdxSet[0] ).m_newFacePointIdx] ).m_v)  / 4;
			vp->m_newEdgePointIdx = addSubdivVertex(v);
		}
		else	// vp->m_adjFaceIdxSet.size() == 1
		{
			vp->m_newEdgePointIdx = addSubdivVertex(vp->m_midPoint);
		}
	}
	// new vertex point:  Beta/k * all edge + Gama/k * all anti vertex + (1-Beta-Gama)old vertex 
	//                     (Beta = 3/2k, Gama = 1/4k, Beta = 6 * Gama)
	// == all( face point / faceVertexNum * gama / Beta 
	//    + edge point * 2 * 5 / 4 / k
	//    + old vertex point * 1-(6+2+5/2)* gama / k

	for( i = 0; i < m_pVertexes->size(); i ++)
	{
		Vector3d q, r;	// initially zero
		int k = (*m_pVertexes)[i].m_adjFaceIdxSet.size();
*/

⌨️ 快捷键说明

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