#include "stdafx.h"
#include <gtest/gtest.h>
#include <fstream>
#include <math.h>
#include <algorithm>
#include <iostream>
#include "..\TestServer\FileHelper.h"
#include "Algorithm/algsimplifier.h"
#include "algqemsimplifier.h"
#include "Geometry/Plane.h"
#include "Algorithm/algTriMeshSegm.h"
#include "gmath/GBox3.h"
// coe = 4*1.732*w/(a*a + b*b + c*c) :其中w代表面积,a,b,c代表边长,coe 的结果1表示等边三角形,0表示边重合
// 狭长三角形系数 coe 的边界值
#define COE_MIN_LONG_TRIANGLE 0.1
// 两个面片法线夹角的最大值
#define MAX_ANGLE 3.1415926
// 简化比允许的上下波动
#define FLUCT_RATIO 0.02
// 计算两个网格模型距离平均值时选取的顶点数的比率
#define DIS_NUM_RATIO 0.1
// 计算两个网格模型距离平均值的边界值
#define DIS_MAX 1.0
typedef CVec3<double> point;
typedef CBox3<double> ptrBox;
// 简化后网格模型文件名标识
string SimSign("_simply");
class mesh_vertex;
class mesh_face;
class tri_mesh;
typedef set<mesh_face*, ggp::dereference_functor_less> FaceSet;
// 类表示网格模型的点
class mesh_vertex
{
public:
// 默认构造函数
mesh_vertex(bool inisPatch = false):isPatch(inisPatch){}
// 坐标
point pt;
// 顶点是否加入了分割
bool isPatch;
// 与顶点相连的面
FaceSet p_face;
friend class tri_mesh;
};
// 类表示网格模型的面
class mesh_face
{
public:
// 对应的顶点号
size_t vertices[3];
// 顶点的纹理坐标
CVector2d textcoord[3];
//重载“<”操作符,自定义排序规则
bool operator < (const mesh_face &f) const
{
//按vertices从小到大排列
return (vertices[0] < f.vertices[0]) ||
(vertices[0] == f.vertices[0] && vertices[1] < f.vertices[1]) ||
(vertices[0] == f.vertices[0] && vertices[1] == f.vertices[1] && vertices[2] < f.vertices[2]);
}
friend class tri_mesh;
};
// 类表示三角网格
class tri_mesh
{
public:
// 获得pos位置的面
mesh_face getFace(size_t pos);
vector<mesh_vertex*> VertexList;
FaceSet FaceList;
};
// 获得 tri_mesh 中某个位置的面
mesh_face tri_mesh::getFace(size_t pos)
{
FaceSet::iterator it = FaceList.begin();
int i = 0;
while(i < pos)
{
it ++;
i ++;
}
return **it;
}
// 读取网格文件中的面和点,网格文件类型为 .ply ,成功返回 true
bool ReadMeshFromFilePly(string mesh_path, tri_mesh & mesh)
{
ifstream infile(mesh_path);
string line, str;
int num_vertex = -1, num_face = -1;
//读取点和面的数量
while(getline(infile, line))
{
stringstream s_line(line);
if(s_line >> str )
{
if(str == "element" && s_line >> str)
{
if(str == "vertex" && s_line >> str)
num_vertex = stoi(str);
if(str == "face" && s_line >> str)
{
num_face = stoi(str);
break;
}
}
}
}
if(num_vertex == -1 || num_face == -1)
return false;
while(getline(infile, line))
{
if(line == "end_header")
break;
}
int i = 0;
// 读取点和面
while(i < num_vertex && getline(infile, line))
{
mesh_vertex * mem = new mesh_vertex;
stringstream s_line(line);
// 读取顶点坐标,如果有方向的话,读取方向
if(! (s_line >> mem->pt.X >> mem->pt.Y >> mem->pt.Z))
return false;
mesh.VertexList.push_back(mem);
i ++;
}
i = 0;
while(i < num_face && getline(infile, line))
{
mesh_face * mem = new mesh_face;
std::stringstream s_line(line);
// 面中顶点个数
size_t num_v;
s_line >> num_v;
// 读取面的顶点号
for(int j = 0; j < 3; j++)
{
if(! (s_line >> mem->vertices[j]))
return false;
}
// 面的纹理坐标个数
size_t num_vt;
s_line >> num_vt;
// 读取面的顶点的纹理坐标(假如含有纹理坐标)
for(int j = 0; j < 3; j++)
s_line >> mem->textcoord[j][0] >> mem->textcoord[j][1];
mesh.FaceList.insert(mem);
i ++;
}
int m1 = mesh.VertexList.size(), m2 = mesh.FaceList.size();
if(m1 != num_vertex)
{
for(size_t i = 0; i < m1; i ++)
delete mesh.VertexList[i];
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
delete *it;
return false;
}
infile.close();
size_t pos = 0;
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
{
for(int j = 0; j < 3; j++)
mesh.VertexList[(*it)->vertices[j]]->p_face.insert(*it); // 将面号保存在顶点信息中
pos ++;
}
return true;
}
// 读取网格文件中的面和点,网格文件类型为 .obj ,成功返回 true
bool ReadMeshFromFileObj(string mesh_path, tri_mesh & mesh)
{
// 为方便计算,使vec_vertex从第二个元素开始有效
mesh_vertex * temp = new mesh_vertex;
mesh.VertexList.push_back(temp);
vector<CVector2d> vec_text; // 临时保存纹理坐标
ifstream infile(mesh_path);
string line;
// 读取点的数据
while(getline(infile, line))
{
string str;
stringstream s_line(line);
s_line >> str;
if(str == "v")
{
// 读取顶点坐标
mesh_vertex * mem = new mesh_vertex;
if( ! (s_line >> mem->pt.X >> mem->pt.Y >> mem->pt.Z))
return false;
mesh.VertexList.push_back(mem);
}
if(str == "vt")
{
CVector2d textcoord;
s_line >> textcoord[0] >> textcoord[1];
vec_text.push_back(textcoord);
}
if(str == "f")
{
mesh_face * mem = new mesh_face;
for(int j = 0; j < 3; j++)
{
string str_f;
if( ! (s_line >> str_f))
return false;
string str_v, str_vt;
// 读取面的顶点号
if(str_f.find("/") != string::npos)
{
str_vt = str_f.substr(str_f.find_first_of("/") + 1, str_f.find_last_of("/"));
str_v = str_f.substr(0, str_f.find_first_of("/"));
}
else
str_v = str_f;
size_t v = stoi(str_v);
mem->vertices[j] = v;
// 读取面的顶点的纹理坐标
if(str_vt != "")
{
size_t n_vt = stoi(str_vt);
mem->textcoord[j] = vec_text[n_vt - 1];
}
}
mesh.FaceList.insert(mem);
}
}
int m1 = mesh.VertexList.size(), m2 = mesh.FaceList.size();
infile.close();
size_t pos = 0;
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
{
for(int j = 0; j < 3; j++)
mesh.VertexList[(*it)->vertices[j]]->p_face.insert(*it); // 将面号保存在顶点信息中
pos ++;
}
return true;
}
// 读取网格文件中的面和点,成功返回 true
bool ReadMeshFromFile(string mesh_path, tri_mesh & mesh)
{
string type = mesh_path.substr(mesh_path.find_last_of("."), mesh_path.size() - mesh_path.find_last_of("."));
if(type == ".obj")
return ReadMeshFromFileObj(mesh_path, mesh);
if(type == ".ply")
return ReadMeshFromFilePly(mesh_path, mesh);
return true;
}
// 判断两个网格模型空间之间的距离属性,mesh1:简化前,mesh2:简化后。返回 num 个点距离平方的平均值
double GetDisSquareOfTwoMesh(tri_mesh & mesh1, tri_mesh & mesh2, size_t num)
{
double dissquare = 0.0;
if(num == 0)
return dissquare;
// 每隔per个点取 mesh2 中的一个点
size_t per;
if(num > mesh2.VertexList.size())
per = 1;
else
per = mesh2.VertexList.size()/num;
// 找到对应的距离最小的点
int i = 0, pos = 0;
while(pos < mesh2.VertexList.size())
{
i ++;
if(i == per + 1)
i = 0;
if(i != per)
{
pos ++;
continue;
}
// 循环找到 vec_vertex1 中距离该点最近距离的点(为简化计算,用x+y+z的值来找最近点)
double dis = mesh1.VertexList[0]->pt.SqrDistanceTo(mesh2.VertexList[pos]->pt);
for(size_t j = 1; j < mesh1.VertexList.size(); j++)
{
double new_dis = mesh1.VertexList[j]->pt.SqrDistanceTo(mesh2.VertexList[pos]->pt);
if(dis > new_dis)
{
if(new_dis < 1e-6)
int o = 10;
dis = new_dis;
}
}
// 将距离平方加入到 dissquare 中
dissquare += dis;
pos ++;
}
cout<<"两个网格模型距离:"<<dissquare/num<<endl;
return dissquare/num;
}
// 获得三角形的面积(海伦-秦九公式),已知一个面的三个顶点,a,b,c分别为边长
double GetTriangleArea(tri_mesh & mesh, const mesh_face & face, double & a, double & b, double &c)
{
point pt1, pt2, pt3;
pt1 = mesh.VertexList[face.vertices[0]]->pt;
pt2 = mesh.VertexList[face.vertices[1]]->pt;
pt3 = mesh.VertexList[face.vertices[2]]->pt;
double p, s;
// 求三边长度
a = pt1.DistanceTo(pt2);
b = pt1.DistanceTo(pt3);
c = pt2.DistanceTo(pt3);
p = (a + b + c) / 2;
// 求面积
s = sqrt(p*(p - a)*(p - b)*(p - c));
return s;
}
// 计算两个向量的夹角
static double GetAngleOfTwoDir(const point& v1, const point & v2)
{
double mult = v1.Dot(v2);
double longth1 = v1.Length();
double longth2 = v2.Length();
return acos(mult / (longth1 * longth2));
}
// 通过两个点获得一个向量,vectex1 表示起点,vertex2 表示终点
static void GetVecFromVertex(const point & vertex1, const point & vertex2, point & vect)
{
vect[0] = vertex2[0] - vertex1[0];
vect[1] = vertex2[1] - vertex1[1];
vect[2] = vertex2[2] - vertex1[2];
}
// 由三角面片的三个点获得三角面片的方向
static void GetDirectOfFace(const point & vertex1, const point & vertex2, const point & vertex3, point & dir)
{
// 两个点组成的向量
point vector1, vector2;
GetVecFromVertex(vertex1, vertex2, vector1);
GetVecFromVertex(vertex2, vertex3, vector2);
// 获得两个向量的叉乘,即面片的方向
dir = vector1.Cross(vector2);
}
// 使用公式 coe = 4*1.732*w/(a*a + b*b + c*c) :其中w代表面积,a,b,c代表边长,coe 的结果1表示等边三角形,0表示边重合
int GetLongTriangleNum(tri_mesh & mesh)
{
int num = 0;
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
{
double coe, a, b, c, s;
s = GetTriangleArea(mesh, **it, a, b, c);
coe = 4 * 1.732 * s /(pow(a, 2) + pow(b, 2) + pow(c, 2));
if(coe <= COE_MIN_LONG_TRIANGLE)
{
//cout<<"狭长三角形:"<<i<<" 系数是:"<<coe<<endl;
num ++;
}
}
cout<<"狭长三角形个数:"<<num<<endl;
return num;
}
// 获得两个 mesh_face 的公共顶点个数
size_t GetCommenVertexNum(const mesh_face & face1, const mesh_face & face2, tri_mesh & mesh)
{
size_t num = 0;
for(size_t i = 0; i < 3; i ++)
{
for(size_t j = 0; j < 3; j++)
{
if(face1.vertices[i] == face2.vertices[j])
num ++;
}
}
return num;
}
// 找到三角面片 n_pos 周围相邻的面片
void FindAdjTriangle(mesh_face face, tri_mesh & mesh, FaceSet & adj_triangle)
{
for(size_t i = 0; i < 3; i ++)
{
size_t vertex_pos = face.vertices[i]; // 找到面的第i个顶点的顶点号
FaceSet & pFace = mesh.VertexList[vertex_pos]->p_face; // 第i个顶点周围的面号
for(FaceSet::iterator it = pFace.begin(); it != pFace.end(); it ++)
{
if(GetCommenVertexNum(face, **it, mesh) == 2)
adj_triangle.insert(*it);
}
}
}
// 获得面的法线
void GetUnitOfFace(mesh_face face, tri_mesh & mesh, point & dir)
{
point vertex[3];
for(size_t i = 0; i < 3; i ++)
vertex[i] = mesh.VertexList[face.vertices[i]]->pt;
GetDirectOfFace(vertex[0], vertex[1], vertex[2], dir);
}
// 判断褶皱,即判断网格模型中的三角形是否有两个三角形角度小于等于120度的情况,即两个三角形法线点乘大于0
int GetCoincideTriangleNum(tri_mesh & mesh)
{
int num = 0;
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
{
point dir1, dir2;
GetUnitOfFace(**it, mesh, dir1);
// 找到相邻的面
FaceSet adj_triangle;
FindAdjTriangle(**it, mesh, adj_triangle);
// 查找跟 vec_face[i] 有公共边的面
for(FaceSet::iterator it2 = adj_triangle.begin(); it2 != adj_triangle.end(); it2 ++)
{
GetUnitOfFace(**it2, mesh, dir2);
// 如果两个面片的方向向量点乘小于等于0.0,证明两个面片夹角小于等于180度
double angle = GetAngleOfTwoDir(dir1, dir2);
if(angle >= MAX_ANGLE)
{
num ++;
}
}
}
cout<<"褶皱面个数:"<<num<<endl;
return num;
}
// 获得拟合平面的距离误差
double GetFitPlaneCoef(ggp::UVPatch::UVPatchGeom & goems, tri_mesh & mesh, string fileType)
{
vector<CVector3d> pPtsVec;
CPlaneCoef plane_coe;
double coe;
for(size_t i = 0; i < goems.faceVertexIdxs.size(); i ++)
{
size_t vertex_id = goems.faceVertexIdxs[i];
if(fileType == ".obj")
vertex_id ++;
mesh.VertexList[vertex_id]->isPatch = true; // 点标记为加入到分割中
point & re_vetex = mesh.VertexList[vertex_id]->pt;
pPtsVec.push_back(re_vetex);
}
plane_coe.CalPlaneCoef(pPtsVec, pPtsVec.size(), coe);
return coe;
}
// 获得平均网格模型的平均边长
double GetAverSqrSideLenth(tri_mesh & mesh)
{
double sqrlength = 0.0;
int num = 0;
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
{
point pts[3];
for(size_t j = 0; j < 3; j ++)
{
size_t ver_id = (*it)->vertices[j];
pts[j] = mesh.VertexList[ver_id]->pt;
}
sqrlength += pts[0].SqrDistanceTo(pts[1]) + pts[0].SqrDistanceTo(pts[2]) + pts[1].SqrDistanceTo(pts[2]);
num += 3;
}
return sqrlength/num;
}
// 验证是否所有的平面加入了分割
bool IsAllInPatch(tri_mesh & mesh)
{
bool isAllPath = true;
for(size_t i = 0; i < mesh.VertexList.size(); i ++)
{
if(mesh.VertexList[i]->p_face.size() > 0 && ! mesh.VertexList[i]->isPatch)
return false;
}
return isAllPath;
}
// 释放内存
void FreeMesh(tri_mesh & mesh)
{
// 释放顶点
for(size_t i = 0; i < mesh.VertexList.size(); i ++)
if(mesh.VertexList[i])
delete mesh.VertexList[i];
// 释放面
for(FaceSet::iterator it = mesh.FaceList.begin(); it != mesh.FaceList.end(); it ++)
if(*it)
delete *it;
}
// 验证三角网格简化:是否能够正确获得简化模型
void SimplifyResultTest_1(string fileName, double ratio)
{
string meshPath = CFileHelper::GetFilePath(fileName, g_WhiteboxCaseSimplifyMetrics);
string fileType = fileName.substr(fileName.find_last_of("."), fileName.size() - fileName.find_last_of("."));
// 读取网格模型,并将简化的模型写入新的文件
SimConfig simSign(false, COE_MIN_LONG_TRIANGLE, cos(MAX_ANGLE));
ggp::SimMesh* simedMesh = ggp::Simplify(meshPath, ratio, simSign);
EXPECT_TRUE(simedMesh != nullptr);
// 将简化后网格模型写入文件
string sub1 = meshPath.substr(0, meshPath.find_last_of("."));
string sub2 = meshPath.substr(meshPath.find_last_of("."), meshPath.size() - meshPath.find_last_of("."));
string simplydMeshPath = sub1 + SimSign + sub2;
bool isWriteOk = ggp::EdgeCollapsor::writeTriMesh(*simedMesh, simplydMeshPath);
EXPECT_TRUE(isWriteOk);
// 读取简化前后
tri_mesh mesh1, mesh2;
ReadMeshFromFile(meshPath, mesh1);
ReadMeshFromFile(simplydMeshPath, mesh2);
// 重新计算简化比,使简化比在0.0 - 1.0
if(ratio > 1.0 + g_DistEpsilon)
{
int temp = ratio;
ratio = (double)temp/mesh1.FaceList.size();
}
if(ratio > 1.0 && ratio <= 1.0 + g_DistEpsilon)
ratio = 1.0;
EXPECT_TRUE(ratio >= 0.0 && ratio <= 1.0);
// 验证实际简化比是否正确
double f1, f2;
f1 = mesh1.FaceList.size();
f2 = mesh2.FaceList.size();
double real_ratio = f2/f1;
if(ratio < 1.0/f1)
EXPECT_TRUE(real_ratio == 0.0);
else
EXPECT_TRUE(fabs(ratio - real_ratio) <= FLUCT_RATIO);
// 验证两个网格模型距离是否正确 //-----------------------------------------------------------待修正---------------------------------
double dis = GetDisSquareOfTwoMesh(mesh1, mesh2, DIS_NUM_RATIO * mesh2.VertexList.size());
EXPECT_TRUE(dis < DIS_MAX);
//-----------------------------------------------------------待修正---------------------------------
// 折叠三角形
int CoinNum = GetCoincideTriangleNum(mesh1);
int CoinNum_Simplify = GetCoincideTriangleNum(mesh2);
EXPECT_TRUE(CoinNum_Simplify <= CoinNum);
// 狭长三角形
int LongNum = GetLongTriangleNum(mesh1);
int LongNum_Simplify = GetLongTriangleNum(mesh2);
EXPECT_TRUE(LongNum_Simplify <= LongNum);
// 验证简化后的网格模型——网格分割是否正确
double sqrLength = GetAverSqrSideLenth(mesh2);
ggp::TriMeshSegm meshSegm;
double dDistEpsilon = 0.0;
meshSegm.PartitionMesh(*simedMesh);
std::vector<ggp::UVPatch::UVPatchGeom> patchGeoms = meshSegm.ExportPatchs();
for(int i = 0; i < patchGeoms.size(); i ++)
{
dDistEpsilon = GetFitPlaneCoef(patchGeoms[i], mesh2, fileType); // 拟合平面距离误差
//cout<<dDistEpsilon<<" ";
// 验证拟合平面的距离误差是否正确
double coe_patch = dDistEpsilon /(sqrt(sqrLength) * 2);
EXPECT_TRUE(coe_patch < 10.0)<<coe_patch;
}
EXPECT_TRUE(IsAllInPatch(mesh2)); // 验证是否所有面参与了分割
// 释放内存
delete simedMesh;
FreeMesh(mesh1);
FreeMesh(mesh2);
// 删除创建的简化后网格模型文件
string delFile = (string)"del" + " " + simplydMeshPath;
system(delFile.data());
}
// 验证三角网格简化:不能正确获得简化模型
void SimplifyResultTest_2(string fileName, double ratio)
{
string meshPath = CFileHelper::GetFilePath(fileName, g_WhiteboxCaseSimplifyMetrics);
// 读取网格模型,并将简化的模型写入新的文件
ggp::SimMesh* simedMesh = ggp::Simplify(meshPath, ratio);
EXPECT_TRUE(simedMesh == nullptr);
string sub1 = meshPath.substr(0, meshPath.find_last_of("."));
string sub2 = meshPath.substr(meshPath.find_last_of("."), meshPath.size() - meshPath.find_last_of("."));
string simplydMeshPath = sub1 + "_simply" + sub2;
bool isWriteOk = ggp::EdgeCollapsor::writeTriMesh(*simedMesh, simplydMeshPath);
EXPECT_FALSE(isWriteOk);
}
//表示 文件名 和 简化比的类
struct FilenameAndRatio
{
FilenameAndRatio(string f, double r) : fileName(f), ratio(r){}
string fileName; // 文件名
double ratio; // 简化比
};
// 测试用例参数化类:获得正确的简化模型
class MeshSimplifyTest_1 : public ::testing::TestWithParam<FilenameAndRatio>
{
};
// 测试用例参数化类:不能获得正确的简化模型
class MeshSimplifyTest_2 : public ::testing::TestWithParam<FilenameAndRatio>
{
};
// 时间超长的测试用例
class LongTime_MeshSimplifyTest : public ::testing::TestWithParam<FilenameAndRatio>
{
};
// 参数化:正确简化
TEST_P(MeshSimplifyTest_1, GGP_22144)
{
FilenameAndRatio Data = GetParam();
string fileName = Data.fileName;
double ratio = Data.ratio;
SimplifyResultTest_1(fileName, ratio);
}
// 参数化:不能正确简化
TEST_P(MeshSimplifyTest_2, GGP_22144)
{
FilenameAndRatio Data = GetParam();
string fileName = Data.fileName;
double ratio = Data.ratio;
SimplifyResultTest_2(fileName, ratio);
}
// 参数化:不能正确简化
TEST_P(LongTime_MeshSimplifyTest, GGP_22144)
{
FilenameAndRatio Data = GetParam();
string fileName = Data.fileName;
double ratio = Data.ratio;
SimplifyResultTest_1(fileName, ratio);
}
// 测试用例:正确简化
INSTANTIATE_TEST_CASE_P(TrueReturn, MeshSimplifyTest_1, testing::Values(// 经典网格模型
FilenameAndRatio("bunny.obj", 0.0), // /0 //v: 3508 f: 6944
FilenameAndRatio("bunny.ply", 0.5), // /1 //v: 35947 f: 69451
FilenameAndRatio("horse.ply", 1.0), // /2 //v: 48485 f: 96966
FilenameAndRatio("bunny.obj", 0.00001), // /3 //v: 3508 f: 6944
FilenameAndRatio("bunny.ply", 0.99999), // /4 //v: 35947 f: 69451
FilenameAndRatio("bunny.obj", 1.00001), // /5 //v: 3508 f: 6944
FilenameAndRatio("horse.ply", 96966 - 3), // /6 //v: 48485 f: 96966
FilenameAndRatio("horse.ply", 5), // /7 //v: 48485 f: 96966
// 离散获得的网格模型
FilenameAndRatio("annulus.ply", 0.5), // /8 //v: 64 f: 64
FilenameAndRatio("cone.ply", 0.00001), // /9 //v: 74 f: 144
FilenameAndRatio("sphere.ply", 0.99999), // /10 //v: 642 f: 1280
FilenameAndRatio("ModifyFile.obj", 0.5), // /11 //v: 642 f: 1280
// 存在往复边
FilenameAndRatio("ReciproEdge.ply", 0.5), // /12 //v: 75 f: 145
// 存在退化三角形
FilenameAndRatio("DegeTriangle.ply", 0.5), // /13 //v: 74 f: 144
// 存在重合的三角形
FilenameAndRatio("CoinTriangle.ply", 0.1), // /14 //v: 642 f: 1281
// 非流行网格模型
FilenameAndRatio("NonManifold.ply", 0.5), // /15 //v: 38 f: 67
// 存在游离的点
FilenameAndRatio("FreeVertex.obj", 0.5), // /16 //v: 3511 f: 6944
// 验证三角网分割的特殊用例
FilenameAndRatio("DesignChair.obj", 0.5), // /17 //v: 16034 f: 32064
FilenameAndRatio("Medalballfootball.obj", 0.5), // /18 //v: 23778 f: 47492
FilenameAndRatio("MedBottles.obj", 0.5), // /19 //v: 2214 f: 4396
FilenameAndRatio("StingSword.obj", 0.5) )); // /20 //v: 1329 f: 2596
// 测试用例:不能正确简化
INSTANTIATE_TEST_CASE_P(FalseReturn, MeshSimplifyTest_2, testing::Values(// 错误的简化比
FilenameAndRatio("bunny.obj", -1.0), // /0 //v: 3508 f: 6944
FilenameAndRatio("bunny.ply", -0.5), // /1 //v: 35947 f: 69451
FilenameAndRatio("horse.ply", -0.00001), // /2 //v: 48485 f: 96966
FilenameAndRatio("bunny.ply", 69451 + 3), // /3 //v: 35947 f: 69451
// 错误的模型
// 含有错误的标识符
//FilenameAndRatio("ErrorIdentifier.ply", 0.5), // /4 //v: 64 f: 64 // 卡住了
// 三角形有些点不存在
//FilenameAndRatio("InvalidVertex.ply", 0.5), // /5 //v: 642 f: 1280 // 生成了简化后网格模型,没有报错
// 0个点,0个面
FilenameAndRatio("NoVertexFace.ply", 0.5), // /6 //v: 0 f: 0
// 错误的路径
FilenameAndRatio("bunny", 0.5), // /7
FilenameAndRatio("12345543", 0.5), // /8
FilenameAndRatio("bunny\\bunny.obj", 0.5) )); // /9
// 运行超长时间的测试用例
//INSTANTIATE_TEST_CASE_P(LongTime, LongTime_MeshSimplifyTest, testing::Values(// 运行时间较长的用例
//
// FilenameAndRatio("Armadillo.ply", 0.9), // /0 //v: 172974 f: 345944
// FilenameAndRatio("blade.ply", 441477), // /1 //v: 882954 f: 1765388
// FilenameAndRatio("dragon_vrip.ply", 0.9), // /2 //v: 437645 f: 871414
// FilenameAndRatio("hand.ply", 0.9), // /3 //v: 327323 f: 654666
// FilenameAndRatio("happy_vrip.ply", 0.9), // /4 //v: 543652 f: 1087716
// FilenameAndRatio("sofa.obj", 0.9) )); // /5 //v: 189637 f: 379234
简化测试代码
猜你喜欢
转载自blog.csdn.net/qq_32563489/article/details/85779626
今日推荐
周排行