c++给已生成模型上色
时间: 2023-06-20 18:07:21 浏览: 46
要给已生成的模型上色,你需要为每个顶点分配一个颜色值。这可以通过使用纹理贴图来实现,其中每个像素都对应于模型上的一个顶点,并且包含了该顶点的颜色值。
以下是一个简单的示例代码,用于将纹理贴图应用于模型:
```c++
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <GL/glut.h>
using namespace std;
// 纹理贴图文件名
const char* textureFilename = "texture.png";
// 模型文件名
const char* modelFilename = "model.obj";
// 纹理贴图数据
vector<unsigned char> textureData;
int textureWidth, textureHeight;
// 模型数据
vector<float> vertices;
vector<float> texCoords;
vector<int> indices;
// 加载纹理贴图
void loadTexture()
{
// 使用 SOIL 库读取纹理贴图文件
textureData = SOIL_load_image(textureFilename, &textureWidth, &textureHeight, 0, SOIL_LOAD_RGBA);
if (!textureData.empty())
{
cout << "Successfully loaded texture: " << textureFilename << endl;
}
else
{
cerr << "Failed to load texture: " << textureFilename << endl;
exit(1);
}
}
// 加载模型数据
void loadModel()
{
ifstream fin(modelFilename);
if (fin.is_open())
{
string line;
while (getline(fin, line))
{
// 处理顶点数据
if (line.substr(0, 2) == "v ")
{
istringstream s(line.substr(2));
float x, y, z;
s >> x >> y >> z;
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(z);
}
// 处理纹理坐标数据
else if (line.substr(0, 3) == "vt ")
{
istringstream s(line.substr(3));
float u, v;
s >> u >> v;
texCoords.push_back(u);
texCoords.push_back(v);
}
// 处理面数据
else if (line.substr(0, 2) == "f ")
{
istringstream s(line.substr(2));
int i1, i2, i3, j1, j2, j3, k1, k2, k3;
char c;
s >> i1 >> c >> j1 >> c >> k1 >> i2 >> c >> j2 >> c >> k2 >> i3 >> c >> j3 >> c >> k3;
indices.push_back(i1 - 1);
indices.push_back(i2 - 1);
indices.push_back(i3 - 1);
}
}
fin.close();
cout << "Successfully loaded model: " << modelFilename << endl;
}
else
{
cerr << "Failed to load model: " << modelFilename << endl;
exit(1);
}
}
// 绘制模型
void drawModel()
{
// 开启纹理贴图
glEnable(GL_TEXTURE_2D);
// 绑定纹理贴图
glBindTexture(GL_TEXTURE_2D, 1);
// 设置纹理贴图参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// 加载纹理贴图数据
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
// 绘制模型
glBegin(GL_TRIANGLES);
for (int i = 0; i < indices.size(); i++)
{
int index = indices[i];
glTexCoord2f(texCoords[index * 2], texCoords[index * 2 + 1]);
glVertex3f(vertices[index * 3], vertices[index * 3 + 1], vertices[index * 3 + 2]);
}
glEnd();
// 关闭纹理贴图
glDisable(GL_TEXTURE_2D);
}
// 初始化函数
void init()
{
// 设置清空颜色为黑色
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 设置投影矩阵
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 0.1f, 100.0f);
// 加载纹理贴图和模型
loadTexture();
loadModel();
}
// 显示函数
void display()
{
// 清空颜色缓冲区和深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 设置视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
// 绘制模型
drawModel();
// 刷新缓冲区
glutSwapBuffers();
}
// 主函数
int main(int argc, char** argv)
{
// 初始化 GLUT 库
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 800);
glutCreateWindow("Model Viewer");
// 初始化 GLEW 库
glewInit();
// 调用初始化函数
init();
// 注册回调函数
glutDisplayFunc(display);
// 进入主循环
glutMainLoop();
return 0;
}
```
在上面的示例代码中,我们使用了 SOIL 库来加载纹理贴图文件。如果你没有安装该库,可以通过以下命令在 Ubuntu 系统上进行安装:
```bash
sudo apt-get install libsoil-dev
```
在 Windows 系统上,你可以直接下载该库的预编译版本,并将其添加到 Visual Studio 的项目中。
在绘制模型时,我们使用了 glBegin(GL_TRIANGLES) 和 glEnd() 函数来指定绘制三角形。对于每个三角形,我们通过 glTexCoord2f() 函数设置纹理坐标,并通过 glVertex3f() 函数设置顶点坐标。其中,纹理坐标和顶点坐标的索引值是一致的,即第 i 个顶点的纹理坐标为第 i 个纹理坐标,第 i 个顶点的坐标为第 i 个顶点坐标。最后,我们使用 glDisable(GL_TEXTURE_2D) 函数关闭纹理贴图。
需要注意的是,为了使纹理贴图正确显示,我们需要启用深度测试和背面剔除。这可以通过在初始化函数中添加以下代码来实现:
```c++
// 启用深度测试
glEnable(GL_DEPTH_TEST);
// 启用背面剔除
glEnable(GL_CULL_FACE);
```
另外,为了使视图矩阵正确工作,我们需要调用 gluLookAt() 函数来设置摄像机位置和朝向。在本例中,我们将摄像机位置设置为 (0, 0, 5),朝向原点,并设置上方向为 Y 轴正方向。
最后,我们在主函数中调用 glutMainLoop() 函数进入主循环,等待用户交互事件的发生。当有事件发生时,系统将自动调用注册的回调函数,例如 display() 函数,在屏幕上绘制图形。