📄 mesh.cpp
字号:
{
int k = vitr->m_adjEdgePosSet.size();
ASSERT( k < 50 );//断言函数,返回一个布尔值
Vector3d newV(vitr->m_v * ( 1. - aerfa[k]));
for( int i = 0; i < k; i ++ )
{
int vi = getEdge(vitr->m_adjEdgePosSet[i]).getCounterVertex(vitr->m_index);
newV += (getVertex(vi).m_v * aerfa[k])/k;
}
vitr->m_newVertexPointIdx = addSubdivVertex(newV);
}
}
Mesh* Mesh::calcsqrt3SubdivMesh(bool divBeforesqrt3)
{
if(divBeforesqrt3)
{
FOR_EACH_FACE(fitr)
{
Mesh *p, *q;
if(fitr->m_vertexIdxSet.size() > 3)
{
p = splitTriangleMesh();
// p->dump();
q = p->calcsqrt3SubdivMeshSep();
p->reset();
delete p; // delete temp triangle-mesh删除临时的三角面片
return q;
}
}
}
// fall through if no face to div:
return calcsqrt3SubdivMeshSep();
}
Mesh* Mesh::calcsqrt3SubdivMeshSep()// loop细分开始
{
preparesqrt3SubdivMesh();
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> firstFaceVertex;//分裂三角形
//vector<int> cornerFaceVertex;//
int k = m_faces[i].m_vertexIdxSet.size();
for( int j = 0; j < k; j ++)
{
// 连接新面点和新顶点
firstFaceVertex.push_back(m_faces[i].m_newFacePointIdx );
firstFaceVertex.push_back(getVertex(m_faces[i].m_vertexIdxSet[j]).m_newVertexPointIdx );
//firstFaceVertex.push_back(m_faces[i].m_newFacePointIdx );
firstFaceVertex.push_back(getVertex(m_faces[i].m_vertexIdxSet[(j+1)%k]).m_newVertexPointIdx );
pSubMesh->addFace(firstFaceVertex);
firstFaceVertex.clear();
}
}
this->m_pSubdivVertexes = NULL;
pSubMesh->printMeshInfo();
return pSubMesh;
}
inline void Mesh::GLSetVertex( Vector3d &v )
{
glVertex3f(v.x, v.y, v.z); //glVertex3d
}
inline void Mesh::GLSetNormal( Vector3d &v )
{
glNormal3f(v.x, v.y, v.z); //glVertex3d
}
void Mesh::render(int rtype)
{
if( rtype == Mesh::RenderVertex ) //顶点显示
{
glPointSize(4);
glColor3f(1, 1 ,100);
glBegin(GL_POINTS);
FOR_EACH_VERTEX(itr)
{
GLSetVertex(itr->m_v);
}
glEnd();
}
else if (rtype == Mesh::RenderEdge )//边显示
{
glColor3f(100, 0 ,0);
glBegin(GL_LINES);
FOR_EACH_EDGE(itr)
{
GLSetVertex((*m_pVertexes)[itr->m_bgVertexIdx].m_v);
GLSetVertex((*m_pVertexes)[itr->m_edVertexIdx].m_v);
}
glEnd();
}
else if (rtype == Mesh::RenderFace )//面显示
{
glColor3f(1, 1 ,0);
FOR_EACH_FACE(itr)
{
glBegin(GL_POLYGON);
int vnum = itr->m_vertexIdxSet.size();
for( int i = 0; i < vnum; i ++ )
{
GLSetNormal(itr->m_normal);
GLSetVertex(getVertex(itr->m_vertexIdxSet[i]).m_v);
}
glEnd();
}
}
}
void Mesh::dump() const
{
FOR_EACH_CONST_VERTEX(vitr)
{
vitr->dump();
}
FOR_EACH_CONST_EDGE(eitr)
{
eitr->dump();
}
FOR_EACH_CONST_FACE(fitr)
{
fitr->dump();
}
}
void Mesh::printMeshInfo()
{
cout << "Mesh Vertexes Number:" << m_pVertexes->size() << endl;//输出顶点的个数
cout << "Mesh Edges Number:" << m_edges.size() << endl;//输出边的个数
cout << "Mesh Faces Number:" << m_faces.size() << endl;//输出面的个数
}
void Mesh::saveObjFile(CString objFile)//保存obj文件
{
CString strLine, strtemp;
CStdioFile fmesh;
if( !fmesh.Open( objFile, CFile::modeWrite | CFile::modeCreate | CFile::typeText ) )
{
AfxMessageBox("Error Open File");
}
/*strLine1.Format("%f",m_pVertexes->size());
fmesh.WriteString(strLine1);
fmesh.WriteString("\r\n");*/
FOR_EACH_VERTEX(vitr)
{
// vitr->dump();
strLine.Format("v %f %f %f", vitr->m_v.x, vitr->m_v.y, vitr->m_v.z );
fmesh.WriteString(strLine);
fmesh.WriteString("\r\n");
}
fmesh.WriteString("g \n");
FOR_EACH_FACE(fitr)
{
strLine = "f ";
for( int i = 0; i < fitr->m_vertexIdxSet.size(); i ++ )//面的顶点个数
{
strtemp.Format("%d ", fitr->m_vertexIdxSet[i]+1);
// add 1 for index base 1使面的索引基数为1
strLine += strtemp;
}
fmesh.WriteString(strLine);//写字符串文件
fmesh.WriteString("\r\n");
//cout<<m_vertexIdxSet.size()<<endl;
}
fmesh.Close();
}
// call this to each vertex before generating a new vertex-face when doing doo-sabin subdiv
// as for each vertexes this function is called and called only once,
// it should take the same time as pre-sorting in for subdiv-calculation...
// sort the face index of vertex vi clockwisely!
// Needs only one known adj-face.(by taking care of this, optimism is possible!)
void Mesh::sortVertexAdjFace(int vi)
{
// should check before call this function
if((*m_pVertexes)[vi].m_adjFaceIdxSet.size() <= 0)
return;
// ASSERT((*m_pVertexes)[vi].m_adjFaceIdxSet.size() > 0);
// (*m_pVertexes)[vi].dump(); // dump before sort
vector<int> sortedAdjFaceIdxSet;
int ofi = (*m_pVertexes)[vi].m_adjFaceIdxSet[0];
int fi = (*m_pVertexes)[vi].m_adjFaceIdxSet[0];
do
{
sortedAdjFaceIdxSet.push_back(fi); // clockwise!
// find the vertex_vi's idx in face's m_vertexIdxSet, then the edge
// start from vertex_vi is m_faces[first].m_faceIdxSet[idx]
bool blFound = false;
for( int j = 0; j < m_faces[fi].m_vertexIdxSet.size(); j ++ )
if (m_faces[fi].m_vertexIdxSet[j] == vi)
{
blFound = true;
break;
}
ASSERT(blFound);
/*
cout << "Vertex " << vi + 1 << " 's out edge in face " << fi + 1 << " is :" << endl;
cout << " ";
m_faces[fi].m_edgePosSet[j]->dump();
cout << " ";
m_faces[fi].dump();
*/
m_faces[fi].dump();
fi = getAdjFace( fi, *(m_faces[fi].m_edgePosSet[j]) );
}
while( ofi != fi && fi != -1);
(*m_pVertexes)[vi].m_adjFaceIdxSet = sortedAdjFaceIdxSet;
// (*m_pVertexes)[vi].dump(); // dump after sort
}
typedef struct{
int a,b,c;
}polygon_type;
bool Mesh::loadObjFile(CString fname)//加载obj文件
{
// check file validity
if( fname.Find(".obj") == -1 )
return false;
CString strLine;
CStdioFile fmesh;
char type[4];
if( !fmesh.Open( fname, CFile::modeRead | CFile::typeText ) )
{
AfxMessageBox("Error Open File");
}
int i1, i2, i3;
float f1, f2, f3;
int vcount = 0;
while( fmesh.ReadString(strLine) )
{
//int nnn;
//nnn=strLine.GetLength();
strLine.TrimRight();//删除右边部分
//nnn=strLine.GetLength();
if(strLine.GetLength() < 2)
continue;
sscanf(strLine, "%3s", type);
if(type[1] != 0 || !(type[0] == 'f' || type[0] == 'v'))
// type[0] == 0: sscanf stop when meeting any ' ' and patch '\0' to type
continue;
else if(type[0] == 'v')
{
vcount ++;
sscanf(strLine.Mid(2), "%f %f %f", &f1, &f2, &f3);
this->addVertex(f1, f2, f3);
cout << "vertex: " << f1 << " " << f2 << " " << f3 << endl;
}
else if(type[0] == 'f')
{
vector<int> vectVertex;
int i1, i = 2, j;
cout << "face: ";
while( i < strLine.GetLength() )
{
j = strLine.Find(' ',i);
if( j == -1) j = strLine.GetLength();
sscanf(strLine.Mid(i,j-i), "%d", &i1);
cout <<i1<<" " ; //i1
vectVertex.push_back(i1 - 1);
// vector index base 0 while obj index base 1
i = j + 1;
}
cout << endl;
this->addFace(vectVertex);
}
}
fmesh.Close();
printMeshInfo();
return true;
}
bool Mesh::load3dsFile(CString p_filename)
{
int i; //Index variable
FILE *l_file; //File pointer
unsigned short l_chunk_id; //Chunk identifier
unsigned int l_chunk_lenght; //Chunk lenght
vector<int> fvs;
unsigned char l_char; //Char variable
unsigned short l_qty; //Number of elements in each chunk
unsigned short l_face_flags; //Flag that stores some face information
if ((l_file=fopen (p_filename, "rb"))== NULL) return false; //Open the file
while (ftell (l_file) < filelength (fileno (l_file))) //Loop to scan the whole file
{
//getche(); //Insert this command for debug (to wait for keypress for each chuck reading)
fread (&l_chunk_id, 2, 1, l_file); //Read the chunk header
printf("ChunkID: %x\n",l_chunk_id);
fread (&l_chunk_lenght, 4, 1, l_file); //Read the lenght of the chunk
printf("ChunkLenght: %x\n",l_chunk_lenght);
switch (l_chunk_id)
{
//----------------- MAIN3DS -----------------
// Description: Main chunk, contains all the other chunks
// Chunk ID: 4d4d
// Chunk Lenght: 0 + sub chunks
//-------------------------------------------
case 0x4d4d:
break;
//----------------- EDIT3DS -----------------
// Description: 3D Editor chunk, objects layout info
// Chunk ID: 3d3d (hex)
// Chunk Lenght: 0 + sub chunks
//-------------------------------------------
case 0x3d3d:
break;
//--------------- EDIT_OBJECT ---------------
// Description: Object block, info for each object
// Chunk ID: 4000 (hex)
// Chunk Lenght: len(object name) + sub chunks
//-------------------------------------------
case 0x4000:
i=0;
do
{
fread (&l_char, 1, 1, l_file);
//p_object->name[i]=l_char;
i++;
}while(l_char != '\0' && i<20);
break;
//--------------- OBJ_TRIMESH ---------------
// Description: Triangular mesh, contains chunks for 3d mesh info
// Chunk ID: 4100 (hex)
// Chunk Lenght: 0 + sub chunks
//-------------------------------------------
case 0x4100:
break;
//--------------- TRI_VERTEXL ---------------
// Description: Vertices list
// Chunk ID: 4110 (hex)
// Chunk Lenght: 1 x unsigned short (number of vertices)
// + 3 x float (vertex coordinates) x (number of vertices)
// + sub chunks
//-------------------------------------------
case 0x4110:
float vx, vy, vz;
fread (&l_qty, sizeof (unsigned short), 1, l_file);
printf("Number of vertices: %d\n",l_qty);
for (i=0; i<l_qty; i++)
{
fread (&vx, sizeof(float), 1, l_file);
fread (&vy, sizeof(float), 1, l_file);
fread (&vz, sizeof(float), 1, l_file);
this->addVertex(vx, vy, vz);
//cout << "vertex" << i << " :" << vx << " " << vy << " " << vz << endl;
}
break;
//--------------- TRI_FACEL1 ----------------
// Description: Polygons (faces) list
// Chunk ID: 4120 (hex)
// Chunk Lenght: 1 x unsigned short (number of polygons)
// + 3 x unsigned short (polygon points) x (number of polygons)
// + sub chunks
//-------------------------------------------
case 0x4120:
fread (&l_qty, sizeof (unsigned short), 1, l_file);
printf("Number of polygons: %d\n",l_qty);
for (i=0; i<l_qty; i++)
{
unsigned short i1, i2, i3;
fread (&i1, sizeof (unsigned short), 1, l_file); // !!!! unsigned short !!! NOT int!!
fvs.push_back(i1);
fread (&i2, sizeof (unsigned short), 1, l_file); // !!!! unsigned short !!! NOT int!!
fvs.push_back(i2);
fread (&i3, sizeof (unsigned short), 1, l_file); // !!!! unsigned short !!! NOT int!!
fvs.push_back(i3);
this->addFace(fvs);
//cout << "face " << i << " :" << i1 << " " << i2 << " " << i3 << endl;
fread (&l_face_flags, sizeof (unsigned short), 1, l_file);
fvs.clear();
// printf("Face flags: %x\n",l_face_flags);
}
break;
//------------- TRI_MAPPINGCOORS ------------
// Description: Vertices list
// Chunk ID: 4140 (hex)
// Chunk Lenght: 1 x unsigned short (number of mapping points)
// + 2 x float (mapping coordinates) x (number of mapping points)
// + sub chunks
//-------------------------------------------
case 0x4140:
fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
/* fread (&l_qty, sizeof (unsigned short), 1, l_file);
for (i=0; i<l_qty; i++)
{ // Mapping list u, v
float u,v;
fread (&u, sizeof (float), 1, l_file);
fread (&v, sizeof (float), 1, l_file);
}*/
break;
//----------- Skip unknow chunks ------------
//We need to skip all the chunks that currently we don't use
//We use the chunk lenght information to set the file pointer
//to the same level next chunk
//-------------------------------------------
default:
fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
}
}
fclose (l_file); // Closes the file stream
return (true); // Returns ok
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -