//映射算法核心部分
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来做的。
不知道你这个问题是否已经解决, 如果还没有解决的话:
#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));
}