加载OBJ文件,如何使用法线(#vertices< #normals) [英] Loading an OBJ file, how to use normals (#vertices < #normals)

查看:1279
本文介绍了加载OBJ文件,如何使用法线(#vertices< #normals)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个obj文件,并已成功加载对象到opengl,而不使用给定的法线。

这是它的外观:



文件的格式为:

  vxyz 
vn xyz
fx // x'y // y'z // z'

网格的显示功能如下:

  glBegin(GL_TRIANGLES ); 
所有面
{
glVertex3f(..,..,..);
glVertex3f(..,..,..);
glVertex3f(..,..,..);
}
glEnd();

结果是:



我读到对象可能看起来很平坦,因为OpenGL用于照明方程的默认法线向量。

这可以用法线解决。提供的法线是780和顶点155.



我试过在每个glVertex3f调用之前使用glNorm,但obj看起来完全怪异(线等)。



我该怎么办?



EDIT#1:
我读取文件:

  void loader(class mesh& tree)
{
int vx1, vx2,vx3,vn1,vn2,vn3;
ifstream file;
string line;
point vec,norm;
face tempface;

file.open(tree.obj);
if(file.is_open()== true)
{
while(getline(file,line))
{
if(line.substr 2)==)continue;
else if(line.substr(0,2)==v)
{
istringstream numbers(line.substr(2));
numbers>> vec.x>> vec.y>> vec.z;
tree.vectors.push_back(vec);
}
else if(line.substr(0,2)==vn)
{
istringstream numbers(line.substr(2));
numbers>> norm.x>> norm.y>> norm.z;
tree.normals.push_back(norm);
}
else if(line.substr(0,2)==f)
{
face f;
line = line.substr(2,line.length());
for(string :: iterator it = line.begin(); it!= line.end(); ++ it)
{
if(* it =='/'
{
//擦除两个//
line.erase(it);
line.erase(it);
//在数字之间添加一个空格
line.insert(it,'');
}
}
istringstream inp(line);
inp>> f.vert_indices [0]>> f.norm_indices [0]> f.vert_indices [1]> f.norm_indices [1]>> f.vert_indices [2]> f.norm_indices [2];
tree.faces.push_back(f);
}
else
continue;
}
file.close();
}
}

这是我的显示方式:

  void mesh :: displayMesh()
{
glPushMatrix
glBegin(GL_TRIANGLES);
for(vector< face> :: const_iterator it = faces.begin();
it!= faces.end(); ++ it)
{
// glVertex3f (normals [it-> norm_indices [0] -1] .x,normals [it-> norm_indices [0] -1] .y,normals [it-> norm_indices [0] -1] .z);
glVertex3f(vectors [it-> vert_indices [0] -1] .x,vectors [it-> vert_indices [0] -1] .y,vectors [it-> vert_indices [0] -1 ]。
// glVertex3f(normals [it-> norm_indices [1] -1] .x,normals [it-> norm_indices [1] -1] .y,normals [it-> norm_indices [1] -1]。
glVertex3f(vectors [it-> vert_indices [1] -1] .x,vectors [it-> vert_indices [1] -1] .y,vectors [it-> vert_indices [1] -1 ]。
// glVertex3f(normals [it-> norm_indices [2] -1] .x,normals [it-> norm_indices [2] -1] .y,normals [it-> norm_indices [2] -1]。
glVertex3f(vectors [it-> vert_indices [2] -1] .x,vectors [it-> vert_indices [2] -1] .y,vectors [it-> vert_indices [2] -1 ]。
}
glEnd();
glPopMatrix();
}

在openGL的Render函数中调用函数displayMesh,并调用加载器函数到设置OpenGL函数,网格树对象是一个全局变量。



编辑#2:
法线:


这是OpenGL的安装函数的代码

解决方案<

  //擦除两个//
it = line.erase(it);
it = line.erase(it);
//在数字之间添加一个空格
it = line.insert(it,'');

但您可以擦除一次,然后替换

  //擦除两个//
it = line.erase(it);
//在数字之间添加一个空格
* it ='';


I have an obj file and have succesfully loaded the object to opengl without using the normals given.
This is how it looks:

The format of the file is:

v x y z
vn x y z
f x//x' y//y' z//z'

The displaying function of the mesh is like that:

glBegin(GL_TRIANGLES);
for all faces
{
    glVertex3f(.., .., ..);
    glVertex3f(.., .., ..);
    glVertex3f(.., .., ..);
}
glEnd();

And the result is this:

I've read that the object might look flat due to the default normal vector that OpenGL uses for lighting equations.
This could be solved with normals. The normals given are 780 and the vertices 155.

I've tried using glNorm before each glVertex3f call but the obj looks completely weird (lines, etc).

What should I do?

EDIT #1: This is how I read the file:

void loader(class mesh &tree)
{
int vx1, vx2, vx3, vn1, vn2, vn3;
ifstream file;
string line;
point vec, norm;
face tempface;

file.open("tree.obj"); 
if (file.is_open() == true)
{
    while(getline(file, line) )
    {
        if (line.substr(0,2) == "") continue;
        else if (line.substr(0, 2) == "v ")
        {
            istringstream numbers(line.substr(2));
            numbers >> vec.x >> vec.y >> vec.z;
            tree.vectors.push_back(vec);
        }
        else if (line.substr(0,2) == "vn")
        {
            istringstream numbers(line.substr(2));
            numbers >> norm.x >> norm.y >> norm.z;
            tree.normals.push_back(norm);
        }
        else if (line.substr(0,2) == "f ")
        {
            face f;
            line = line.substr(2,line.length());
            for (string::iterator it = line.begin(); it != line.end(); ++it)
            {
                if (*it == '/')
                {
                    //erase both of the "//"
                    line.erase(it);
                    line.erase(it);
                    //add a space between the numbers
                    line.insert(it, ' ');
                }
            }
            istringstream inp(line);
            inp >> f.vert_indices[0] >> f.norm_indices[0] >> f.vert_indices[1] >> f.norm_indices[1] >> f.vert_indices[2] >> f.norm_indices[2];
            tree.faces.push_back(f);
        }
        else 
            continue;
    }
    file.close();
}
}

And this is how I am displaying it:

    void mesh::displayMesh()
{
    glPushMatrix();
    glBegin(GL_TRIANGLES);
    for(vector<face>::const_iterator it = faces.begin();
        it != faces.end(); ++it)
    {
        //glVertex3f(normals[it->norm_indices[0] -1 ].x, normals[it->norm_indices[0] -1 ].y, normals[it->norm_indices[0] -1 ].z);
        glVertex3f(vectors[it->vert_indices[0] -1 ].x, vectors[it->vert_indices[0] -1 ].y, vectors[it->vert_indices[0] -1 ].z);
        //glVertex3f(normals[it->norm_indices[1] -1 ].x, normals[it->norm_indices[1] -1 ].y, normals[it->norm_indices[1] -1 ].z);
        glVertex3f(vectors[it->vert_indices[1] -1 ].x, vectors[it->vert_indices[1] -1 ].y, vectors[it->vert_indices[1] -1 ].z);
        //glVertex3f(normals[it->norm_indices[2] -1 ].x, normals[it->norm_indices[2] -1 ].y, normals[it->norm_indices[2] -1 ].z);
        glVertex3f(vectors[it->vert_indices[2] -1 ].x, vectors[it->vert_indices[2] -1 ].y, vectors[it->vert_indices[2] -1 ].z);
    }
    glEnd();
    glPopMatrix();
}

The function displayMesh is called within Render function of openGL and the loader function is called into Setup OpenGL function and the mesh tree object is a global variable.

EDIT #2: This how the tree looks with the normals:
Also this is the code of the setup function of OpenGL.

解决方案

when you use erase it invalidates the iterator

//erase both of the "//"
it = line.erase(it);
it = line.erase(it);
//add a space between the numbers
it = line.insert(it, ' ');

however you can erase once and then replace

//erase both of the "//"
it = line.erase(it);
//add a space between the numbers
*it = ' ';

这篇关于加载OBJ文件,如何使用法线(#vertices&lt; #normals)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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