OpenGL:设置索引/顶点 [英] OpenGL: setting up indices/vertices

查看:145
本文介绍了OpenGL:设置索引/顶点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试在c ++中编写一个非常简单的.obj模型加载器,但在我的两个方法中,模型不能正确显示,我也想知道这两个方法中哪一个更快/更好,为什么。这是我的第一个方法:

  //顶点和索引是类Model的私有成员
//与size和indexCount相同

void Model :: loadModel(std :: string source)
{
using namespace std;

string name = source.substr(0,source.find('。'));
cout<<=== LOADING:<<< name<<===<

ifstream file;
file.open(source);
string line,v0 =,v1 =,v2 =;
string v3 =,v4 =,v5 =;
int indexCount = 0;
while(file.good())
{
getline(file,line);
if(line [0] =='v')size ++;
if(line [0] =='f')indexCount ++;
}
file.close();
size * = 3;
vertices = new float [size];
indexSize = indexCount * 3;
indices = new short [indexSize];
int count = 0;
int indexCountForFilling = 0;
file.open(source);
while(file.good())
{
getline(file,line);
if(line [0] =='v')
{
line = line.substr(2,line.length());
int oldindex = 0;

v0 = line.substr(0,line.find());
v1 = line.substr(line.find(),line.rfind(,line.find()));
v2 = line.substr(line.rfind(,line.find()),line.length());
v2 = v2.substr(line.find()+ 2,v2.length());

// 1
float temp = atof(v0.c_str());
vertices [count] = temp;
count ++;
// 2
temp = atof(v1.c_str());
vertices [count] = temp;
count ++;
// 3
temp = atof(v2.c_str());
vertices [count] = temp;
count ++;
}
else if(line [0] =='f')
{
line = line.substr(2,line.length());

int firstIndex = line.find();
v3 = line.substr(0,firstIndex);
line = line.substr(firstIndex + 1,line.length()); // + 1跳过空格

int secondIndex = line.find();
v4 = line.substr(0,secondIndex);
line = line.substr(secondIndex,line.length());

if(secondIndex + 1> = line.length())
v5 = line.substr(0,line.length());
else
v5 = line.substr(1,line.length()); // zelfde
// 1
short temp = atof(v3.c_str());
indices [indexCountForFilling] = temp;
indexCountForFilling ++;
// 2
temp = atof(v4.c_str());
indices [indexCountForFilling] = temp;
indexCountForFilling ++;
// 3
temp = atof(v5.c_str());
indices [indexCountForFilling] = temp;
indexCountForFilling ++;
}
}
cout<<顶点数量:<<<<<< endl;
cout<<Index of indexes:<<< indexCountForFilling<< endl;
cout<<=== ENDED LOADING:<<< name<<===<
file.close();
}

这是使用stringstreams的第二种方法:

  void Model :: loadModel2(std :: string source)
{
using namespace std;
string name = source.substr(0,source.find(。));
cout<<+++ LOADING ::<<< name<<+++<

ifstream file;
file.open(source);
string line;
while(file.good())
{
getline(file,line);
if(line [0] =='v')size ++;
if(line [0] =='f')indexSize ++;
}
size * = 3;
vertices = new GLfloat [size];
indexSize * = 3;
indices = new GLshort [indexSize];
cout<<\tSize:<<< size<< endl;
cout<<\tIndexSize:<< indexSize<< endl;
file.close();
file.open(source);
int count = 0;
int index = 0;
while(file.good())
{
getline(file,line);
istringstream(line);
string type;
在>>类型中;
if(type ==v)
{
float x,y,z;
在>> x>> y>> z;
vertices [count ++] = x;
vertices [count ++] = y;
vertices [count ++] = z;
}
else if(type ==f)
{
float x,y,z;
在>> x>> y>> z;
indices [index ++] = x;
indices [index ++] = y;
indices [index ++] = z;
}
}
file.close();

cout<<+++ ENDED LOADING:<<< name<<+++<
}

这两个都是初始化的代码:

  glGenBuffers(1,& vbo); 
glBindBuffer(GL_ARRAY_BUFFER,vbo);
GLfloat model_test [834]; // 834
memset(model_test,0.0f,sizeof(model_test));
for(unsigned int i = 0; i <834; i ++)model_test [i] = model.getIndex(i);
glBufferData(GL_ARRAY_BUFFER,sizeof(model_test),& model_test,GL_STATIC_DRAW);

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);

GLuint ibo;
glGenBuffers(1,& ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
GLshort indices [1656]; // 1656
memset(indices,0,sizeof(indices));
for(int i = 0; i <1656; i ++)indices [i] = model.getVertexIndex(i);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),& indices,GL_STATIC_DRAW);

最后这是正在渲染的代码:

  glBindVertexArray(vao); 
if(rasterize)glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glDrawElements(GL_TRIANGLES,model.getIndexSize(),GL_UNSIGNED_SHORT,0);

这是我应该得到的结果:



http://imgur.com/OGGDLFq



这是我得到的结果:



http:// imgur。 com / U9ZTGsG



正如你可以看到,它几乎完美加载,直到最后几个三角形



所以总而言之,我的两个问题是:

   - 这两种方法中的哪一种是从txt文件加载的最好的方法? 

- 我做渲染的错误吗?

编辑:我的猜测是,我使用错误的索引,简单文件与较少的顶点/索引,并比较每个数字的输出,似乎我已经正确地复制数据到我的应用程序。所以我的猜测是,我在我的初始化代码为openGL的错误,任何人都可以找到错误?一切都编译好...

解决方案

不要这样做

  while(file.good()){...} 



<

 

while(std :: getline(...)){...}

这是因为之后的标志( eof / / etc。 / em>输入操作失败。这意味着你会循环,因为一切都会好起来,但是 std :: getline 失败,因为它在文件的结尾,但你仍然试图解析wasn' t阅读。


I have been trying to write a very simple .obj model loader in c++ but in both of my methods the model doesn't get displayed correctly and I would also like to know which of the 2 methods is faster/better and why. this is my first method:

    //vertices&indices are private members of the class "Model"
    //same with size and indexCount

void Model::loadModel(std::string source)
{
    using namespace std;

    string name = source.substr(0,source.find('.'));
    cout<<"===LOADING: "<<name<<"==="<<endl;

    ifstream file;
    file.open(source);
    string line,v0="",v1="",v2="";
    string v3="",v4="",v5="";
    int indexCount = 0;
    while(file.good())
    {
        getline(file,line);
        if(line[0] =='v') size++;
        if(line[0] =='f') indexCount++;
    }
    file.close();
    size *= 3;
    vertices = new float[size];
    indexSize = indexCount*3;
    indices = new short[indexSize];
    int count = 0;
    int indexCountForFilling =0;
    file.open(source);
    while(file.good())
    {
        getline(file,line);
        if(line[0] == 'v')
        {
            line = line.substr(2,line.length());
            int oldindex =0;

            v0 = line.substr(0,line.find(" "));
            v1 = line.substr(line.find(" "),line.rfind(" ",line.find(" ")));
            v2 = line.substr(line.rfind(" ",line.find(" ")),line.length());
            v2 = v2.substr(line.find(" ")+2,v2.length());

            //1
            float temp = atof(v0.c_str());
            vertices[count] = temp;
            count++;
            //2
            temp = atof(v1.c_str());
            vertices[count] = temp;
            count++;
            //3
            temp = atof(v2.c_str());
            vertices[count] = temp;
            count++;
        }
        else if(line[0] == 'f')
        {
            line = line.substr(2,line.length());

            int firstIndex = line.find(" ");
            v3 = line.substr(0,firstIndex);
            line = line.substr(firstIndex+1,line.length()); //+1 to skip space

            int secondIndex = line.find(" "); 
            v4 = line.substr(0,secondIndex);
            line = line.substr(secondIndex,line.length());

            if(secondIndex+1>=line.length())
                v5 = line.substr(0,line.length()); 
            else
                v5 = line.substr(1,line.length()); //zelfde
            //1
            short temp = atof(v3.c_str());
            indices[indexCountForFilling] = temp;
            indexCountForFilling++;
            //2
            temp = atof(v4.c_str());
            indices[indexCountForFilling] = temp;
            indexCountForFilling++;
            //3
            temp = atof(v5.c_str());
            indices[indexCountForFilling] = temp;
            indexCountForFilling++;
        }
    }
    cout<<"Amount of vertices: "<<size<<endl;
    cout<<"Amount of indexes: "<<indexCountForFilling<<endl;
    cout<<"===ENDED LOADING: "<<name<<"==="<<endl;
    file.close();
}

This is the second method using stringstreams:

void Model::loadModel2(std::string source)
{
    using namespace std;
    string name = source.substr(0,source.find("."));
    cout<<"+++LOADING::"<<name<<"+++"<<endl;

    ifstream file;
    file.open(source);
    string line;
    while(file.good())
    {
        getline(file,line);
        if(line[0]=='v') size++;
        if(line[0]=='f') indexSize++;
    }
    size *= 3;
    vertices = new GLfloat[size];
    indexSize *= 3;
    indices = new GLshort[indexSize];
    cout<<"\tSize: "<<size<<endl;
    cout<<"\tIndexSize:"<<indexSize<<endl;
    file.close();
    file.open(source);
    int count = 0;
    int index = 0;
    while(file.good())
    {
        getline(file,line);
        istringstream in(line);
        string type;
        in>>type;
        if(type=="v")
        { 
            float x,y,z;
            in >> x >> y >> z;
            vertices[count++] = x;
            vertices[count++] = y;
            vertices[count++] = z;
        }
        else if(type == "f")
        {
            float x,y,z;
            in >> x >> y >> z;
            indices[index++] = x;
            indices[index++] = y;
            indices[index++] = z;
        }
    }
    file.close();

    cout<<"+++ENDED LOADING:"<<name<<"+++"<<endl;
}

This is the code where both are initialized:

glGenBuffers(1,&vbo);
    glBindBuffer(GL_ARRAY_BUFFER,vbo);
    GLfloat model_test[834]; //834
    memset(model_test,0.0f,sizeof(model_test));
    for(unsigned int i=0;i<834;i++) model_test[i] = model.getIndex(i);
    glBufferData(GL_ARRAY_BUFFER,sizeof(model_test),&model_test,GL_STATIC_DRAW);

    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));
    glEnableVertexAttribArray(0);

    GLuint ibo;
    glGenBuffers(1,&ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
    GLshort indices[1656];//1656
    memset(indices,0,sizeof(indices));
    for(int i=0;i<1656;i++) indices[i] = model.getVertexIndex(i);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),&indices,GL_STATIC_DRAW);

And finally this is the code where it is being rendered:

glBindVertexArray(vao);
    if(rasterize)glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
    else glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    glDrawElements(GL_TRIANGLES,model.getIndexSize(),GL_UNSIGNED_SHORT,0);

This is the result i should get:

http://imgur.com/OGGDLFq

This is the result i get:

http://imgur.com/U9ZTGsG

As you can see it loads almost perfectly until the last few triangles

So in conclusion my 2 questions are:

- Which of the 2 methods is the best way to load from a txt file?

- Am I doing something wrong with the rendering?

EDIT: My guess is that i'm use the wrong indices, however i've loaded a more simple file with fewer vertices/indices and compared the output of each number and it seems i've correctly copied the data into my application. So my guess is that i did something wrong in my initialization code for openGL, could anyone find the error? Everything compiles fine...

解决方案

Don't do e.g.

while (file.good()) { ... }

or similar, it will not do what you think it does.

Instead do

while (std::getline(...)) { ... }

It's because the flags (eof/bad/etc.) will not be set until after the input operation fails. This means that you will loop because everything will look good, but then std::getline fails because it's at the end of the file but you still try to parse data that wasn't read.

这篇关于OpenGL:设置索引/顶点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆