概述
本教程提供了使用多边形网格进行细分曲面建模的基本用法,细分建模一般通过从创建一个基本体开始,通过拉伸,变换,细分等生成一个曲面的的稠密网格近似。
构建基本体
模块支持构建多种基本体,构建一个边长为3,每方向分割2段的立方体代码如下。
Class of PolyMesh API for make a cube
定义 MeshMakeCube.hpp:15
Class of TMSpline structure The Low Level API functions are not exported for this version
定义 PolyMesh.hpp:23
FrameT< double, 3 > Frame3
三维标架
定义 FrameT.hpp:885
构建一个底面半径为4,上面半径为2,高为4的圆台可以使用圆锥的提供的函数,默认沿着旋转方向分割8段,沿着高的方向分割4段。
Class of PolyMesh API for make a cone
定义 MeshMakeCone.hpp:15
构建一个漩涡模型
模型预览
本教程使用简单的漩涡模型展示细分建模模块中的一些主要建模功能。模型如下图所示:
漩涡模型
命名空间
为了示例代码清晰,使用命名空间
AMCAX SubD 模块提供的所有接口所在的命名空间。
定义 misc.docu:63
AMCAX 内核提供的所有接口所在的命名空间。
定义 misc.docu:8
构建底面
从构建一个平面开始。
MeshMakeRectangle mkRect(frame, 3, 3, 3, 3);
PolyMesh* mesh = mkRect.BuildMesh();
点击这里example1可获得以上示例完整源码,大家根据学习需要自行下载。
拉伸面和变换
拉伸中间的面形成一个峰,注意执行拉伸函数仅修改网格拓扑,没有移动任何元素的位置。
std::vector<int> face_id = {4};
std::vector<int> face_id_new;
MeshExtrude::ExtrudeFace(mesh, face_id, face_id_new);
施加平移和旋转的变换将新生成的面移动到指定位置。
MeshTransform trsfF;
trsfF.SetTransformation(trsfMove);
trsfF.TransformMeshFaces(mesh, face_id_new);
trsfF.SetTransformation(trsfRot);
trsfF.TransformMeshFaces(mesh, face_id_new);
constexpr const CoordType & Coord() const noexcept
获取方向的内在坐标
定义 DirectionT.hpp:213
constexpr const DirectionT< Scalar, DIM > & Direction() const noexcept
获取三维主方向(z 方向)
定义 FrameT.hpp:441
AxisT< double, 3 > Axis3
三维轴
定义 AxisT.hpp:423
TransformationT< double, 3 > Transformation3
三维变换
定义 TransformationT.hpp:1102
VectorT< double, 3 > Vector3
三维向量
定义 VectorT.hpp:707
DirectionT< double, 3 > Direction3
三维方向
定义 DirectionT.hpp:587
PointT< double, 3 > Point3
三维点
定义 PointT.hpp:459
点击这里example2可获得以上示例完整源码,大家根据学习需要自行下载。
删除顶面
可以自由删除任意数目的面并留下洞。
MeshReduce::DeleteFaces(mesh, face_id_new);
点击这里example3可获得以上示例完整源码,大家根据学习需要自行下载。
拉伸边和变换
将删除面留下的边向四周拉伸从而生成新的顶面,先执行拉伸操作,然后施加缩放变换将新生成的边移动到指定位置。
std::vector<int> edgeid;
std::vector<int> edge_id_new;
for (int i = 0; i < mesh->numEdges(); ++i)
{
if (MeshCheck::IsEdgeBoundary(mesh, i))
{
int v0, v1;
MeshTool::EdgeVertexIndexs(mesh, i, v0, v1);
Point3 pv0 = MeshTool::Position(mesh, v0);
Point3 pv1 = MeshTool::Position(mesh, v1);
if (pv0.
Z() > 0.9 * h && pv1.
Z() > 0.9 * h)
{
edgeid.push_back(i);
}
}
}
MeshExtrude::ExtrudeEdge(mesh, edgeid, edge_id_new);
MeshTransform trsfE;
trsfE.SetTransformation(trsfScale);
trsfE.TransformMeshEdges(mesh, edge_id_new);
constexpr const Scalar & Z() const noexcept
获取点的 z 坐标,仅在 DIM >= 3 时可用
定义 PointT.hpp:136
点击这里example4可获得以上示例完整源码,大家根据学习需要自行下载。
进行加厚
将形状加厚,从而构建出实体。
MeshOffset::ThickenMesh(mesh, 0.2);
点击这里example5可获得以上示例完整源码,大家根据学习需要自行下载。
应用面分割
对连接上下部分,变化比较剧烈的这部分的面进行分割使得结果更平滑,分割通过选择一个条边将与该边拓扑平行的所有面一分为二。
for (int i = 0; i < mesh->numEdges(); ++i)
{
int v0, v1;
MeshTool::EdgeVertexIndexs(mesh, i, v0, v1);
Point3 pv0 = MeshTool::Position(mesh, v0);
Point3 pv1 = MeshTool::Position(mesh, v1);
if (std::fabs(pv1.
Z() - pv0.
Z()) > 0.8 * h)
{
MeshSplit::SplitLoop(mesh, i);
i = 0;
}
}
点击这里example6可获得以上示例完整源码,大家根据学习需要自行下载。
设置锐边特征
可以选取一些边设置锐利程度,该值在 0-1 之间,值越大,最终形状在边这里就越锐利,该值为 1 时,最终结果中会呈现为锐利的特征边
std::vector<int> edgeidCrese;
for (int i = 0; i < mesh->numEdges(); ++i)
{
int v0, v1;
MeshTool::EdgeVertexIndexs(mesh, i, v0, v1);
Point3 pv0 = MeshTool::Position(mesh, v0);
Point3 pv1 = MeshTool::Position(mesh, v1);
{
edgeidCrese.push_back(i);
}
}
std::vector<double> creaseLevel(edgeidCrese.size(), 1.0);
MeshCreaseTool::AddCreaseEdge(mesh, edgeidCrese, creaseLevel);
auto Distance(const PointT< OtherScalar, DIM > &other) const noexcept
计算该点与其他点的欧几里得距离
定义 PointT.hpp:180
执行细分
模块提供了两种细分方式,其中 Catmull-Clark 细分支持任意网格,Loop 细分仅支持三角形网格,细分后的形状仍然可以再次编辑。
MeshSubdivideHE::CatmullClark(mesh, 3);
保存网格
本模块提供将网格保存为 OBJ 文件和 OFF 文件,可以依据需要在任意细分层级保存网格并在之后使用,此外,还支持将网格导出为 TMS 格式。
std::string fileNameOBJ = "sampleResult.obj";
PolyMeshIO::WriteMesh(fileNameOBJ, mesh);
点击这里example7可获得多边形网格细分建模示例完整源码,大家根据学习需要自行下载。
附录
下面列出了此示例的完整代码:
void MakeTornado()
{
double h = 2;
MeshMakeRectangle mkRect(frame, 3, 3, 3, 3);
PolyMesh* mesh = mkRect.BuildMesh();
std::vector<int> face_id = {4};
std::vector<int> face_id_new;
MeshExtrude::ExtrudeFace(mesh, face_id, face_id_new);
MeshTransform trsfF;
trsfF.SetTransformation(trsfMove);
trsfF.TransformMeshFaces(mesh, face_id_new);
trsfF.SetTransformation(trsfRot);
trsfF.TransformMeshFaces(mesh, face_id_new);
MeshReduce::DeleteFaces(mesh, face_id_new);
std::vector<int> edgeid;
std::vector<int> edge_id_new;
for (int i = 0; i < mesh->numEdges(); ++i)
{
if (MeshCheck::IsEdgeBoundary(mesh, i))
{
int v0, v1;
MeshTool::EdgeVertexIndexs(mesh, i, v0, v1);
Point3 pv0 = MeshTool::Position(mesh, v0);
Point3 pv1 = MeshTool::Position(mesh, v1);
if (pv0.
Z() > 0.9 * h && pv1.
Z() > 0.9 * h)
{
edgeid.push_back(i);
}
}
}
MeshExtrude::ExtrudeEdge(mesh, edgeid, edge_id_new);
MeshTransform trsfE;
trsfE.SetTransformation(trsfScale);
trsfE.TransformMeshEdges(mesh, edge_id_new);
MeshOffset::ThickenMesh(mesh, 0.2);
for (int i = 0; i < mesh->numEdges(); ++i)
{
int v0, v1;
MeshTool::EdgeVertexIndexs(mesh, i, v0, v1);
Point3 pv0 = MeshTool::Position(mesh, v0);
Point3 pv1 = MeshTool::Position(mesh, v1);
if (std::fabs(pv1.
Z() - pv0.
Z()) > 0.8 * h)
{
MeshSplit::SplitLoop(mesh, i);
i = 0;
}
}
std::vector<int> edgeidCrese;
for (int i = 0; i < mesh->numEdges(); ++i)
{
int v0, v1;
MeshTool::EdgeVertexIndexs(mesh, i, v0, v1);
Point3 pv0 = MeshTool::Position(mesh, v0);
Point3 pv1 = MeshTool::Position(mesh, v1);
{
edgeidCrese.push_back(i);
}
}
std::vector<double> creaseLevel(edgeidCrese.size(), 1.0);
MeshCreaseTool::AddCreaseEdge(mesh, edgeidCrese, creaseLevel);
MeshSubdivideHE::CatmullClark(mesh, 3);
std::string fileNameOBJ = "sampleResult.obj";
PolyMeshIO::WriteMesh(fileNameOBJ, mesh);
delete mesh;
}
Class of PolyMesh check Tool
Class of PolyMesh API for extrude method
Class of PolyMesh API for make a plane rectangle
Class of PolyMesh API for Thicken a Mesh
Class of PolyMesh API for Reduce a Mesh
Class of PolyMesh API for split mesh
多边形网格接口中的网格细分类,它使用半边数据结构来修改网格