其他分享
首页 > 其他分享> > 从源头看Dust3d |(二)Blockmesh立方体网格建立

从源头看Dust3d |(二)Blockmesh立方体网格建立

作者:互联网

2021SC@SDUSC

Part1:简略介绍

Blockmesh.h与blockmesh.cpp主要定义了BlockMesh类,blockmesh主要用于生成简单的立方体网格。

在BlockMesh类中,有公共变量及函数:

  1. 结构体Block
    struct Block
        {
            QVector3D fromPosition;//in QT,a 3D vector,起点
            double fromRadius;
            QVector3D toPosition;//终点
            double toRadius;
        };
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  2. 构造函数与析构函数
        BlockMesh()//构造函数
        { 
        }
    
        ~BlockMesh()//析构函数
        {
            delete m_resultVertices;
            delete m_resultQuads;
            delete m_resultFaces;
        }
        
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  3. 获得立方体网格的顶点和面的函数
        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;
        }
  4. 添加立方体的函数
    //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);
        }
  5. 建立立方体的函数

私有变量及函数:

  1. 三个指针: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;
        //指针
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  2. vector m_blocks,存放Block型的元素
    std::vector<Block> m_blocks;
        //容器,放block型的元素
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  3. 函数buildBlock:建立立方体网格的函数
  4. 函数buildFace:创建面
  5. 函数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]});
    }
}

 

 

 

标签:std,Blockmesh,startDirection,网格,vector,QVector3D,Dust3d,resultVertices,block
来源: https://blog.csdn.net/weixin_46273149/article/details/120640449