1.绘制目标
纹理贴图、光照计算
2.核心代码
// 加载纹理
void loadTexture() {
cv::Mat texture_img = loadImage("./Textures/bark_08.jpg", TEX_W, TEX_H);
cv::Mat texture_img_GD = loadImage("./Textures/soil.jpg", TEX_W_GD, TEX_H_GD);
if (texture_img.empty()) {
cout << "Failed load the texture file!" << endl;
}
else {
// 加载 图片纹理
/// TO DO ///
glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_W, TEX_H, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_img.data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID_GD);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_W_GD, TEX_H_GD, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_img_GD.data);
glGenerateMipmap(GL_TEXTURE_2D);
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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
cout << "Load the texture image successfully!" << endl;
}
}
// 加载模型
bool load_mesh(const string& filename)
{
cout << "Start loading the obj file, please wait......" << endl;
// 读取网格对应的obj文件
clock_t time_start = clock();
bool load_success = OBJ_FILE_LOADER.read_file(filename);
float time_elapsed = float(clock() - time_start) / CLOCKS_PER_SEC;
if (!load_success) {
cout << "Failed read the mesh obj file!" << endl;
return false;
}
cout << "Finished load the obj file! Time elapsed: " << time_elapsed << " seconds." << endl;
cout << "Total Vertices: " << OBJ_FILE_LOADER.total_vertices() << endl;
cout << "Total Faces: " << OBJ_FILE_LOADER.total_faces() << endl;
MIN_X = OBJ_FILE_LOADER.get_min_x();
MIN_Y = OBJ_FILE_LOADER.get_min_y();
MIN_Z = OBJ_FILE_LOADER.get_min_z();
MAX_X = OBJ_FILE_LOADER.get_max_x();
MAX_Y = OBJ_FILE_LOADER.get_max_y();
MAX_Z = OBJ_FILE_LOADER.get_max_z();
cout << "Min x: " << MIN_X << ", Max X: " << MAX_X << endl;
cout << "Min y: " << MIN_Y << ", Max Y: " << MAX_Y << endl;
cout << "Min z: " << MIN_Z << ", Max Z: " << MAX_Z << endl;
OFFSET_X = (MIN_X + MAX_X) * 0.5f;
OFFSET_Y = (MIN_Y + MAX_Y) * 0.5f;
OFFSET_Z = (MIN_Z + MAX_Z) * 0.5f;
Z_HALF_LENGTH = (MAX_Z - MIN_Z) * 0.5f;;
// 创建显示列表
MESH_LIST_ID = glGenLists(1);
// 填充显示列表
glNewList(MESH_LIST_ID, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID);
glBegin(GL_TRIANGLES);
for (int i = 0; i < OBJ_FILE_LOADER.total_faces(); ++i) {
const Triangle& t = OBJ_FILE_LOADER.get_triangle_at(i);// 获取三角形面片
//获取三角形的顶点数据
for (int j = 0; j < 3; ++j) {
float vertex_coords[3] = { 0 }; // 存储顶点的x,y,z坐标
float texture_coords[2] = { 0 }; // 存储顶点的纹理坐标
float normal_coords[3] = { 0 }; // 保存法向量
// TO DO : 获取并指定三角形三个顶点处的纹理坐标以及X,Y,Z空间坐标
OBJ_FILE_LOADER.get_vertex_at(t.m_vertex_ids[j], vertex_coords);
OBJ_FILE_LOADER.get_texture_at(t.m_texture_ids[j], texture_coords);
OBJ_FILE_LOADER.get_normal_at(t.m_normal_ids[j], normal_coords);
glTexCoord2f(texture_coords[0], texture_coords[1]);
glNormal3f(normal_coords[0], normal_coords[1], normal_coords[2]);
glVertex3f(vertex_coords[0], vertex_coords[1], vertex_coords[2]);//D
}
}
glEnd();
glEndList();
return true;
}
// 加载模型
bool load_mesh2(const string& filename)
{
cout << "Start loading the obj file, please wait......" << endl;
// 读取网格对应的obj文件
clock_t time_start = clock();
bool load_success = OBJ_FILE_LOADER_GD.read_file(filename);
float time_elapsed = float(clock() - time_start) / CLOCKS_PER_SEC;
if (!load_success) {
cout << "Failed read the mesh obj file!" << endl;
return false;
}
cout << "Finished load the obj file! Time elapsed: " << time_elapsed << " seconds." << endl;
cout << "Total Vertices: " << OBJ_FILE_LOADER_GD.total_vertices() << endl;
cout << "Total Faces: " << OBJ_FILE_LOADER_GD.total_faces() << endl;
MIN_X = OBJ_FILE_LOADER_GD.get_min_x();
MIN_Y = OBJ_FILE_LOADER_GD.get_min_y();
MIN_Z = OBJ_FILE_LOADER_GD.get_min_z();
MAX_X = OBJ_FILE_LOADER_GD.get_max_x();
MAX_Y = OBJ_FILE_LOADER_GD.get_max_y();
MAX_Z = OBJ_FILE_LOADER_GD.get_max_z();
cout << "Min x: " << MIN_X << ", Max X: " << MAX_X << endl;
cout << "Min y: " << MIN_Y << ", Max Y: " << MAX_Y << endl;
cout << "Min z: " << MIN_Z << ", Max Z: " << MAX_Z << endl;
OFFSET_X = (MIN_X + MAX_X) * 0.5f;
OFFSET_Y = (MIN_Y + MAX_Y) * 0.5f;
OFFSET_Z = (MIN_Z + MAX_Z) * 0.5f;
Z_HALF_LENGTH = (MAX_Z - MIN_Z) * 0.5f;;
// 创建显示列表
MESH_LIST_ID_GD = glGenLists(1);
// 填充显示列表
glNewList(MESH_LIST_ID_GD, GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, BARK_TEXTURE_ID_GD);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0, 0);
glNormal3f(0.000000, 1.000000, 0.000000);
glVertex3f(-112.000000, -27.628487, 112.000000);//D
glTexCoord2f(1, 0);
glNormal3f(0.000000, 1.000000, 0.000000);
glVertex3f(112.000000, -27.628487, 112.000000);//D
glTexCoord2f(0, 1);
glNormal3f(0.000000, 1.000000, 0.000000);
glVertex3f(-112.000000, -27.628487, -112.000000);//D
glTexCoord2f(1, 1);
glNormal3f(0.000000, 1.000000, 0.000000);
glVertex3f(112.000000, -27.628487, -112.000000);//D
glEnd();
glEndList();
return true;
}
void init()
{
glClearColor(1.f, 1.f, 1.f, 0.f);
glEnable(GL_DEPTH_TEST);
// 申请纹理
glGenTextures(1, &BARK_TEXTURE_ID);
glGenTextures(1, &BARK_TEXTURE_ID_GD);
loadTexture();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient_color0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse_and_specular0);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_diffuse_and_specular0);
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material_ambient_and_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, material_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, material_shininess);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
load_mesh2("./Meshes/Tree96-Ground.obj");
load_mesh("./Meshes/Tree96-Branch.obj");
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// TO DO: 设置照相机
gluLookAt
(
0.0, 0.0, 256, /**eyex xyz*/
0.0, 0.0, 0.0, /**center xyz*/
0.0, 1.0, 0.0 /** up xyz*/
);
glRotatef(ROT_Z, 0.f, 0.f, 1.f);
glRotatef(ROT_Y, 0.f, 1.f, 0.f);
glRotatef(ROT_X, 1.f, 0.f, 0.f);
glScalef(SCALE, SCALE, SCALE);
glTranslatef(-OFFSET_X, -OFFSET_Y, -OFFSET_Z);
glColor3f(0.f, 0.f, 1.f);
// 调用显示列表,进行三维模型的绘制
glCallList(MESH_LIST_ID_GD);
glCallList(MESH_LIST_ID);
glutSwapBuffers();
}