我爱科学_我爱语言_我爱文化 2023-03-27 21:23 采纳率: 0%
浏览 9

朋友写的映射算法,把mesh的z值改了。把3d模型绘制成2d模型。但绘制出的模型有瑕疵。不知道如何改善这个瑕疵

//映射算法核心部分
void Model::mapping()
{
    // 保存该点坐标的临时变量
    std::vector<float> points(3);

    int mesh_num = m_meshes.size();
    for(int mesh_idx = 0; mesh_idx < mesh_num; ++ mesh_idx)
    {
        // 当前 mesh 中顶点的数量
        int cur_mesh_size = m_meshes[mesh_idx].m_vertices.size();

        // 获取每一行顶点坐标
        for(int vertex_idx = 0; vertex_idx < cur_mesh_size; ++ vertex_idx)
        {
               points[0] = m_meshes[mesh_idx].m_vertices[vertex_idx].Position.x();
               points[1] = m_meshes[mesh_idx].m_vertices[vertex_idx].Position.y();
               points[2] = m_meshes[mesh_idx].m_vertices[vertex_idx].Position.z();

               // 对 x, y, z 进行标准化
               for(int i = 0; i < 3; i ++ )
               {
                   //normalization
                   points[i] -= (m_max_coord[mesh_idx][i] + m_min_coord[mesh_idx][i]) / 2.0f;
                   points[i] /= m_max_coord[mesh_idx][i] - m_min_coord[mesh_idx][i];
               }

               // 坐标系的 y, z 在 obj 里是相反的
               if(m_max_coord[mesh_idx][2] - m_min_coord[mesh_idx][2] > m_max_coord[mesh_idx][1] - m_min_coord[mesh_idx][1])
               {
                   std::swap(points[1], points[2]);
               }

               //做二维映射
               for(int i = 0; i < 3; i ++)
               {
                   if(i == 0)
                   {
                       points[i] = (PI + std::atan2(points[2], points[0])) / (static_cast<float>(PI) * 2);
                       m_meshes[mesh_idx].m_vertices[vertex_idx].Position.setX(points[i]);
                   }
                   else if(i == 1)
                   {
                       points[i] = (1 + points[1]) / 2;
                       m_meshes[mesh_idx].m_vertices[vertex_idx].Position.setY(points[i]);
                   }
                   else
                   {
                        points[i] = 1.0;
                        m_meshes[mesh_idx].m_vertices[vertex_idx].Position.setZ(points[i]);
                   }
               }
        }
    }
}

.h文件

//.h文件
#ifndef TRANSFORMTOIMAGE
#define TRANSFORMTOIMAGE
#define STB_IMAGE_IMPLEMENTATION

#define PI 3.141593
#define VERTEX_NUM 3
#define TEXTURE_VERTEX_NUM 3
#define INDEX_NUM 2

#define LOG_VARIABLE(info, x) std::cout<<"[ "<<info" ]  "<<x<<std::endl
#define LOG_TEXT(text) std::cout<<text<<std::endl

#include <glad/glad.h> 

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

#include "mesh.h"
#include "shader_m.h"
#include "camera.h"

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>

const float INF = 999.0;

class TransformToImage
{
public:
	TransformToImage() = default;
	~TransformToImage();

	// TransformToImage(std::vector<Vertex> vertices, std::vector<unsigned int> indices, std::vector<Texture> textures);
	TransformToImage(std::vector<Mesh> meshed);

	void transform();

	std::vector<Mesh> get_meshes() { return this->m_meshes; }

	void set_matrics(Shader shader, Camera camera);         // 变换矩阵

	void *get_data();

	void draw_texture(Shader& shader, Camera& camera);

protected:
	void get_bounding_box();	// 获取包围盒参数
	void mapping();				// 实施二维映射
	void create_framebuffer();  // 创建帧缓冲

private:
	std::vector<Mesh>    m_meshes;
	std::vector<std::vector<float>> m_max_coord;
	std::vector<std::vector<float>> m_min_coord;
	unsigned int FBO;
	unsigned int RBO;
	unsigned int texture_2D;
	float* data;
};

#endif

.cpp文件

#include "transform_to_image.h"


TransformToImage::TransformToImage(std::vector<Mesh> meshes)
{
    this->m_meshes = meshes;

    int meshes_size = meshes.size();
    this->m_max_coord.resize(meshes_size);
    this->m_min_coord.resize(meshes_size);

    // 初始化每个网格的包围盒初值
    for (int mesh_idx = 0; mesh_idx < meshes_size;  ++ mesh_idx)
    {
        for (int i = 0; i < VERTEX_NUM; ++i)
        {
            this->m_max_coord[mesh_idx].push_back(-INF);
            this->m_max_coord[mesh_idx].push_back(-INF);
            this->m_max_coord[mesh_idx].push_back(-INF);

            this->m_min_coord[mesh_idx].push_back(INF);
            this->m_min_coord[mesh_idx].push_back(INF);
            this->m_min_coord[mesh_idx].push_back(INF);
        }
    }

    LOG_TEXT("initialization succeed");
}

TransformToImage::~TransformToImage()
{
    // delete[] data;
}

void TransformToImage::transform()
{
    // 计算三维包围盒
    this->get_bounding_box();

    // 二维映射
    this->mapping();
}

void TransformToImage::draw_texture(Shader& shader, Camera& camera)
{
    glClearColor(0.05f, 0.05f, 0.05f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /// 设置变换矩阵
    set_matrics(shader, camera);

    /// 创建 FBO
    create_framebuffer();

    ///渲染
    int mesh_size = m_meshes.size();
    for (int mesh_idx = 0; mesh_idx < mesh_size; ++mesh_idx)
    {
        /// 设置好 mesh 参数
        m_meshes[mesh_idx].setMesh();

        /// 构建、编译着色器
        shader.use();

        /// 渲染
        m_meshes[mesh_idx].Draw(shader);
    }

    get_data();
}

void TransformToImage::get_bounding_box()
{
    // 保存该点坐标的临时变量
    std::vector<float> points(3);

    int mesh_num = this->m_meshes.size();
    // LOG_VARIABLE("mesh_num", mesh_num);
    // std::cout << m_meshes[0].vertices[0].Position.x << " " << m_meshes[0].vertices[0].Position.y << " " << m_meshes[0].vertices[0].Position.z << std::endl;

    for (int mesh_idx = 0; mesh_idx < mesh_num; ++mesh_idx)
    {
        // 当前 mesh 中顶点的数量
        int cur_mesh_size = m_meshes[mesh_idx].vertices.size();
        LOG_VARIABLE("vertices in mesh bounding box", cur_mesh_size);
    
        // 获取每一行顶点坐标
        for (int vertex_idx = 0; vertex_idx < cur_mesh_size; ++vertex_idx)
        {
            // 删除法向量
            this->m_meshes[mesh_idx].vertices[vertex_idx].Normal = glm::vec3(0.0f, 0.0f, 1.0f);

            points[0] = this->m_meshes[mesh_idx].vertices[vertex_idx].Position.x;
            points[1] = this->m_meshes[mesh_idx].vertices[vertex_idx].Position.y;
            points[2] = this->m_meshes[mesh_idx].vertices[vertex_idx].Position.z;

            for (int i = 0; i < VERTEX_NUM; ++i)
            {

                // 获取包围盒参数
                m_max_coord[mesh_idx][i] = std::max(m_max_coord[mesh_idx][i], points[i]);
                m_min_coord[mesh_idx][i] = std::min(m_min_coord[mesh_idx][i], points[i]);
            }

        }
    }

}

void TransformToImage::mapping()
{
    /// 保存该点坐标的临时变量
    std::vector<float> points(3);

    int mesh_num = this->m_meshes.size();
    // LOG_VARIABLE("mesh_num", mesh_num);

    for (int mesh_idx = 0; mesh_idx < mesh_num; ++mesh_idx)
    {
        // 当前 mesh 中顶点的数量
        int cur_mesh_size = m_meshes[mesh_idx].vertices.size();
        LOG_VARIABLE("vertices in mesh mapping", cur_mesh_size);

        // 获取每一行顶点坐标
        for (int vertex_idx = 0; vertex_idx < cur_mesh_size; ++vertex_idx)
        {
            points[0] = this->m_meshes[mesh_idx].vertices[vertex_idx].Position.x;
            points[1] = this->m_meshes[mesh_idx].vertices[vertex_idx].Position.y;
            points[2] = this->m_meshes[mesh_idx].vertices[vertex_idx].Position.z;

            // 对 x, y, z 进行标准化
            for (int i = 0; i < VERTEX_NUM; ++i)
            {
                // normalization
                points[i] -= (m_max_coord[mesh_idx][i] + m_min_coord[mesh_idx][i]) / 2.0f;      // 平移到中心点
                points[i] /= m_max_coord[mesh_idx][i] - m_min_coord[mesh_idx][i];
            }

            // 坐标系的 y, z 在 obj 里是相反的
            if (m_max_coord[mesh_idx][2] - m_min_coord[mesh_idx][2] > m_max_coord[mesh_idx][1] - m_min_coord[mesh_idx][1])
            {
                std::swap(points[1], points[2]);
            }

            // 做二维映射
            for (int i = 0; i < VERTEX_NUM; ++i)
            {
                if (i == 0)
                {
                    points[i] = (PI + std::atan2(points[2], points[0])) / (static_cast<float>(PI) * 2);
                    this->m_meshes[mesh_idx].vertices[vertex_idx].Position.x = points[i];
                }
                else if (i == 1)
                {
                    points[i] = (1 + points[1]) / 2;
                    this->m_meshes[mesh_idx].vertices[vertex_idx].Position.y = points[i];
                }
                else
                {
                    points[i] = 1.0;
                    this->m_meshes[mesh_idx].vertices[vertex_idx].Position.z = points[i];
                }
            }
        }
    }

}

void TransformToImage::set_matrics(Shader shader, Camera camera)
{
    // 定义投影矩阵、视图矩阵
    glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)800 / (float)600, 0.1f, 100.0f);
    glm::mat4 view = camera.GetViewMatrix();

    // 定义模型矩阵
    glm::mat4 model = glm::mat4(1.0f);
    // 平移
    model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
    // 缩放
    model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
    // 旋转
    model = glm::rotate(model, glm::radians(0.0f), glm::vec3(1.0f, 0.0f, 0.0f));

    // 转换矩阵传入着色器
    shader.setMat4("projection", projection);
    shader.setMat4("view", view);
    shader.setMat4("model", model);
}

void *TransformToImage::get_data()
{
    /// 为像素数据分配内存
    data = new float[800 * 600 * sizeof(float) * 3];

    /// 从显存中读取数据
    glReadPixels(0, 0, 800, 600, GL_RGBA, GL_FLOAT, data);

    return static_cast<void*>(data);
}


void TransformToImage::create_framebuffer()
{
    // 创建帧缓冲
    glGenFramebuffers(1, &FBO);
    // 激活, 在绑定到GL_FRAMEBUFFER目标之后,所有的读取和写入帧缓冲的操作将会影响当前绑定的帧缓冲
    glBindFramebuffer(GL_FRAMEBUFFER, FBO);

#if 0
    // 生成纹理
    glGenTextures(1, &texture_2D);
    glBindTexture(GL_TEXTURE_2D, texture_2D);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 将纹理附加到当前创建的 framebuffer 上
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_2D, 0);
#endif

    // 深度附件
    glGenRenderbuffers(1, &RBO);
    glBindRenderbuffer(GL_RENDERBUFFER, RBO);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);

    // 将渲染缓冲对象附加到帧缓冲的深度和模板附件上
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO);

    // 检查完整性
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
    else
        std::cout << "SUCCEED::FRAMEBUFFER:: Framebuffer is complete!" << std::endl;

    // 恢复主窗口的前台渲染效果
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

这是我们的实验结果。我们是用Qt封装成mesh来做的。

 

 

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-03-28 06:38
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/725048
    • 这篇博客你也可以参考下:Qt 3D开发案例:音频可视化器示例(附源码)
    • 这篇博客也不错, 你可以看下Qt 3D开发案例:音频可视化器示例(附源码)
    • 除此之外, 这篇博客: QT 进程通讯--共享内存进行通讯,并且两个进程均可进行修改结构体数据中的 cpp文件 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
      #include "widget.h"
      #include "ui_widget.h"
      #include <QMessageBox>
      #include <QDebug>
      Widget::Widget(QWidget *parent) :
          QWidget(parent),
          ui(new Ui::Widget)
      {
          ui->setupUi(this);
          //m_pSharedMemory = NULL;//共享内存
          setWindowTitle("proA--first connect");
          m_psharedlg = NULL;
          m_pSharedMemory.setKey("LD_SHARED");
      }
      
      Widget::~Widget()
      {
          //再关闭程序时,释放共享内存
          //如果在释放内存之后,仍然有对共享内存的操作,则会报错
          m_pSharedMemory.detach();
          delete ui;
      }
      
      void Widget::on_connect_btn_clicked()
      {
          /*
           * 进程A-写
      
      分为下面几步:
      
      检测该进程是否连接到共享内存段,如果连接,则将该进程与共享内存段分离。
      从系统足够大的内存中得到一个新的共享内存段。
      锁定该共享内存段,以阻止第二个对话框进程访问,将缓冲区中的图片复制进共享内存段。
      将共享内存段解锁,然后第二个对话框进程就可以访问了。
      */
          if(m_pSharedMemory.isAttached())
          {
              //将该进程与共享内存分离
              if(!m_pSharedMemory.detach())
              {
                  qDebug() << "unable to detach from shared memory" << endl;
              }
      
          }
      
          int nsize = sizeof(sharedlg);
      
          qDebug() << "ok"<<nsize<< endl;
           //创建共享内存段
          if(!m_pSharedMemory.create(nsize))
          {
              qDebug() << m_pSharedMemory.errorString() << "create error" <<endl;
              return;
          }
      
          m_pSharedMemory.lock();
      
          //char *pch = (char *)m_pSharedMemory.data();
      
          //memcpy(pch, &m_psharedlg,qMin(m_pSharedMemory.size(), nsize));
      
          m_psharedlg = (sharedlg *)m_pSharedMemory.data();
      
          //memcpy(pch, from,sizeof(sendbuf));
          m_pSharedMemory.unlock();
      
          m_psharedlg->aa = 1;
          m_psharedlg->dfei =2;
          m_psharedlg->fDui=3;
          m_psharedlg->nFlag =4;
          m_psharedlg->nnew = 5;
          QMessageBox::information(this, "ok", "proa-connect-ok");
          qDebug() << "ok"<<endl;
      }
      
      void Widget::on_update_btn_clicked()
      {
          if(m_psharedlg == NULL)
          {
              return ;
          }
          static int ncl = 10;
          m_psharedlg->aa = ncl++;
          m_psharedlg->nFlag = ncl++;
          m_psharedlg->dfei = ncl++;
      
          QMessageBox::information(this,"zi",QString("ar%1,%2,%3,%4,%5").arg(m_psharedlg->aa).arg(m_psharedlg->dfei).arg(m_psharedlg->fDui).arg(m_psharedlg->nFlag).arg(m_psharedlg->nnew));
      
      }
      
      void Widget::on_show_btn_clicked()
      {
          if(m_psharedlg == NULL)
          {
              return ;
          }
          QMessageBox::information(this,"proA",QString("ar%1,%2,%3,%4,%5").arg(m_psharedlg->aa).arg(m_psharedlg->dfei).arg(m_psharedlg->fDui).arg(m_psharedlg->nFlag).arg(m_psharedlg->nnew));
      
      }
      

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 创建了问题 3月27日

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?