这个是读取obj的另一个版本,专门读取由灰度图转换的obj。其中math3d是蓝宝书的程序。
readobj.h
#ifndef READOBJ_H_
#define READOBJ_H_
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
//存放name的文件夹
string prename = "obj/";
void readmtl(char *name, char *picname)
{
char mtlname[100];
sprintf(mtlname, "%s%s", prename.c_str(), name);
FILE *fp;
fp = fopen(mtlname, "r");
if (!fp)
{
cout<<"error, cannot load fil.\a"<<endl;
}
char token[100];
while(!feof(fp))
{
token[0] = NULL;
fscanf(fp,"%s", token);
if (!strcmp(token, "map_Kd"))
{
fscanf(fp, "%s", token);
sprintf(picname, "%s%s", prename.c_str(), token);
}
else
fgets(token, 100, fp);
}
if (fp)
fclose(fp);
}
void readobj
(
char *objname,
float *x,
float *y,
float *z,
float *spoints,
float *tpoints,
int *f1,
int *f2,
int *f3,
int &v,
int &vt,
int &f,
float &xmax,
float &ymax,
float &zmax,
float &xmin,
float &ymin,
float &zmin,
char *picname
)
{
FILE *fp;
fp = fopen(objname, "r");
if (!fp)
{
cout<<"error, cannot load obj file."<<endl;
system("pause");
return;
}
char token[100];
v = vt = f = 0;
xmax = ymax = zmax = -100;
xmin = ymin = zmin = 100;
//处理几种情况:
//v, f, vt
while(!feof(fp))
{
token[0] = NULL;
fscanf(fp,"%s", token);
if (!strcmp(token, "mtllib"))
{
fscanf(fp, "%s", token);
readmtl(token, picname);
}
else if (!strcmp(token, "v"))
{
float xx, yy, zz;
fscanf(fp, "%f %f %f", &xx, &yy, &zz);
x[v] = xx;
y[v] = yy;
z[v] = zz;
if (xmax < xx)
{
xmax = xx;
}
if (ymax < yy)
{
ymax = yy;
}
if (zmax < zz)
{
zmax = zz;
}
if (xmin > xx)
{
xmin = xx;
}
if (ymin > yy)
{
ymin = yy;
}
if (zmin > zz)
{
zmin = zz;
}
v++;
}
else if (!strcmp(token,"vt"))
{
float ss, tt;
fscanf(fp, "%f %f %f", &ss, &tt);
spoints[vt] = ss;
tpoints[vt] = tt;
vt++;
}
else if (!strcmp(token,"f"))
{
char s[3][100];
int vv[3];
for (int i=0;i<3;i++)
{
fscanf(fp ,"%s", s[i]);
}
//for each vertex of this face
for (int i=0;i<3;i++)
{
char str[30], ch;
int base, offset;
base = offset = 0;
// calculate vertex-list index
while((ch=s[i][base+offset]) != '/' && (ch=s[i][base+offset]) != '\0')
{
str[offset] = ch;
offset++;
}
str[offset] = '\0';
vv[i] = atoi(str);
}
f1[f] = vv[0];
f2[f] = vv[1];
f3[f] = vv[2];
f++;
}
else
fgets(token, 100, fp);
}
if (fp)
fclose(fp);
}
#endif
r2.h
// Jet.cpp
// A hand modeled Jet airplane
// OpenGL SuperBible
// Beginning of OpenGL lighting sample
// Program by Richard S. Wright Jr.
#ifndef R2_H_
#define R2_H_
#include <GL2/freeglut.h>
#include "math3d.h"
#include "readobj.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat signvalue = 0.0f;
static GLfloat gltranslateangle = 1.0;
static GLfloat gladdddd = 0.0;
static int picnum = 0;
static int firstinti = 1;
//默认f,v分别不超过2000000和1000000
//即图片大小不超过1000x1000
int f = 0;
int vt = 0;
int v = 0;
float x[1000000];
float y[1000000];
float z[1000000];
float s[1000000];
float t[1000000];
int f1[2000000];
int f2[2000000];
int f3[2000000];
char picname[100];
float xmax = 0, ymax = 0, zmax = 0;
float xmin = 0, ymin = 0, zmin = 0;
float z_ave = 0;
static int height = 460;
static int width = 345;
//static GLbyte colorArr[1000*1000*3];
static GLbyte TextData[1000*1000*4];
static GLuint TexName;
static int picrows = 0;
static int piccols = 0;
static float picz = 0;
string objname;
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", objname.c_str(), "_", picnum);
imwrite(tmpname, show);
delete colorArr;
}
// Called to draw scene
void RenderScene(void)
{
M3DVector3f vNormal; // Storeage for calculated surface normal
// 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();
//glRotatef(xRot, 1.0f, 0.0f, 0.0f);
//glTranslatef(0, 0, z_ave);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
//glTranslatef(0, 0, -z_ave);
// Nose Cone - Points straight down
// Set material color
glColor3ub(200, 200, 200);
//模型
glBegin(GL_TRIANGLES);
for (int i = 0; i< f; i++)
{
// Verticies for this panel
M3DVector3f vPoints[3] = {{ x[f1[i]-1], y[f1[i]-1], z[f1[i]-1]},
{ x[f2[i]-1], y[f2[i]-1], z[f2[i]-1]},
{ x[f3[i]-1], y[f3[i]-1], z[f3[i]-1]}};
// Calculate the normal for the plane
m3dFindNormal(vNormal, vPoints[0], vPoints[1], vPoints[2]);
glNormal3fv(vNormal);
glTexCoord2f(s[f1[i]-1], t[f1[i]-1]);
glVertex3fv(vPoints[0]);
glTexCoord2f(s[f2[i]-1], t[f2[i]-1]);
glVertex3fv(vPoints[1]);
glTexCoord2f(s[f3[i]-1], t[f3[i]-1]);
glVertex3fv(vPoints[2]);
}
glEnd();
// Restore the matrix state
glPopMatrix();
// Display the results
glutSwapBuffers();
//savepic();
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Light values and coordinates
GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 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, 128);
// Light blue background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glClearDepth(1);
glEnable(GL_NORMALIZE);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
set pixel storage modes
glPixelStoref( GL_UNPACK_ALIGNMENT, 1 );
glGenTextures( 1, &TexName );
glBindTexture( GL_TEXTURE_2D, TexName );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, piccols,
picrows, 0, GL_RGBA, GL_UNSIGNED_BYTE,
TextData );
/*gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, texImageWidth, texImageHeight,
GL_RGBA, GL_UNSIGNED_BYTE, texImage[i]);*/
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// when texture area is large, bilinear filter the first mipmap
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); // GL_NEAREST );//
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); // GL_LINEAR_MIPMAP_NEAREST ); // GL_NEAREST );//
GLfloat lightPos[] = { -100.0f, 200.0f, 100.0f, 1.0f };
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
}
/
// Handle arrow keys
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
{
xRot-= 5.0f;
picz -=0.1;
}
if(key == GLUT_KEY_DOWN)
{
xRot += 5.0f;
picz += 0.1;
}
if(key == GLUT_KEY_LEFT)
yRot -= 5.0f;
if(key == GLUT_KEY_RIGHT)
yRot += 5.0f;
if(key > 356.0f)
xRot = 0.0f;
if(key < -1.0f)
xRot = 355.0f;
if(key > 356.0f)
yRot = 0.0f;
if(key < -1.0f)
yRot = 355.0f;
// Refresh the Window
glutPostRedisplay();
}
///
// Called by GLUT library when idle (window not being
// resized or moved)
void TimerFunction(int value)
{
if (picnum >= 1
&&picnum <=gltranslateangle*4/0.1+1)
{
savepic();
}
//if(picnum >=gltranslateangle*4/0.1+1)
//{
//exit(0);
//}
picnum++;
if (signvalue < gltranslateangle)
{
yRot += 0.1f; // Update Rotation
signvalue += 0.1f;
}
else if (signvalue >= gltranslateangle
&&signvalue < gltranslateangle*3)
{
yRot -= 0.1f;
signvalue += 0.1f;
}
else if (signvalue >= gltranslateangle*3
&&signvalue < gltranslateangle*4)
{
yRot += 0.1f;
signvalue += 0.1f;
}
// Redraw the scene
glutPostRedisplay();
// Reset timer
glutTimerFunc(33, TimerFunction, 1);
}
//
// Reset projection and light position
void ChangeSize(int w, int h)
{
//GLfloat fAspect;
// Prevent a divide by zero
if(h == 0)
h = 1;
if (w%4 != 0)
{
w = ((w/4)+1)*4;
}
if (h%4 != 0)
{
h = ((h/4)+1)*4;
}
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//fAspect = (GLfloat) w / (GLfloat) h;
//gluPerspective(45.0f, fAspect, 1.0f, 225.0f);
glOrtho(-1.0, 1.0, -1.0, 1.0, -100, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//载入图片
void gettex(string name)
{
Mat t = imread(name);
//imshow("t", t);
//waitKey();
piccols = t.cols;
picrows = t.rows;
width = piccols;
height = picrows;
for (int i = picrows-1; i>= 0; i--)
{
for (int j = 0; j< piccols; j++)
{
TextData[((picrows-1-i)*piccols+j)*4+0] = (GLubyte)t.at<Vec3b>(i, j)[2];
TextData[((picrows-1-i)*piccols+j)*4+1] = (GLubyte)t.at<Vec3b>(i, j)[1];
TextData[((picrows-1-i)*piccols+j)*4+2] = (GLubyte)t.at<Vec3b>(i, j)[0];
TextData[((picrows-1-i)*piccols+j)*4+3] = 255;
}
}
}
//归一化
void getvertex()
{
for (int i = 0; i< v; i++)
{
x[i] = (x[i]-xmin)/(xmax-xmin)*2-1;
y[i] = (y[i]-ymin)/(ymax-ymin)*2-1;
z[i] = (z[i]-zmin)/(zmax-zmin)*2-1;
}
for (int i = 0; i< v; i++)
{
z_ave += z[i];
}
z_ave = z_ave/v;
}
int getpic(string objname2)
{
objname = objname2;
char fullname[100];
sprintf(fullname, "%s%s%s", "obj/", objname.c_str(), ".obj");
readobj(fullname,
x, y, z,
s, t,
f1, f2, f3,
v, vt,
f,
xmax, ymax, zmax,
xmin, ymin, zmin,
picname
);
cout<<"v : "<<v<<"\tf : "<<f<<endl;
cout<<"max x : "<<xmax<<"\tminx : "<<xmin<<"\n";
cout<<"max y : "<<ymax<<"\tminy : "<<ymin<<"\n";
cout<<"max z : "<<zmax<<"\tminz : "<<zmin<<endl;
cout<<"picname : "<<picname<<endl;
//system("pause");
//归一化
getvertex();
//读取tex
gettex(picname);
int argc = 0;
char *argv[1] = {""};
if (firstinti)
{
//glutInit(&argc, argv);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(width, height);
glutCreateWindow("Shiny Jet");
firstinti = 0;
}
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
glutTimerFunc(33, TimerFunction, 1);
SetupRC();
while(picnum <= gltranslateangle * 4 / 0.1 + 1)
{
glutMainLoopEvent();
RenderScene();
}
//system("pause");
picnum = 0;
xRot = 0.0f;
yRot = 0.0f;
signvalue = 0.0f;
gltranslateangle = 3.0;
gladdddd = 0.0;
picnum = 0;
//默认f,v分别不超过2000000和1000000
//即图片大小不超过1000x1000
f = 0;
vt = 0;
v = 0;
xmax = 0;
ymax = 0;
zmax = 0;
xmin = 0;
ymin = 0;
zmin = 0;
z_ave = 0;
height = 460;
width = 345;
//static GLbyte colorArr[1000*1000*3];
//static GLuint TexName;
picrows = 0;
piccols = 0;
picz = 0;
return 0;
}
#endif
其中,由于opengl用了mainloop就会推出,所以我用了freeglut。