2

obj ファイルがあり、指定された法線を使用せずにオブジェクトを opengl に正常にロードしました。 ファイルの形式は次の
とおりです。
法線のない木

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

メッシュの表示機能は次のようになります。

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

結果は次のとおりです。
ここに画像の説明を入力

OpenGL が照明方程式に使用するデフォルトの法線ベクトルが原因で、オブジェクトが平らに見える可能性があることを読みました。
これは法線で解決できます。指定された法線は 780 で、頂点は 155 です。

各 glVertex3f 呼び出しの前に glNorm を使用しようとしましたが、obj は完全に奇妙に見えます (行など)。

私は何をすべきか?

編集#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(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();
}
}

そして、これは私がそれを表示する方法です:

    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();
}

関数 displayMesh は openGL の Render 関数内で呼び出され、ローダー関数は Setup OpenGL 関数内で呼び出され、メッシュ ツリー オブジェクトはグローバル変数です。

編集 #2: ツリーが法線でどのように見えるか:
法線のある木 また、これはOpenGL のセットアップ関数のコードです。

4

2 に答える 2

0

代わりに、描画コードに次のものを含めるべきではありませんか?

glNormal3f(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);
glNormal3f(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);
glNormal3f(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);

編集:おっと、あなたはすでにそれを実現しました

法線が正しいかどうかを確認する場合は、法線に従って各頂点に色を付けます。glColor3f法線を使用しますが、供給します。

于 2013-02-06T21:58:51.777 に答える
0

消去を使用すると、イテレータが無効になります

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

ただし、一度消去してから置き換えることができます

//erase both of the "//"
it = line.erase(it);
//add a space between the numbers
*it = ' ';
于 2014-04-28T08:13:58.847 に答える