其实是承接上一篇读取obj之后的显示。
说明:由于我读取的是wrl转换的obj,所以我还要还原wrl的视角。就是viewpoint。另外,模型自动旋转,又由于需要保存,会自动保存。
tmp.h
#include <Windows.h>
#include <gl/glut.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
#include "readobj.h"
#define max_points 10000
#define max_face 10000
#define max_material 50
//data
static float vn_list[max_points][3];
static float v_list[max_points][3];
static float vt_list[max_points][2];
static float f_list[max_points][10];
static int f_num = 0;
//vertex box
static GLfloat v_box[6];
//texture
static GLuint tex_index[max_material];
static int m_num = 0;
//viewpoint
static viewpoint view =
{
{-1, -1, -1},
{-1, -1, -1, -1},
-1
};
//rotate, mouse
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
//move, keyboard
static GLfloat ySignal = 0;
//pic
//save
static string objame;
static char picname[100];
static int picnum = 0;
static int picrows = 0;
static int piccols = 0;
void savePic()
{
GLint viewPort[4] = {0};
glGetIntegerv(GL_VIEWPORT, viewPort);
int nowcols = viewPort[2];
int nowrows = viewPort[3];
GLbyte *colorArr = new GLbyte[nowrows*nowcols*3];
glReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGB, GL_UNSIGNED_BYTE, colorArr);
for(int i=0; i<nowcols * nowrows * 3; i ++)
{
if(colorArr[i] == -1)
{
colorArr[i] = 255;
}
}
Mat show = Mat(nowrows, nowcols, CV_8UC3, Scalar::all(0));
for (int i = 0; i< nowrows; i++)
{
for (int j = 0; j< nowcols; j++)
{
show.at<Vec3b>(nowrows-i-1, j) = Vec3b(colorArr[(i*nowcols+j)*3+2], colorArr[(i*nowcols+j)*3+1], colorArr[(i*nowcols+j)*3]);
}
}
char tmpname[100];
sprintf(tmpname, "pic/%s%s%05d.png", objame.c_str(), "_", picnum);
imwrite(tmpname, show);
delete []colorArr;
}
void getTex(vector<material> m_vector_list)
{
//texture
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);//默认只显示纹理
//单字节对齐
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//tex_index = new GLuint[m_vector_list.size()];
assert(m_vector_list.size() < max_material);
glGenTextures(m_vector_list.size(), tex_index);
m_num = m_vector_list.size();
for (int i = 0; i< m_vector_list.size(); i++)
{
Mat Src = imread(m_vector_list[i].map_Kd);
assert(!Src.empty());
//imshow("Src", Src);
//waitKey();
int row = Src.rows;
int col = Src.cols;
GLbyte *texture = new GLbyte[row*col*4];
for (int j = row-1; j>= 0; j--)
{
for (int k = 0; k< col; k++)
{
texture[((row-j-1)*col+k)*4+0] = Src.at<Vec3b>(j, k)[2];
texture[((row-j-1)*col+k)*4+1] = Src.at<Vec3b>(j, k)[1];
texture[((row-j-1)*col+k)*4+2] = Src.at<Vec3b>(j, k)[0];
texture[((row-j-1)*col+k)*4+3] = 255;
}
}
glBindTexture(GL_TEXTURE_2D, tex_index[i]);//绑定对象
glTexImage2D
(
GL_TEXTURE_2D,
0,
GL_RGBA,
col,
row,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
texture
);
//when texture area is small, bilinear filter the closest mipmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//when texture area is large, bilinear filter the first mipmap
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//delete []texture;
}
cout<<m_num<<"\tmaterials\n";
for (int i = 0; i< m_num; i++)
{
if (glIsTexture(tex_index[i]));
{
cout<<"material\t"<<i<<"\tis loaded"<<endl;
}
}
}
void getData
(
vector<vertex_normal> vn_vector_list,
vector<vertex> v_vector_list,
vector<vertex_texture> vt_vector_list,
vector<face> f_vector_list,
vector<material> m_vector_list
)
{
//data
//vn
//vn_list = new float[vn_vector_list.size()][3];
assert(vn_vector_list.size() < max_points);
float tmp_vn_length = 0;
for (int i = 0; i< vn_vector_list.size(); i++)
{
tmp_vn_length = 0;
for (int j = 0; j< 3; j++)
tmp_vn_length += vn_vector_list[i][j]*vn_vector_list[i][j];
tmp_vn_length = sqrt(tmp_vn_length);
assert(tmp_vn_length != 0);
for (int j = 0; j< 3; j++)
vn_list[i][j] = vn_vector_list[i][j]/tmp_vn_length;
}
//v_box
v_box[0] = v_box[2] = v_box[4] = 100000000;
v_box[1] = v_box[3] = v_box[5] = -100000000;
for (int i = 1; i< v_vector_list.size(); i++)
{
float a, b, c;
a = v_vector_list[i][0];
b = v_vector_list[i][1];
c = v_vector_list[i][2];
if (a < v_box[0])
{
v_box[0] = a;
}
if (a > v_box[1])
{
v_box[1] = a;
}
if (b < v_box[2])
{
v_box[2] = b;
}
if (b > v_box[3])
{
v_box[3] = b;
}
if (c < v_box[4])
{
v_box[4] = c;
}
if (c > v_box[5])
{
v_box[5] = c;
}
}
//v,归一化
//v_list = new float[v_vector_list.size()][3];
assert(v_vector_list.size() < max_points);
/*
for (int i = 0; i< v_vector_list.size(); i++)
for (int j = 0; j< 3; j++)
v_list[i][j] = (v_vector_list[i][j] - v_box[2*j])/(v_box[2*j+1] - v_box[2*j])*2-1;
*/
//不归一化
for (int i = 0; i< v_vector_list.size(); i++)
for (int j = 0; j< 3; j++)
v_list[i][j] = v_vector_list[i][j];
//vt
//vt_list = new float[vt_vector_list.size()][2];
assert(vt_vector_list.size() < max_points);
for (int i = 0; i< vt_vector_list.size(); i++)
for (int j = 0; j< 2; j++)
vt_list[i][j] = vt_vector_list[i][j];
//f
//f_list = new float[f_vector_list.size()][10];
assert(f_vector_list.size() < max_face);
for (int i = 0; i< f_vector_list.size(); i++)
for (int j = 0; j< 10; j++)
f_list[i][j] = f_vector_list[i][j];
f_num = f_vector_list.size();
//texture
getTex(m_vector_list);
}
void SetupRC( vector<vertex_normal> vn_vector_list,
vector<vertex> v_vector_list,
vector<vertex_texture> vt_vector_list,
vector<face> f_vector_list,
vector<material> m_vector_list)
{
getData(vn_vector_list,
v_vector_list,
vt_vector_list,
f_vector_list,
m_vector_list);
//light
//Light values and coordinates
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glEnable(GL_DEPTH_TEST);// Hidden surface removal
glDepthFunc(1);//设置深度测试函数
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
//glEnable(GL_CULL_FACE); // Do not calculate inside of jet
// Enable lighting
glEnable(GL_LIGHTING);
// Setup and enable light 0
glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHT0,GL_SPECULAR, specular);
glEnable(GL_LIGHT0);
//只考虑光照,设不设都一样
// Enable color tracking
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// All materials hereafter have full specular reflectivity
// with a high shine
glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
glMateriali(GL_FRONT, GL_SHININESS, 32);
// Light blue background
// 浅紫色 222,160,228
GLfloat clearColor[3] = {0/255, 0/255, 139.0/255};
glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0f );
glClearDepth(1);
glEnable(GL_NORMALIZE);
}
void ChangeSize(int w, int h)
{
//Prevent a divide by zero
if(h == 0)
h = 1;
//Set Viewport to window dimensions
glViewport(0, 0, w, h);
//Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float aspect = w*1.0/h;
gluPerspective(view.fieldOfView/3.141590*180, aspect, v_box[4], v_box[5]);
//glOrtho (-1, 1, -1, 1, -100, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Called to draw scene
void RenderScene(void)
{
// Black blue background
//glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
//glClearDepth(1);
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glPushMatrix();
glTranslatef((v_box[0]+v_box[1])/2, 0, (v_box[4]+v_box[5])/2);
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glTranslatef(-(v_box[0]+v_box[1])/2, 0, -(v_box[4]+v_box[5])/2);
glPushMatrix();
glTranslatef(-view.position[0], -view.position[1], -view.position[2]);
glRotatef(view.orientation[3]/3.141590*180, view.orientation[0], view.orientation[1], view.orientation[2]);
glColor3f(1.0, 1.0, 1.0);
//M3DVector3f vNormal; // Storeage for calculated surface normal
for (int m_now = 0; m_now< m_num; m_now++)
{
glBindTexture(GL_TEXTURE_2D, tex_index[m_now]);
glBegin(GL_TRIANGLES);
for (int i = 0; i< f_num; i++)
{
if (f_list[i][9] != m_now)
{
continue;
}
int vindex[3];
int nindex[3];
int tindex[3];
for (int j = 0; j< 3; j++)
{
vindex[j] = f_list[i][3*j];
tindex[j] = f_list[i][3*j+1];
nindex[j] = f_list[i][3*j+2];
}
for (int j = 0; j< 3; j++)
{
glTexCoord2f(vt_list[tindex[j]][0], vt_list[tindex[j]][1]);
glVertex3f(v_list[vindex[j]][0], v_list[vindex[j]][1], v_list[vindex[j]][2]);
}
}
glEnd();
}
glPopMatrix();
// Restore the matrix state
glPopMatrix();
// Buffer swap
glutSwapBuffers();
}
// Respond to arrow keys
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
xRot-= 5.0f;
if(key == GLUT_KEY_DOWN)
xRot += 5.0f;
if(key == GLUT_KEY_LEFT)
yRot -= 5.0f;
if(key == GLUT_KEY_RIGHT)
yRot += 5.0f;
//xRot = (GLfloat)(xRot % 360);
//yRot = (GLfloat)(yRot % 360);
// Refresh the Window
glutPostRedisplay();
}
///
// Called by GLUT library when idle (window not being
// resized or moved)
void TimerFunction(int value)
{
if (picnum >= 1
&&picnum <= 121)
{
savePic();
}
if (picnum >121)
{
exit(0);
}
picnum++;
if (ySignal < 3.0f)
{
yRot += 0.1f; // Update Rotation
ySignal += 0.1f;
}
else if (ySignal >= 3.0f
&&ySignal < 9)
{
yRot -= 0.1f;
ySignal += 0.1f;
}
else if (ySignal >= 9.0f
&&ySignal < 12.0f)
{
yRot += 0.1f;
ySignal += 0.1f;
}
//xRot = (GLfloat)(xRot % 360);
//yRot = (GLfloat)(yRot % 360);
// Redraw the scene
glutPostRedisplay();
// Reset timer
glutTimerFunc(33, TimerFunction, 1);
}
void showobj
(
vector<vertex_normal> vn_vector_list,
vector<vertex> v_vector_list,
vector<vertex_texture> vt_vector_list,
vector<face> f_vector_list,
vector<material> m_vector_list,
char *objname,
viewpoint tmp
)
{
view = tmp;
objame = string(objname);
int w_col = 800;
int w_row = 600;
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(w_col, w_row);
glutInitWindowPosition(200, 200);
glutCreateWindow("Fuck OpenGL");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
glutTimerFunc(33, TimerFunction, 1);
SetupRC(vn_vector_list,
v_vector_list,
vt_vector_list,
f_vector_list,
m_vector_list);
glutMainLoop();
}
test.h
#include "tmp.h"
int main()
{
char* objname = "p1010770.obj";
//char* objname = "candies.obj";
viewpoint tmp =
{
{-0.00, 176.64, -0.00},
{0, 1, 0, 3.141590},
0.78
};
vector<vertex_normal> vn_vector_list;
vector<vertex> v_vector_list;
vector<vertex_texture> vt_vector_list;
vector<face> f_vector_list;
vector<material> m_list;
readobj(
objname,
vn_vector_list,
v_vector_list,
vt_vector_list,
f_vector_list,
m_list
);
cout<<"\n"<<v_vector_list.size()-1<<" vertices, ";
cout<<vn_vector_list.size()-1<<" vertices normals"<<endl;
cout<<f_vector_list.size()<<" faces, ";
cout<<vt_vector_list.size()-1<<" coords texture"<<endl;
cout<<"\n"<<m_list.size()<<" material\n"<<endl;
//system("pause");
showobj(vn_vector_list, v_vector_list, vt_vector_list, f_vector_list, m_list, objname, tmp);
//system("pause");
return 0;
}
over。另外,文件包在这里,http://download.csdn.net/detail/lcbwlx/7147385。