OpenGL Learning Footprints: Model loading Preliminary-loading obj model (Load obj models)

Source: Internet
Author: User

Write in front
The lighting basics, as well as the materials and lighting maps, and the types of light sources are described earlier, and we have a certain understanding of the use of lighting to enhance the realism of the scene. But so far, we've been drawing cubes with cube data that we've specified in our program, and it still looks boring. This section begins with the introduction of model loading, which enriches our scene and becomes fun by loading a rich model. The sample code for this section can be downloaded from my github.

The load model can use a better library, such as a library loaded by the OBJ model, assimp loading the library. As an introductory article, we started off by not using these libraries to load cool models, but rather familiar with the concepts of models and model loading, then we encapsulated a simple obj model load class and loaded a simple cube model.

Do not be too eager to see the beautiful 3D model, the next section we will use the ASSIMP library will load a cool 3d model, but this section is also focused on the multi-feeling model loading foundation, or the next section will be difficult to learn.

In this section, you can learn about

    • The concept of mesh
    • OBJ Model data format
    • OBJ model simple load class and load experiment
Expression of the model

In 3d graphics processing, a model is usually made up of one or more mesh (meshes), and a mesh is an independent entity that can be drawn. For example, the complex character model can be divided into the head, limbs, costumes, weapons and other parts to model, these mesh combination of the final form of the character model.

A mesh consists of vertex, edge, and Polygon faces, which contains the data needed to draw, such as vertex position, texture coordinates, normal vector, material properties, and so on, which is the smallest entity that OpenGL uses to draw. The concept of mesh is illustrated as shown (from: What's a mesh in OpenGL?) :

A mesh can contain multiple faces, a face that is a basic entity that can be drawn in a mesh, such as triangles, polygons, and points. To make the model more realistic, it is generally necessary to add more elements to refine the mesh, which, of course, is limited by hardware processing power, such as the ability to handle PC games better than mobile devices. Because polygons can be divided into triangles, and triangles are basic primitives that are supported in a graphics processor, a triangular mesh is used to model them. For example, the following figure (from: What's a mesh in OpenGL?) expresses the process of modeling a rabbit using increasingly complex mesh:

As the number of triangles increases, the rabbit model becomes more and more real.

The current model storage format is very rich, more commonly used, such as wavefront. obj File,collada, to understand the characteristics of each format, you can refer to the wiki 3D graphics file formats. In many formats, the obj format is common, and it is internally expressed in textual form, and next we understand how the model is defined and how it is loaded into OpenGL to render the model, by familiarizing yourself with the following obj format.

OBJ Model data format

The obj model is stored internally as a text, such as a cube model obtained from loading cube.obj data as follows:

# Blender3d v249 OBJ File:untitled.blend# www.blender3d.orgMtllib CUBE.MTLV1.000000-1.000000-1.000000V1.000000-1.000000 1.000000V-1.000000-1.000000 1.000000V-1.000000-1.000000-1.000000V1.000000 1.000000-1.000000V0.999999 1.000000 1.000001V-1.000000 1.000000 1.000000V-1.000000 1.000000-1.000000Vt0.748573 0.750412Vt0.749279 0.501284Vt0.999110 0.501077Vt0.999455 0.750380Vt0.250471 0.500702Vt0.249682 0.749677Vt0.001085 0.750380Vt0.001517 0.499994Vt0.499422 0.500239Vt0.500149 0.750166Vt0.748355 0.998230Vt0.500193 0.998728Vt0.498993 0.250415Vt0.748953 0.250920Vn0.000000 0.000000-1.000000VN-1.000000-0.000000-0.000000VN-0.000000-0.000000 1.000000VN-0.000001 0.000000 1.000000Vn1.000000-0.000000 0.000000Vn1.000000 0.000000 0.000001Vn0.000000 1.000000-0.000000VN-0.000000-1.000000 0.000000USEMTL material_ray.pngs OFFF5/1/1 1/2/1 4/3/1F5/1/1 4/3/1 8/4/1F3/5/2 7/6/2 8/7/2F3/5/2 8/7/2 4/8/2F2/9/3 6/Ten/3 3/5/3F6/Ten/4 7/6/4 3/5/4F1/2/5 5/1/5 2/9/5F5/1/6 6/Ten/6 2/9/6F5/1/7 8/ One/7 6/Ten/7F8/ One/7 7/ A/7 6/Ten/7F1/2/8 2/9/8 3/ -/8F1/2/8 3/ -/8 4/ -/8

Make a brief description of this text format:

    • Behavior that begins with # comment line
    • USEMTL and mtllib represent the texture-related data, parsing texture data is a little cumbersome, this section we just to illustrate the principle of loading the model, not to discuss.
    • o introduction of a new object
    • V indicates vertex position
    • VT represents vertex texture coordinates
    • VN denotes vertex normal vector
    • F represents a polygon, the polygon uses the format of 1/2/8, which represents the index of the vertex position/texture coordinate/normal vector, which is indexed in the previous data defined by V,VT,VN Note that the index of obj here is starting at 1, not 0

Models are typically modeled by 3d modeling software, such as Blender, 3DS Max, or Maya, and the data format changes when exported, and the task of importing models into OpenGL is to model a model data file, Convert to data that OpenGL can take advantage of. For example, in the obj file above, we need to parse the vertex position, texture coordinates and other data to form a mesh object that OpenGL can render.

Mesh that can be understood from obj to OpenGL

The data format of obj is explained above, so how do we express mesh in OpenGL? First define the vertex attribute data as follows:

// 表示一个顶点属性struct Vertex{    glm::vec3 position;  // 顶点位置    glm::vec2// 纹理坐标    glm::vec3 normal;  // 法向量};

The mesh contains information such as vertex properties, texture objects, and so on, this section defines the mesh data structure as follows:

//Represents the smallest entity for an OpenGL renderclassmesh{ Public:voidDraw (shader& Shader)//Draw meshMesh (Const STD:: vector<Vertex>& Vertdata, Glint Textureid)//Construct a meshPrivate:STD:: vector<Vertex>Vertdata;//Vertex dataGluint vaoid, vboid;//Cache objectGlint Textureid;//Texture Object ID    voidSetupmesh ();//create buffers such as Vao,vbo};

Loading the OBJ model is the process of reading the obj file and converting it into the mesh object above. The idea of this process is roughly the same, reading each line of the file, determining the data type according to the direction of the beginning, and then loading it into the mesh's vertdata, which is the framework:

Std::ifstreamfile(Objfilepath); while(Getline (file, line)) {if(Line.substr (0,2) =="VT")//vertex texture coordinate data{//parse vertex texture data}Else if(Line.substr (0,2) =="VN")//vertex normal vector data{//Analytic method vector data}Else if(Line.substr (0,1) =="V")//Vertex position data{//parse vertex position data}Else if(Line.substr (0,1) =="F")//Polygon Data{//Parse polygon data}Else if(line[0] ==' # ')//Note ignore{ }Else{//The rest of the content is temporarily not processed}}

The above provides a framework to read the obj file format, such as parsing texture data as follows:

if (Line.substr  (0 , 2 ) = =  "VT" )//vertex texture coordinate data {std :: Istringstream s (line (2 ))     GLM::VEC2 v    s >> v.x  ;     s >> v.y  ;  V.y  =-v.y    temp_textcoords.push  _back (v) }  

The rest are also treated similarly. Once the data has been read, the buffer data must be created in the mesh object as it was before the object was drawn, as follows:

voidSetupmesh ()  //create buffers such as Vao,vbo{glgenvertexarrays (1, &this->vaoid);glgenbuffers (1, &this->vboid);Glbindvertexarray (this->vaoid);Glbindbuffer (Gl_array_buffer, this->vboid);Glbufferdata (Gl_array_buffer, sizeof (Vertex)* this->vertdata.  Size (), &this->vertdata[0], Gl_static_draw);//Vertex position Properties    Glvertexattribpointer (0, 3, Gl_float, Gl_false, sizeof (Vertex), (glvoid*)0);Glenablevertexattribarray (0);//Vertex texture coordinates    Glvertexattribpointer (1, 2, Gl_float, Gl_false, sizeof (Vertex), (glvoid*)(3 *sizeof (gl_float)));Glenablevertexattribarray (1);//Vertex normal vector properties    Glvertexattribpointer (2, 3, Gl_float, Gl_false, sizeof (Vertex), (glvoid*)(5 *sizeof (gl_float)));Glenablevertexattribarray (2);Glbindbuffer (Gl_array_buffer, 0);Glbindvertexarray (0);}

While creating buffers, we use the cube model Cube.dds texture as shown in this section:

This is not the same as the PNG texture used before, here I used C + + to re-adapt the model loading loading DDS texture function, loading texture is not the focus of this section, you can see the GitHub code. After loading the texture, you can render the cube model of this obj expression as follows:

//Section1 从obj文件加载数据std::vector<Vertex> vertData;ObjLoader::loadFromFile("cube.obj", vertData)// Section2 准备纹理GLint textureId = TextureHelper::loadDDS("cube.dds");// Section3 建立Mesh对象Mesh mesh(vertData, textureId);// Section4 准备着色器程序Shader shader("cube.vertex""cube.frag");// 在游戏主循环中渲染立方体

As we can see here, our code is more concise than it used to be to specify a cube model in a program, and after the use of assimp loading the library, you can load more rich models, which are better than this cube. But this section still looks at the effect of the final cube, as follows:

The final note

When using a DDS texture, be aware that the y-axis of the texture is reversed relative to OpenGL, so it needs to be accessed using (coord.u, 1.0-COORD.V), which can be done while loading obj or in the shader. Not using the inverted V coordinate will cause the normal rendering, which is also a place to trap me. Later, the error was found using the data, such as the reversed data on the left and the non-inverted data on the right:

When using the Blender software to export the model, even if the includ UVs is checked, the output still does not have texture coordinates, this is because in addition to check these options, there is also a UV map operation, this is also prone to error, in detail can refer to the Add UV Mapped Texture coordinates to OBJ file?. UV Mappring The process of this operation is more cumbersome, it is no longer introduced here, it is interesting to refer to the UV Mapping a Mesh

Finally, the load obj program in this section is just an example and does not parse the Texture MTL section, and does not use texture data to draw the classic Suzanne model as shown in:

Textures and lighting are missing, so the model does not look real, and the next section will improve this when loading the library using Assimp.

Resources
    1. Https://www.quora.com/What-is-a-mesh-in-OpenGL
    2. Http://gamedev.stackexchange.com/questions/38412/whats-the-difference-between-mesh-and-a-model
    3. http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/
    4. Https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Load_OBJ
    5. http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/

OpenGL Learning Footprints: Model loading Preliminary-loading obj model (Load obj models)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.