2

アップデート

私の法線は正常に機能しているように見えますが、それは私の顔の描き方に問題があり (半分しか描かれていません)、その理由がわかりません -

頂点、法線は適切に描画されます

以前から私のコードを見ていただければ(以下に表示)


元の投稿

現在、.obj ファイル タイプのパーサー/レンダラーに取り組んでいます。法線ベクトルの表示で問題が発生しています。

法線なし:

法線の場合:

何らかの理由で、法線ベクトルの半分だけが影響を受けているのに、残りの半分は顔がまったくないかのように振る舞う理由がわかりません。

これがobjファイルにロードするための私のコードです:

    void ObjModel::Load(string filename){
    ifstream file(filename.c_str());

    if(!file) return;

    stringstream ss;
    string param, line;
    float nparam, cur;

    vector<vector<float> > coords;
    vector<float> point;

    while(getline(file, line)){ 
        ss.clear();
        ss.str(line);

        ss >> param;

        //vertex
        if(param == "v"){
            for(int i = 0; i < 3; i++){
                ss >> nparam;
                this->vertices.push_back(nparam);
            }
        }

        //face
        else if(param == "f"){
            coords.clear();
            point.clear();

            for(int i = 0; i < 3; i++){
                ss >> nparam;
                nparam--;

                for(int j = 0; j < 3; j++){
                    cur = this->vertices[nparam * 3 + j];

                    this->faces.push_back(cur);
                    point.push_back(cur);
                }

                coords.push_back(point);
            }

            point = this->ComputeNormal(coords[0], coords[1], coords[2]);

            for(int i = 0; i < 3; i++) this->normals.push_back(point[i]);
        }

        else continue;
    }
}
void ObjModel::Render(){
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);

    glVertexPointer(3, GL_FLOAT, 0, &this->faces[0]);
    glNormalPointer(GL_FLOAT, 0, &this->normals[0]);

    glDrawArrays(GL_TRIANGLES, 0, this->faces.size() / 3);

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

そして、法線ベクトルを計算する関数は次のとおりです。

vector<float> ObjModel::ComputeNormal(vector<float> v1, vector<float> v2, vector<float> v3){
vector<float> vA, vB, vX;
float mag;

vA.push_back(v1[0] - v2[0]);
vA.push_back(v1[1] - v2[1]);
vA.push_back(v1[2] - v2[2]);

vB.push_back(v1[0] - v3[0]);
vB.push_back(v1[1] - v3[1]);
vB.push_back(v1[2] - v3[2]);

vX.push_back(vA[1] * vB[2] - vA[2] * vB[1]);
vX.push_back(vA[2] * vB[0] - vA[0] * vB[2]);
vX.push_back(vA[0] * vB[1] - vA[1] * vB[0]);

mag = sqrt(vX[0] * vX[0] + vX[1] * vX[1] + vX[2] * vX[2]);

for(int i = 0; i < 3; i++) vX[i] /= mag;

return vX;}

法線ベクトルと面の数が同じであることを確認するために、既にチェックしました (私が正しければ、存在するはずです)。

前もって感謝します!:)

編集OpenGLの機能を有効/無効にする方法は次のとおりです。

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
GLfloat amb_light[] =  0.1, 0.1, 0.1, 1.0 ;
GLfloat diffuse[] = {0.6, 0.6, 0.6, 1};
GLfloat specular[] = {0.7, 0.7, 0.3, 1};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb_light);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glShadeModel(GL_SMOOTH);
glLightModeli(L_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDisable(GL_CULL_FACE);
4

3 に答える 3

1

要素を使用していますか?Objファイルは1からカウントを開始しますが、OpenGLは0からカウントを開始します。各要素から1を引くだけで、正しいレンダリングが得られるはずです。

于 2012-11-22T09:20:17.770 に答える
0
for(int i = 0; i < 3; i++) this->normals.push_back(point[i]);

これにより、面ごとに法線が 1 つだけ提供されます。頂点ごとに 1 つの法線が必要です。

于 2012-11-22T16:28:56.243 に答える