读取并显示 obj (2)

这个是读取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。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值