OpenGL, DevIL, obj loader with textures

OpenGL, DevIL, obj loader with textures

本文关键字:with textures loader obj DevIL OpenGL      更新时间:2023-10-16

我写了一个obj加载器,据我所知,所有加载工作正常,但是当我尝试绘制纹理时,它不起作用。

我已经研究了Devil,加载后没有错误,一切都有数据,但是当我绘制时,它不会显示图像只是黑色。

你们有什么可以推荐我调查的吗我已经看过一些东西,但找不到解决方案。

与我做事的方式我有一个为每个纹理创建的 MTL

装载机.h

#pragma once
#include "typedef.h"
#include <string>
#include <vector>
#include <fstream>
#include "MTL.h"
#include "../freeglut.h"
#include <iostream> // this is just for testing, you can remove this with all the cout's
class Loader
{
public:
    /**
     *  brief string location of the obj file
     *  
     *  In Order for you to Load the 3D object you need to specify its location 
     *  in a string. 
     *  
     *  
     */
    Loader( std::string input);
    ~Loader(void);

    void draw(); // this function takes the obj file and draws it
    //this can be ignored, it does not make any changes to the problem
    void move(float x, float y, float z);
    void getPos();
    void setPos(float x, float y, float z); // set position
    void find_box(float &maxX,float &minX,float &maxY, float &minY, float &maxZ,float &minZ);
private:


    std::ifstream m_inFile;
    // the list of vectors that i will be using
    std::vector<points> m_points;
    std::vector<normal> m_normals;
    std::vector<coordinate> m_coords;
    std::vector<MTL> m_mtl;
    std::vector<face> m_faces;
    void process(std::string input);
    void processMTL(std::string input);
    void inputPoints(points temp);
    void inputNormals(normal temp);
    void inputCoordinates(coordinate temp);
    void createFaces(face temp);

};

装载机.cpp

void Loader::process(std::string input)
{
    std::string identifier; //used to identify where the input should go

    points temppoint;
    normal tempnormal;
    coordinate tempcoord;
    face tempface; 

    std::string read;       // used to read the curent line
    int readNum; // this is the number that has just been read in
    char skip; // a char to skip thr /
    int i;
    int count= 1;
    //other things to take into account
    //****************************************
    std::string l_name;
    bool firstRun = true;
    std::string parse;
    //**************************************

    m_inFile.open(input);

    //creation of the reading loop
    m_inFile >> identifier;
    do {
         // check to see what the opening is
        if (identifier =="#")
        {
            getline(m_inFile,read); // use this to read the whole line
        }
        else if(identifier == "v")
        {
            m_inFile >> temppoint.x >> temppoint.y >> temppoint.z;
            inputPoints(temppoint);
        }
        else if(identifier == "vn")
        {
            m_inFile >> tempnormal.vn[0] >> tempnormal.vn[1] >> tempnormal.vn[2];
            inputNormals(tempnormal);
        }
        else if (identifier == "vt")
        {
            m_inFile >> tempcoord.vt[0] >> tempcoord.vt[1] >> tempcoord.vt[2];
            inputCoordinates(tempcoord);
        }
        else if(identifier == "f")
        {

            for( i =0; i < 3; i++)
            {
                count++;

                m_inFile >> readNum;
                if(readNum == 0)
                    break;
                readNum--;
                tempface.p[i].x = m_points[readNum].x;
                tempface.p[i].y = m_points[readNum].y;
                tempface.p[i].z = m_points[readNum].z;

                m_inFile >> skip >> readNum;
                readNum--;
                tempface.coord[i].vt[0] = m_coords[readNum].vt[0];
                tempface.coord[i].vt[1] = m_coords[readNum].vt[1];
                tempface.coord[i].vt[2] = m_coords[readNum].vt[2];

                m_inFile >> skip >> readNum;
                readNum--;
                tempface.norm[i].vn[0] = m_normals[readNum].vn[0];
                tempface.norm[i].vn[1] = m_normals[readNum].vn[1];
                tempface.norm[i].vn[2] = m_normals[readNum].vn[2];

            }
            tempface.name = l_name; // this gives the mtl name to the face so it can be compared and applied later
            createFaces(tempface);
        }
        else if(identifier =="mtllib")
        {
            m_inFile >> identifier;
            identifier = "test/" + identifier;
            processMTL(identifier);
        }
        else if(identifier == "usemtl")
        {
        // chnages the mtl that is being applied
            m_inFile >> read;
            l_name = read; // so the face can have 
        }
        else 
        {
            getline(m_inFile,read);
            std::cout << "Not Processed From Loader" << identifier << " " << read <<std::endl;
        }
        m_inFile >> identifier;
    } while (!m_inFile.eof());
    //m_inFile.close();
    //m_inFile.~basic_ifstream();
}

void Loader::draw()
{
    int i;
    int j;
    int k;
    std::string currentTex;
    glEnable(GL_TEXTURE_2D);
    //glDisable(GL_TEXTURE_2D);
    //glBegin(GL_TRIANGLES);
    for (i=0; i < m_faces.size();i++)
    {
        //bind a certain image 
        for (k=0; k<m_mtl.size();k++)
        {
            if (m_mtl[k].compare(m_faces[i].name) == true)
            {
                //these next two lines do the same thing
                //m_mtl[k].draw();
                glBindTexture(GL_TEXTURE_2D,m_mtl[k].getGLID());
                //break; // break out of the loop
            }
        }
        glBegin(GL_TRIANGLES);
        for(j = 0 ; j < 3; j++)
        {
            glNormal3f(m_faces[i].norm[j].vn[0],m_faces[i].norm[j].vn[1],m_faces[i].norm[j].vn[2]);
            glTexCoord2f(m_faces[i].coord[j].vt[0],m_faces[i].coord[j].vt[1]);
            glVertex3f(m_faces[i].p[j].x,m_faces[i].p[j].y,m_faces[i].p[j].z);
        }
        glEnd();
    }
}


void Loader::processMTL(std::string input)
{
    std::string identifier;
    std::string read; //for reading whole lines
    MTL mtlTemp;
    std::ifstream l_inMtl;
    //for reading in numbers to give to the mtl
    float ka0, ka1, ka2;
    float kd0, kd1, kd2;
    float ks0, ks1, ks2;
    //so that an empty mtl is not pushed back into the vector
    bool firstRun = true;
    l_inMtl.open(input);
    l_inMtl >> identifier;
    do{
        if(identifier == "#")
        {
            getline(l_inMtl,read);
        }
        else if(identifier == "newmtl")
        {
            //checks to see if it has run before if it has not run before don't push back the last read
            if (firstRun == false)
                m_mtl.push_back(mtlTemp);
            else 
                firstRun = false;

            l_inMtl >> identifier;
            mtlTemp.setName(identifier);
        }
        else if(identifier == "Ka")
        {
            l_inMtl >>ka0 >> ka1 >> ka2;
            mtlTemp.setKa(ka0,ka1,ka2);
        }
        else if(identifier == "Kd")
        {
            l_inMtl >> kd0 >>kd1 >> kd2;
            mtlTemp.setKd(kd0,kd1,kd2);
        }
        else if(identifier =="Ks")
        {
            l_inMtl >> ks0 >> ks1 >> ks2;
            mtlTemp.setKs(ks0, ks1, ks2);
        }
        else if(identifier == "map_Ka")
        {
            getline(l_inMtl,identifier);
            //l_inMtl >> identifier;
            mtlTemp.setLoc(identifier);
        }
        else
        {
            getline(l_inMtl,read);
            std::cout << "Not Processed MTL" << identifier << " " << read << std::endl;
        }
        l_inMtl >> identifier;
    }while(!l_inMtl.eof());
    l_inMtl.close();
    m_mtl.push_back(mtlTemp); // so the last one is pushed back
}

MTL.h

 #pragma once 

#include "../freeglut.h"
#include <string>
#include <fstream>
#include "typedef.h"
#include "../lib/IL/il.h"
#include <iostream>
//#include <IL/il.h>
class MTL
{
public:
    MTL(); //name of the file
    ~MTL(void);
    void bind(std::string bindType);// somehow set the bind type eg tile stretch ect
    void setVar(float ka0, float ka1, float ka2,float kd0, float kd1, float kd2, float ks0, float ks1, float ks2); // takes in all the inputs and sets them to the class
    void setLoc(std::string inLocation); // set the location
    void setName(std::string inName);
    void setKa(float ka0, float ka1, float ka2);
    void setKd(float kd0, float kd1, float kd2);
    void setKs(float ks0, float ks1, float ks2);
    void setNs(float inNs);
    bool compare(std::string inName); // compare the string with another
    void draw(); // change the binds
    GLuint getGLID() { return texture;};
private:
    std::string name;
    std::string location; // the location of the image
    float ka[3];
    float kd[3];
    float ks[3];

    // must have freeglut in order to use this
    BYTE *pixmap; // contains the data (not yet set)
    GLuint texture;
    //two functions that you need to load and display
    void LoadThing();
    void createTex(int width, int height, int chan);
};

MTL.cpp

#include "MTL.h"
MTL::MTL() /
{   
}
MTL::~MTL()
{
}
void MTL::setName(std::string inName)
{
    name = inName;
}



void MTL::setLoc(std::string inLocation)
{
    location = inLocation;
    LoadThing();
}
bool MTL::compare(std::string inName) // compare the string with another
{
    //return true if they are the same
    if (name == inName)
        return true;
    else
        return false;
}
void MTL::draw() // change the binds
{
    glBindTexture(GL_TEXTURE_2D, texture); 
}
void MTL::setKa(float ka0, float ka1, float ka2)
{
    ka[0] = ka0;
    ka[1] = ka1;
    ka[2] = ka2;
}
void MTL::setKd(float kd0, float kd1, float kd2)
{
    kd[0] = kd0;
    kd[1] = kd1;
    kd[2] = kd2;
}
void MTL::setKs(float ks0, float ks1, float ks2)
{
    ks[0] = ks0;
    ks[1] = ks1;
    ks[2] = ks2;
}
void MTL::LoadThing()
{
    ILuint devImg;
    ilGenImages(1,&devImg);
    ilBindImage(devImg);
    int error = ilLoadImage("marble_floor2.png");
    int e = ilGetError();
    pixmap = ilGetData();
    int width = ilGetInteger(IL_IMAGE_WIDTH);
    int height = ilGetInteger(IL_IMAGE_HEIGHT);
    int chan = ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL);
    createTex(width,height,chan);
}
void MTL::createTex(int width, int height, int chan)
{
    glEnable(GL_TEXTURE_2D);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glGenTextures(1, &texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, chan, width, height, 0, (chan == 4)?GL_RGBA: GL_RGB, GL_UNSIGNED_BYTE, pixmap);
    //no clue
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}

编辑:首先感谢那些投票给我的人,花了我一段时间才意识到,但我有很多你们不需要看到的功能,所以它被减少了。

我认为可能包含问题的地方是 画() 进程() 从加载器和 绘制() LoadThings() 从 MTL 创建Tex()

编辑:好吧,伙计们,我找到了解决方案,结果由于某种原因,OpenGL 在显示纹理时使用 glColor,所以正在做的是......OpenGL

溶液:在glBegin(poly?triangle)的正上方添加此行 glColor3f(

1.0f,1.0f,1.0f)

好吧,伙计们找到了解决方案,结果由于某种原因,OpenGL 在显示纹理时使用 glColor,所以正在做的是......OpenGL

解决方案:在glBegin(poly?三角形)glColor3f(1.0f,1.0f,1.0f)上方添加此行