//映射算法核心部分
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来做的。