1
\$\begingroup\$

So i made a obj loader in c++.I used blender to export my files. I tried to draw 2 squares(one perpendicular to the other) and when im looking at them from above some weird black triangles apear, although i have glEnable(DL_DEPTH_TEST)

I uploaded a video so you can see the problem https://www.youtube.com/watch?v=1NStm1mFkX0&feature=youtu.be

Vertex shader:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    TexCoord=texCoord;
}

Fragment Shader

#version 330 core

in vec2 TexCoord;

out vec4 color;

uniform sampler2D Texture;

void main()
{
    color = texture(Texture, TexCoord);
}

Here is my class

#ifndef MESH_H
#define MESH_H

#include "Includes.h"
#include "Shader.h"

struct Vertex
{
    glm::vec3 position;
    glm::vec3 normal;
    glm::vec2 texCoord;
    Vertex(){};
    Vertex(glm::vec3 p,glm::vec3 n,glm::vec2 t)
    {
        position=p;
        normal=n;
        texCoord=t;
    }
};

struct Material{
    char name[100];
    float ns,alpha,illum;
    float amb[3],dif[3],spec[3];
    unsigned int ID;
    string path;
    sf::Image image;
};

class Mesh
{
    public:
        void draw(Shader &shader);
        void loadMesh(const char* fileName);
    private:
        GLuint VAO,VBO,EBO;
        vector<Material>material;
        vector<Vertex> vertex;
        vector<GLuint> indices;
        void loadMaterial(Material &M,string imgPath);
        void setupMesh();
};

#endif // MESH_H

And the cpp:

void Mesh::loadMaterial(Material &M,string imgPath)
{
    M.path=imgPath;
    M.image.loadFromFile(imgPath);

    M.image.flipVertically();
    glGenTextures(1,&M.ID);
    glBindTexture(GL_TEXTURE_2D,M.ID);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, M.image.getSize().x, M.image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, M.image.getPixelsPtr());
}

void Mesh::loadMesh(const char* fileName)
{
    int i,j,number1,number2,number3,indNormal1,indNormal2,indNormal3,indTC1,indTC2,indTC3,nrFace=0,nrInd=-1;
    char text[256],matName[256],path[256];

    vector<string>tmp;
    vector<string>line;
    vector<glm::vec3>position;
    vector<glm::vec3>normal;
    vector<glm::vec2>texCoord;
    vector<glm::vec3>vertexNormal;
    vector<glm::vec2>texCoordCopy;
    ifstream fin;
    string imageName;
    glm::vec3 v;
    glm::vec2 t;

    fin.open(fileName);
    while(!fin.eof())
    {
        fin.getline(text,256);
        line.push_back(text);
    }
    fin.close();

    string matFileName;
    matFileName=fileName;
    matFileName.resize(matFileName.size()-3);
    matFileName+="mtl";

    fin.open(matFileName.c_str());
    while(!fin.eof())
    {
        fin.getline(text,200);
        tmp.push_back(text);
    }
    fin.close();


    for(i=0;i<tmp.size();i++)///READ MATERIALS
    {
        Material M;
        if(tmp[i][0]=='\n')
            continue;
        if(tmp[i][0]=='n'&&tmp[i][1]=='e'&&tmp[i][2]=='w')
        {
            sscanf(tmp[i++].c_str(),"newmtl %s",&M.name);
            if(tmp[i][0]=='N'&&tmp[i][1]=='s')
                sscanf(tmp[i++].c_str(),"Ns %f",&M.ns);
            if(tmp[i][0]=='K'&&tmp[i][1]=='a')
                sscanf(tmp[i++].c_str(),"Ka %f %f %f",&M.amb[0],&M.amb[1],&M.amb[2]);
            if(tmp[i][0]=='K'&&tmp[i][1]=='d')
                sscanf(tmp[i++].c_str(),"Kd %f %f %f",&M.dif[0],&M.dif[1],&M.dif[2]);
            if(tmp[i][0]=='K'&&tmp[i][1]=='s')
                sscanf(tmp[i++].c_str(),"Ks %f %f %f",&M.spec[0],&M.spec[1],&M.spec[2]);
            if(tmp[i][0]=='K'&&tmp[i][1]=='e')
                i++;
            if(tmp[i][0]=='N'&&tmp[i][1]=='i')
                i++;
            if(tmp[i][0]=='d'&&tmp[i][1]==' ')
                sscanf(tmp[i++].c_str(),"d %f",&M.alpha);
            if(tmp[i][0]=='i'&&tmp[i][1]=='l')
                sscanf(tmp[i++].c_str(),"illum %f",&M.illum);
            if(tmp[i][0]=='m'&&tmp[i][1]=='a')
            {
                tmp[i].erase(tmp[i].begin(),tmp[i].begin()+7);
                i++;
            }
            imageName=fileName;
            for(j=imageName.size()-1;j>=0;j--)
                if(imageName[j]=='/')
                    break;
            imageName.erase(imageName.begin()+j+1,imageName.end());
            imageName+=tmp[i-1];
            loadMaterial(M,imageName);
            material.push_back(M);
        }
    }
    //vector<int>face;

    for(i=3;i<line.size();i++)///READ THE MESHES
    {
       if(line[i][0]=='v'&&line[i][1]==' ')
        {
            sscanf(line[i].c_str(),"v %f %f %f",&v.x,&v.y,&v.z);
            position.push_back(v);
        }
        else if(line[i][0]=='v'&&line[i][1]=='t')
        {
            sscanf(line[i].c_str(),"vt %f %f",&t.x,&t.y);
            texCoord.push_back(t);
        }
        else if(line[i][0]=='v'&&line[i][1]=='n')
        {
            sscanf(line[i].c_str(),"vn %f %f %f",&v.x,&v.y,&v.z);
            normal.push_back(v);
        }
        else if(line[i][0]=='s'&&line[i][1]==' ')
            continue;
        else if(line[i][0]=='u'&&line[i][1]=='s'&&line[i][2]=='e')
        {
            sscanf(line[i].c_str(),"usemtl %s",&matName);
            //face.push_back(nrFace);
        }
        else if(line[i][0]=='f'&&line[i][1]==' ')
        {
            nrFace++;
            sscanf(line[i].c_str(),"f %d/%d/%d %d/%d/%d %d/%d/%d",&number1,&indTC1,&indNormal1,
                                                                  &number2,&indTC2,&indNormal2,
                                                                  &number3,&indTC3,&indNormal3);
            indices.push_back(number1-1);
            indices.push_back(number3-1);
            indices.push_back(number2-1);

            if(position.size()>vertexNormal.size())
                vertexNormal.resize(position.size());
            if(position.size()>texCoordCopy.size())
                texCoordCopy.resize(position.size());
            vertexNormal[number1-1]=normal[indNormal1-1];
            vertexNormal[number2-1]=normal[indNormal2-1];
            vertexNormal[number3-1]=normal[indNormal3-1];
            texCoordCopy[number1-1]=texCoord[indTC1-1];
            texCoordCopy[number2-1]=texCoord[indTC2-1];
            texCoordCopy[number3-1]=texCoord[indTC3-1];
        }
    }
    //face.push_back(nrFace+1);

    for(i=0;i<position.size();i++)
        vertex.push_back(Vertex(position[i],vertexNormal[i],texCoordCopy[i]));
    setupMesh();
    fin.close();
}

void Mesh::setupMesh()
{
    int i;

    glGenVertexArrays(1, & VAO);
    glGenBuffers(1, & VBO);
    glGenBuffers(1, & EBO);
    glBindVertexArray( VAO);
    glBindBuffer(GL_ARRAY_BUFFER,  VBO);

    glBufferData(GL_ARRAY_BUFFER,  vertex.size() * sizeof(Vertex),
                 & vertex[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,  EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,  indices.size() * sizeof(GLuint),
                 & indices[0], GL_STATIC_DRAW);
    // Vertex Positions
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                         (GLvoid*)0);
    // Vertex Normals
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                         (GLvoid*)offsetof(Vertex, normal));
    // Vertex Texture Coords
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
                         (GLvoid*)offsetof(Vertex, texCoord));
    glBindVertexArray(0);
}

void Mesh::draw(Shader &shader)
{
    int i,j,ind;

    //glEnable(GL_DEPTH_TEST);
    shader.Use();

    glBindTexture(GL_TEXTURE_2D, material[0].ID);
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

The loadMesh() fuction gets a fileName(the exemple.obj file) and reads the content from it.Also it reads the exemple.mtl file content.Then it starts building the data from that file.The first file is the mtl file.It reads all the parameters and saves them into the vectormaterial .Then the function builds data from the obj file.

Then the setupMesh function uses the opengl functions. I know that my code is incomplete since my program doesnt know which texture to bind for each face,it just binds the first one.But i have a model which has only one texture so i figured it should work.

\$\endgroup\$
  • \$\begingroup\$ Note that the OBJ file format allows faces to have more than 3 vertices. If you care about handling/rejecting this, you need to consider the possibility of polygonal faces. \$\endgroup\$ – Lars Viklund Feb 6 '16 at 13:16
  • \$\begingroup\$ Thats not the problem.I used the "Triangulate Faces" option when i exported the model \$\endgroup\$ – Robert Puscasu Feb 6 '16 at 13:39
  • \$\begingroup\$ Thus the note, trying to encourage you to document or augment your question to avoid actual answers going down that track. \$\endgroup\$ – Lars Viklund Feb 6 '16 at 17:30
-1
\$\begingroup\$

Try using glCullFace( GL_BACK );

\$\endgroup\$
  • \$\begingroup\$ This answer could use a little fleshing out. \$\endgroup\$ – Draco18s Feb 5 '16 at 20:59
  • \$\begingroup\$ yeah but my english is not the best, and he can go to the documentation to see it is for the draw priority order =/ khronos.org/opengles/sdk/docs/man/xhtml/glCullFace.xml \$\endgroup\$ – japr Feb 5 '16 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.