2021SC@SDUSC
Part1:简略介绍
Blockmesh.h与blockmesh.cpp主要定义了BlockMesh类,blockmesh主要用于生成简单的立方体网格。
在BlockMesh类中,有公共变量及函数:
- 结构体Block
struct Block { QVector3D fromPosition;//in QT,a 3D vector,起点 double fromRadius; QVector3D toPosition;//终点 double toRadius; };
- 构造函数与析构函数
BlockMesh()//构造函数 { } ~BlockMesh()//析构函数 { delete m_resultVertices; delete m_resultQuads; delete m_resultFaces; }
- 获得立方体网格的顶点和面的函数
std::vector<QVector3D> *takeResultVertices() { std::vector<QVector3D> *resultVertices = m_resultVertices; m_resultVertices = nullptr; return resultVertices; } std::vector<std::vector<size_t>> *takeResultFaces() { std::vector<std::vector<size_t>> *resultFaces = m_resultFaces; m_resultFaces = nullptr; return resultFaces; }
- 添加立方体的函数
//addBlock(起点,起点半径,终点,终点半径) void addBlock(const QVector3D &fromPosition, double fromRadius, const QVector3D &toPosition, double toRadius) { Block block; block.fromPosition = fromPosition; block.fromRadius = fromRadius; block.toPosition = toPosition; block.toRadius = toRadius; m_blocks.push_back(block); }
- 建立立方体的函数
私有变量及函数:
- 三个指针:m_resultVertices、m_resultFaces、m_resultQuads,分别存放最终的顶点、面和网格
std::vector<QVector3D> *m_resultVertices = nullptr; std::vector<std::vector<size_t>> *m_resultFaces = nullptr; std::vector<std::vector<size_t>> *m_resultQuads = nullptr; //指针
- vector m_blocks,存放Block型的元素
std::vector<Block> m_blocks; //容器,放block型的元素
- 函数buildBlock:建立立方体网格的函数
- 函数buildFace:创建面
- 函数calculateStartDirection:找到startDirection
Part2:具体分析
在Blockmesh中,我认为最重要的是buildFace、buildBlock和build函数,同时,在分析这三个函数之前,理解calculateStartDirection函数也是至关重要的。
1.calculateStartDirection函数
calculateStartDirection函数以direction为参数,找到垂直于direction与某一非与它角度最小的坐标轴所在平面的向量——startDirection
QVector3D BlockMesh::calculateStartDirection(const QVector3D &direction)
{
const std::vector<QVector3D> axisList = {
QVector3D {1, 0, 0},
QVector3D {0, 1, 0},
QVector3D {0, 0, 1},
};
//坐标系
float maxDot = -1;
size_t nearAxisIndex = 0;
//size_t:undefined integer
bool reversed = false;
for (size_t i = 0; i < axisList.size(); ++i) {
const auto axis = axisList[i];
auto dot = QVector3D::dotProduct(axis, direction);
//direction分别与三个方向点乘,也就是分别得到了direction的x、y、z坐标值
auto positiveDot = std::abs(dot);
//绝对值,positiveDot是正数
if (positiveDot >= maxDot) {
reversed = dot < 0;
//reversed表示direction的x、y、z是否为负数,若为负数,reversed为1;否则为0
maxDot = positiveDot;
nearAxisIndex = i;
}
}
//maxDot是三个坐标中绝对值最大的,nearAxisIndex是和direction角度最小的坐标轴
const auto& choosenAxis = axisList[(nearAxisIndex + 1) % 3];
//找了一个和direction最接近90度角的?
auto startDirection = QVector3D::crossProduct(direction, choosenAxis).normalized();
//startDirection垂直于direction和choosenAxis
return reversed ? -startDirection : startDirection;
}
2.buildFace函数
buildFace函数返回的是vector face,在对face进行push_back时,添加的是指针指向的元素,因此在后面对m_resultVertices进行push_back时,face中的元素也会发生改变。
即:face中的就是以origin为原点、向upDirection、startDirection的正向反向延伸所得到的四个向量,且buildFace最后产生的面的法向量就是faceNormal。
std::vector<size_t> BlockMesh::buildFace(const QVector3D &origin,
const QVector3D &faceNormal,
const QVector3D &startDirection,
double radius)
{
std::vector<size_t> face;
face.push_back(m_resultVertices->size() + 0);
face.push_back(m_resultVertices->size() + 1);
face.push_back(m_resultVertices->size() + 2);
face.push_back(m_resultVertices->size() + 3);
auto upDirection = QVector3D::crossProduct(startDirection, faceNormal);
//upDirection与startDirection、faceNormal均成90度
m_resultVertices->push_back(origin + startDirection * radius);
m_resultVertices->push_back(origin - upDirection * radius);
m_resultVertices->push_back(origin - startDirection * radius);
m_resultVertices->push_back(origin + upDirection * radius);
//以origin为原点,向upDirection、startDirection的正向反向延伸
return face;
}
3.buildBlock函数
void BlockMesh::buildBlock(const Block &block)
{
QVector3D fromFaceNormal = (block.toPosition - block.fromPosition).normalized();
QVector3D startDirection = calculateStartDirection(-fromFaceNormal);
std::vector<size_t> fromFaces = buildFace(block.fromPosition,
-fromFaceNormal, startDirection, block.fromRadius);
std::vector<size_t> toFaces = buildFace(block.toPosition,
-fromFaceNormal, startDirection, block.toRadius);
//buildFace(const QVector3D &origin, const QVector3D &faceNormal, const QVector3D &startDirection, double radius)
//以fromPosition和toPosition为原点建立两个面,且两个面平行
m_resultQuads->push_back(fromFaces);
for (size_t i = 0; i < fromFaces.size(); ++i) {
size_t j = (i + 1) % fromFaces.size();
m_resultQuads->push_back({fromFaces[j], fromFaces[i], toFaces[i], toFaces[j]});
//fromfaces、tofaces中存放的是点坐标(向量),相当于四个点一个面
}
std::reverse(toFaces.begin(), toFaces.end());
m_resultQuads->push_back(toFaces);
}
4.block函数
void BlockMesh::build()
{
delete m_resultVertices;
m_resultVertices = new std::vector<QVector3D>;
delete m_resultQuads;
m_resultQuads = new std::vector<std::vector<size_t>>;
for (const auto &block: m_blocks)//block is m_blocks引用,m_blocks随block改而改
buildBlock(block);
delete m_resultFaces;
m_resultFaces = new std::vector<std::vector<size_t>>;
m_resultFaces->reserve(m_resultQuads->size() * 2);
for (const auto &quad: *m_resultQuads) {
m_resultFaces->push_back({quad[0], quad[1], quad[2]});
m_resultFaces->push_back({quad[2], quad[3], quad[0]});
}
}