VS+opengl加載obj和mtl文件


opengl和opencv的配置忘記存了...現在也不記得是怎么配置的了。

從obj和mtl文件的結構開始,除開網上都能查到的,個人認為還有的坑點有:
1.不一定所有的面(f行)都是三角形/四邊形,同一個obj文件中可能同時存在不同頂點數的面,所以在畫的時候要用“glBegin(GL_POLYGON)”代表開始畫一個多邊形,每畫完一個多邊形接“glEnd()”。
2.obj文件和mtl文件的聯系:mtl中以“newmtl material_name”行定義一個名為material_name的材質,在obj中以“usemtl material_name”行說明從現在開始往下直到一個新的usemtl行的f都用這個材質。在材質定義中可能用到紋理貼圖,“map_Kd file_directory”。
3.f v/vt/vn,可能是負數,代表從當前行開始往前索引,這種情況很麻煩,我沒管。
4.紋理貼圖的坐標是以左下角為(0,0),左上角為(1,0)。opencv加載的圖片在mat中存的坐標是左上角為(0,0),左下角為(1,0),x坐標是反的.
5.在我使用的版本opengl竟然還是在圖片長寬不是2的整數倍的時候還是會出現加載問題,所以要resize成(1024,1024)。

工程中定義了兩個類,一個存obj一個存mtl信息和texture.

材質類頭文件
/* Class Model */
#include <vector>
#include <string>
#include <fstream>
#include <GL/glut.h>

/* Class Materail */

struct material {
	std::string material_name="";
	int texture_id=-1;
	float Ns = 1024;
	//Ns exponent 指定材質的反射指數,定義了反射高光度.exponent是反射指數值,該值越高則高光越密集,一般取值范圍在0~1000。
	float d = 1;
	//取值為1.0表示完全不透明,取值為0.0時表示完全透明
	float Ni = 0.001;
	//Ni ptical density 指定材質表面的光密度,即折射值。可在0.001到10之間進行取值。若取值為1.0,光在通過物體的時候不發生彎曲。玻璃的折射率為1.5。
	int illum = 2;
	// Highlight on
	GLfloat Ka[3] = { 1.0, 0.0, 0.0 };
	//環境反射
	GLfloat Kd[3] = { 1.0, 0.0, 0.0 };
	//漫反射
	GLfloat Ks[3] = { 1.0, 0.0, 0.0 };
	//鏡面反射
};

class Material
{
public:
	void loadFile(const char* file_name);
	void load_texture(const char* file_name);

	//vectors
	std::vector<material> material_list;
	std::vector<GLuint> texture_list;

};

#endif

obj類頭文件
/* Class Model */
#include <vector>
#include <string>
#include <fstream>
#include <GL/glut.h>

/* Class Model */
 
class Model
{
public: 		
   void loadFile(const char* file_name);		// load model coords from file
	
	//vectors
	std::vector<float> vertex_list;
	std::vector<float> normal_list;
	std::vector<float> texture_list;
	std::vector<std::string> s_list;
	std::vector<std::vector<int>> face_list;
	std::vector<std::string> face_material;

};

#endif

材質和紋理貼圖加載函數
#include "Material.h"
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

void Material::load_texture(const char* file_name)
{
	Mat img = imread(file_name);
	resize(img, img, Size(1024, 1024));
	GLint height = img.rows, width = img.cols, total_bytes;
	GLubyte* pixels = 0;
	GLint last_texture_ID;
	GLuint texture_ID = 0;

	{
		GLint line_bytes = width * 3;
		/*while (line_bytes % 4 != 0)
			++line_bytes;*/      //不一定是bmp了,不存在這個問題
		total_bytes = line_bytes * height;
	}


	pixels = (GLubyte*)malloc(total_bytes);

	//cout << height << " "<<width<<endl;
	for (int i = 0;i < height;i++)
		for (int j = 0;j < width;j++)
		{
			pixels[(i * width + j) * 3] = img.at<Vec3b>(height-1-i, j)[0];
			pixels[(i * width + j) * 3 + 1] = img.at<Vec3b>(height-1-i, j)[1];
			pixels[(i * width + j) * 3 + 2] = img.at<Vec3b>(height-1-i, j)[2];
		}

	glGenTextures(1, &texture_ID);
	if (texture_ID == 0)
	{
		free(pixels);
		return ;
	}

	glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture_ID);
	glBindTexture(GL_TEXTURE_2D, texture_ID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	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);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
		GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
	glBindTexture(GL_TEXTURE_2D, last_texture_ID);

	free(pixels);
	this->texture_list.push_back(texture_ID);
}

void Material::loadFile(const char* file_name)
{

	ifstream fileObject(file_name);
	string fileObjectLine;

	if (fileObject.is_open()) {
		while (!fileObject.eof()) {
			getline(fileObject, fileObjectLine);
			if (fileObjectLine.c_str()[0] == 'n' && fileObjectLine.c_str()[1] == 'e')
			{
				istringstream iss(fileObjectLine);
				string temp, name;
				iss >> temp >> name;
				material now_material;
				now_material.material_name = name;
				while (fileObjectLine.c_str()[0] != '\n' && fileObjectLine.c_str()[0] != '\r')
				{
					getline(fileObject, fileObjectLine);
					if (fileObjectLine.size() < 4)
					{
						break;
					}
					else if (fileObjectLine.c_str()[1] == 'N' && fileObjectLine.c_str()[2] == 's')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float Ns;
						iss >> temp >> Ns;
						now_material.Ns = Ns;
					}
					else if (fileObjectLine.c_str()[1] == 'd' && fileObjectLine.c_str()[2] == ' ')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float d;
						iss >> temp >> d;
						now_material.d = d;
					}
					else if (fileObjectLine.c_str()[1] == 'N' && fileObjectLine.c_str()[2] == 'i')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float Ni;
						iss >> temp >> Ni;
						now_material.Ni = Ni;
					}
					else if (fileObjectLine.c_str()[1] == 'i' && fileObjectLine.c_str()[2] == 'l')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float illum;
						iss >> temp >> illum;
						now_material.illum = illum;
					}
					else if (fileObjectLine.c_str()[1] == 'K' && fileObjectLine.c_str()[2] == 'a')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float a, b, c;
						iss >> temp >> a >> b >> c;
						now_material.Ka[0] = a;
						now_material.Ka[1] = b;
						now_material.Ka[2] = c;
					}
					else if (fileObjectLine.c_str()[1] == 'K' && fileObjectLine.c_str()[2] == 'd')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float a, b, c;
						iss >> temp >> a >> b >> c;
						now_material.Kd[0] = a;
						now_material.Kd[1] = b;
						now_material.Kd[2] = c;
					}
					else if (fileObjectLine.c_str()[1] == 'K' && fileObjectLine.c_str()[2] == 's')
					{
						istringstream iss(fileObjectLine);
						string temp;
						float a, b, c;
						iss >> temp >> a >> b >> c;
						now_material.Ks[0] = a;
						now_material.Ks[1] = b;
						now_material.Ks[2] = c;
					}
					else if (fileObjectLine.c_str()[1] == 'm' && fileObjectLine.c_str()[2] == 'a')
					{
						istringstream iss(fileObjectLine);
						string temp, filename;
						iss >> temp >> filename;
						this->load_texture(filename.c_str());
						now_material.texture_id = this->texture_list.size() - 1;
					}
				}
				this->material_list.push_back(now_material);
			}
		}
	}
}
obj文件加載函數
#include "Model.h"
#include <opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

void Model::loadFile(const char* file_name)
{
	ifstream fileObject(file_name);
	string fileObjectLine;

	if (fileObject.is_open()) {
		while (!fileObject.eof()) {
			getline(fileObject, fileObjectLine);

			if (fileObjectLine.c_str()[0] == 'v' && fileObjectLine.c_str()[1] == ' ')
			{
				float x, y, z;
				fileObjectLine[0] = ' ';
				sscanf_s(fileObjectLine.c_str(), "%f %f %f ", &x, &y, &z);
				this->vertex_list.push_back(x);
				this->vertex_list.push_back(y);
				this->vertex_list.push_back(z);
				continue;
			}
			else if (fileObjectLine.c_str()[0] == 'v' && fileObjectLine.c_str()[1] == 'n')
			{
				float x, y, z;
				fileObjectLine[0] = ' ';
				fileObjectLine[1] = ' ';
				sscanf_s(fileObjectLine.c_str(), "%f %f %f ", &x, &y, &z);
				this->normal_list.push_back(x);
				this->normal_list.push_back(y);
				this->normal_list.push_back(z);
				continue;
			}
			else if (fileObjectLine.c_str()[0] == 'v' && fileObjectLine.c_str()[1] == 't')
			{
				float x, y, z;
				fileObjectLine[0] = ' ';
				fileObjectLine[1] = ' ';
				sscanf_s(fileObjectLine.c_str(), "%f %f", &x, &y);
				this->texture_list.push_back(x);
				this->texture_list.push_back(y);
				continue;
			}
		}

		fileObject.clear();
		fileObject.seekg(0, ios::beg);

		string now_material = "";
		while (!fileObject.eof()) {
			getline(fileObject, fileObjectLine);
			if (fileObjectLine.c_str()[0] == 'u')
			{
				istringstream iss(fileObjectLine);
				string temp;
				iss >> temp >> now_material;
			}
			if (fileObjectLine.c_str()[0] == 'f')
			{

				s_list.push_back(fileObjectLine);
				fileObjectLine[0] = ' ';

				istringstream iss(fileObjectLine);

				vector<int> tri;
				while (iss)
				{
					int value;
					char x;
					iss >> value;
					if (iss.fail()) {/* cout << "qi" << endl;*/break; }
					tri.push_back(value);
					iss >> x >> value;
					tri.push_back(value);
					iss >> x >> value;
					tri.push_back(value);
				}
				this->face_list.push_back(tri);
				this->face_material.push_back(now_material);
			}
		}
	}
}
main函數
#include "Model.h"
#include "Material.h"
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <cassert>
#include <GL/glut.h>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

Model model_object;		// an instance of Model
Material material_object;
GLdouble perspective = 100.0;
double rot_x = 0.0, rot_y = 0;
double dx = 0.0, dy = 0.0;
double mouse_x = 0.0, mouse_y = 0.0;
int moving = 0;
void set_light()
{
    float light[] = { 16.0,16.0,0.0,0.0 };
    glGetLightfv(GL_LIGHT0, GL_POSITION, light);
}

void set_camera()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(75, 1, 1, 21);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.1, 0.1, 4, 0, 0, 0, 0, 1, 0);
}

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(perspective, (GLfloat)w / (GLfloat)h, 10.0, 200.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -30.0);
}


void initialize()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    set_light();
    glShadeModel(GL_SMOOTH);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
}

void display(void)
{
    // 清除屏幕
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // 設置光和視角
    set_light();
    set_camera();
    //處理旋轉
    glRotatef(rot_x, 1.0f, 0.0f, 0.0f);
    glRotatef(rot_y, 0.0f, 1.0f, 0.0f);

    GLint last_texture_ID;
    glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture_ID);
    for (int i = 0;i < model_object.face_list.size();i++)
    {
        vector<int>tri = model_object.face_list.at(i);
        string material_name = model_object.face_material.at(i);
        material now_material;
        for (int k = 0;k < material_object.material_list.size();k++)
        {
            now_material = material_object.material_list.at(k);
            if (now_material.material_name == material_name)
            {
                break;
            }
        }
        if (now_material.texture_id != -1)
        {
            glBindTexture(GL_TEXTURE_2D, material_object.texture_list.at(now_material.texture_id));
            glBegin(GL_POLYGON);
            for (int j = 0;j < tri.size();j += 3)
            {
                int value = tri.at(j + 1);
                glTexCoord2f(model_object.texture_list.at(2 * (value - 1)), model_object.texture_list.at(2 * (value - 1) + 1));
                value = tri.at(j + 2);
                glNormal3f(model_object.normal_list.at(3 * (value - 1)) + dx, model_object.normal_list.at(3 * (value - 1) + 1) + dy, model_object.normal_list.at(3 * (value - 1) + 2));
                value = tri.at(j);
                glVertex3f(model_object.vertex_list.at(3 * (value - 1)) + dx, model_object.vertex_list.at(3 * (value - 1) + 1) + dy, model_object.vertex_list.at(3 * (value - 1) + 2));
            }
            glEnd();
        }
        else {
            glMaterialfv(GL_FRONT, GL_SPECULAR, now_material.Ks);
            glMaterialfv(GL_FRONT, GL_DIFFUSE, now_material.Kd);
            glLightModelfv(GL_LIGHT_MODEL_AMBIENT, now_material.Ka);
            //glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
            glBegin(GL_POLYGON);
            for (int j = 0;j < tri.size();j += 3)
            {
                int value = tri.at(j + 2);
                glNormal3f(model_object.normal_list.at(3 * (value - 1)) + dx, model_object.normal_list.at(3 * (value - 1) + 1) + dy, model_object.normal_list.at(3 * (value - 1) + 2));
                value = tri.at(j);
                glVertex3f(model_object.vertex_list.at(3 * (value - 1)) + dx, model_object.vertex_list.at(3 * (value - 1) + 1) + dy, model_object.vertex_list.at(3 * (value - 1) + 2));
            }
            glEnd();
        }
    }
    glBindTexture(GL_TEXTURE_2D, last_texture_ID);
    glutSwapBuffers();
}

void keyboard_recall(unsigned char key, int x, int y)
{
    if (key == 'a')
    {
        dx -= 0.1;
    }
    else if (key == 'd')
    {
        dx += 0.1;
    }
    else if (key == 'w')
    {
        dy += 0.1;
    }
    else if (key == 's')
    {
        dy -= 0.1;
    }
    glutPostRedisplay();
}

void mouse_recall(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON)
    {
        if (state == GLUT_DOWN)
        {
            if (moving == 0)
            {
                moving = 1;
                mouse_x = x-rot_y;
                mouse_y = -y+rot_x;
            }
        }
        else if (state == GLUT_UP)
        {
            mouse_x = -1;
            mouse_y = -1;
            moving = 0;
        }
    }
}

void mouse_move_recall(int x, int y)
{
    if (moving == 1)
    {
        rot_y = x - mouse_x;
        rot_x = y + mouse_y;
        glutPostRedisplay();
    }
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(500, 500);
    glutCreateWindow("test");
    initialize();
    glutReshapeFunc(reshape);
    //glutIdleFunc(timeadd);
    glutKeyboardFunc(keyboard_recall);
    glutMouseFunc(mouse_recall);
    glutMotionFunc(mouse_move_recall);
    glutDisplayFunc(&display);

    //load the material
    material_object.loadFile("./car_red/car.MTL");
   
    // load the model
    model_object.loadFile("./car_red/car.obj");

    glutMainLoop();

    return 0;
}

好像就沒什么好寫的了,雖然還是折騰了好幾天的orz


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM