OpenGL---加载obj模型

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012319493/article/details/60330708

obj文件格式介绍:http://www.cnblogs.com/youthlion/archive/2013/01/21/2870451.html

mesh.h

#pragma once

#include "vector"
#include "iostream"
#include "string"
#include "fstream"
#include "sstream"
#include "algorithm"
#include "assert.h"
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#pragma comment(lib, "glut.lib")

using namespace std;

struct vec3
{
    double x, y, z;
};

struct vec2
{
    double x, y;
};

class Vertex
{
public: 
    int vertIndex;     // 此顶点在顶点列表中的索引
    int normIndex;     // 顶点的法线索引
    int textIndex;     // 顶点的纹理索引
};

class Face
{
public:
    vector<Vertex> vertex; // 顶点和法线索引组成的列表

    Face(){}
    ~Face(){}
};

class Mesh
{
private:
    vector<vec3> vVertex;  // 顶点数组
    vector<vec2> vText;    // 纹理数组
    vector<vec3> vNorm;    // 法线数组
    vector<Face> vFace;    // 面片数组

public:
    Mesh(){};
    ~Mesh(){};

    bool readFile(char* path);
    void drawMesh();
};

bool Mesh::readFile(char* path)
{   
    ifstream file(path);
    if (!file)
    {
        cerr << "Error::ObjLoader, could not open obj file:"
            << path << " for reading." << std::endl;
        return false;
    }
    string line;
    while (getline(file, line))
    {
        if (line.substr(0, 2) == "vt")     // 顶点纹理坐标数据
        {
            istringstream s(line.substr(2));
            vec2 v;
            s >> v.x; s >> v.y;
            //cout << "vt " << v.x << " " << v.y << endl;
            v.y = -v.y;                     // 注意这里加载的dds纹理 要对y进行反转
            vText.push_back(v);
        }
        else if (line.substr(0, 2) == "vn") // 顶点法向量数据
        {
            istringstream s(line.substr(2));
            vec3 v;
            s >> v.x; s >> v.y; s >> v.z;
            //cout << "vn " << v.x << " " << v.y << " " << v.z << endl;
            vNorm.push_back(v);
        }
        else if (line.substr(0, 1) == "v")  // 顶点位置数据
        {
            istringstream s(line.substr(1));
            vec3 v;
            s >> v.x; s >> v.y; s >> v.z;
            //cout << "v " << v.x << " " << v.y << " " << v.z << endl;
            vVertex.push_back(v);
        }
        else if (line.substr(0, 1) == "f")  // 面数据
        {
            Face face;
            //cout << "f ";
            istringstream vtns(line.substr(1));
            string vtn;
            while (vtns >> vtn)             // 处理一行中多个顶点属性
            {
                Vertex vertex;
                replace(vtn.begin(), vtn.end(), '/', ' ');
                istringstream ivtn(vtn);
                if (vtn.find("  ") != string::npos) // 没有纹理数据,注意这里是2个空格
                {
                    ivtn >> vertex.vertIndex        
                         >> vertex.normIndex;

                    vertex.vertIndex--;     //使得下标从0开始
                    vertex.normIndex--;
                }
                else
                {
                    ivtn >> vertex.vertIndex  
                         >> vertex.textIndex 
                         >> vertex.normIndex;

                    //cout <<  vertex.vertIndex << "/" << vertex.textIndex << "/" << vertex.normIndex << " ";
                    vertex.vertIndex--;   
                    vertex.textIndex--;
                    vertex.normIndex--;
                }
                face.vertex.push_back(vertex);
            }
            vFace.push_back(face);
            //cout << endl;
        }
        else if (line[0] == '#')            // 注释忽略
        { }
        else  
        {
            // 其余内容 暂时不处理
        }
    }

    return true;
}

void Mesh::drawMesh()
{ 
    if(vFace.empty())
        return;

    // 有纹理
    if(vText.size() > 0)  
    {
        for(int f = 0; f < vFace.size(); f++)  // 绘制每个面片
        {
            int n = vFace[f].vertex.size();    // 面的顶点数
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glBegin(GL_TRIANGLES);
            for(int v = 0; v < n; v++)
            {
                int it = vFace[f].vertex[v].textIndex;
                glTexCoord2f(vText[it].x, vText[it].y);

                int in = vFace[f].vertex[v].normIndex;  
                glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

                int iv = vFace[f].vertex[v].vertIndex; 
                glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
            }
            glEnd();
        }
    }
    // 没有纹理
    else                  
    {
        for(int f = 0; f < vFace.size(); f++)  // 绘制每个面片
        {
            int n = vFace[f].vertex.size();    // 面的顶点数
            glBegin(GL_TRIANGLES);
            for(int v = 0; v < n; v++)
            {
                int in = vFace[f].vertex[v].normIndex;
                glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

                int iv = vFace[f].vertex[v].vertIndex; 
                glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
            }
            glEnd();
        }
    }

    //glFlush();
}

main.cpp

#include "mesh.h"

const int windowWidth = 800;
const int windowHeight = 600;

Mesh mesh;

void myDisplay()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_NORMALIZE);
    glColor3f(1, 1, 1);

    mesh.drawMesh();

    glutSwapBuffers();
    glutPostRedisplay();
}   

void myInit()
{
    glClearColor(0, 0, 0, 0);
    glEnable(GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, windowWidth/ windowHeight, 1.0, 21.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(5, 6, 7, 0, 0, 0, 0, 1, 0);

    mesh.readFile("1.obj");
}


int main()
{
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 
    glutInitWindowPosition(50, 50); 
    glutInitWindowSize(windowWidth, windowHeight);
    glutCreateWindow("DEMO"); 

    myInit();
    glutDisplayFunc(myDisplay); 

    glutMainLoop(); 
    return 0; 
}

1.obj

# Blender3D v249 OBJ File: untitled.blend
# www.blender3d.org
mtllib cube.mtl
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 0.999999 1.000000 1.000001
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
vt 0.748573 0.750412
vt 0.749279 0.501284
vt 0.999110 0.501077
vt 0.999455 0.750380
vt 0.250471 0.500702
vt 0.249682 0.749677
vt 0.001085 0.750380
vt 0.001517 0.499994
vt 0.499422 0.500239
vt 0.500149 0.750166
vt 0.748355 0.998230
vt 0.500193 0.998728
vt 0.498993 0.250415
vt 0.748953 0.250920
vn 0.000000 0.000000 -1.000000
vn -1.000000 -0.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn -0.000001 0.000000 1.000000
vn 1.000000 -0.000000 0.000000
vn 1.000000 0.000000 0.000001
vn 0.000000 1.000000 -0.000000
vn -0.000000 -1.000000 0.000000
usemtl Material_ray.png
s off
f 5/1/1 1/2/1 4/3/1
f 5/1/1 4/3/1 8/4/1
f 3/5/2 7/6/2 8/7/2
f 3/5/2 8/7/2 4/8/2
f 2/9/3 6/10/3 3/5/3
f 6/10/4 7/6/4 3/5/4
f 1/2/5 5/1/5 2/9/5
f 5/1/6 6/10/6 2/9/6
f 5/1/7 8/11/7 6/10/7
f 8/11/7 7/12/7 6/10/7
f 1/2/8 2/9/8 3/13/8
f 1/2/8 3/13/8 4/14/8

这里写图片描述

不足:没有对纹理处理,比如没有纹理图片,缺乏相关操作等。

—————————–变一下样式———————————-
将drawMesh()修改一下(仍然没有对纹理进行处理)

void Mesh::drawMesh()
{ 
    if(vFace.empty())
        return;

    // 有纹理
    if(vText.size() > 0)  
    {
        for(int f = 0; f < vFace.size(); f++)  // 绘制每个面片
        {
            int n = vFace[f].vertex.size();    // 面的顶点数
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            glBegin(GL_TRIANGLES);
            glColor3f(1, 1, 1);
            for(int v = 0; v < n; v++)
            {
                int it = vFace[f].vertex[v].textIndex;
                glTexCoord2f(vText[it].x, vText[it].y);

                int in = vFace[f].vertex[v].normIndex;  
                glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

                int iv = vFace[f].vertex[v].vertIndex; 
                glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
            }
            glEnd();

            glBegin(GL_LINE_LOOP);
            glColor3f(0, 0, 1);
            for (int v = 0; v < n; v++)
            {
                int it = vFace[f].vertex[v].textIndex;
                glTexCoord2f(vText[it].x, vText[it].y);

                int in = vFace[f].vertex[v].normIndex;
                glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

                int iv = vFace[f].vertex[v].vertIndex;
                glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
            }
            glEnd();
        }
    }
    // 没有纹理
    else                  
    {
        for(int f = 0; f < vFace.size(); f++)  // 绘制每个面片
        {
            int n = vFace[f].vertex.size();    // 面的顶点数
            glBegin(GL_TRIANGLES);
            for(int v = 0; v < n; v++)
            {
                int in = vFace[f].vertex[v].normIndex;
                glNormal3f(vNorm[in].x, vNorm[in].y, vNorm[in].z);

                int iv = vFace[f].vertex[v].vertIndex; 
                glVertex3f(vVertex[iv].x, vVertex[iv].y, vVertex[iv].z);
            }
            glEnd();
        }
    }
}

这里写图片描述

展开阅读全文

没有更多推荐了,返回首页