2 votes

Les visages ne sont pas dessinés correctement

Mise à jour

Il semble que mes normales fonctionnent bien, mais qu'il y a un problème avec la façon dont je dessine mes visages (seule la moitié est dessinée), et je n'arrive pas à comprendre pourquoi

Vertices, normals are drawn properly

Si vous pouviez jeter un coup d'oeil à mon code d'avant (montré ci-dessous)


Poste original

Je travaille actuellement sur un analyseur/rendeur pour les types de fichiers .obj. Je rencontre un problème avec l'affichage des vecteurs normaux :

Sans normales :

Avec des normales :

Pour une raison quelconque, je n'arrive pas à comprendre pourquoi seule la moitié des vecteurs normaux ont un effet, alors que l'autre moitié agit comme s'il n'y avait pas de visage du tout.

Voici mon code pour le chargement du fichier 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);
}

Et voici la fonction pour calculer le vecteur normal :

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

J'ai déjà vérifié qu'il y a un nombre égal de vecteurs normaux et de faces (ce qui devrait être le cas, si je ne me trompe pas).

Merci d'avance ! :)

Editar Voici comment j'active/désactive les fonctionnalités d'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);

1voto

Utilisez-vous des éléments ? Les fichiers Obj commencent à compter à 1 mais OpenGL commence à compter à 0. Soustrayez simplement 1 à chaque élément et vous devriez obtenir un rendu correct.

1voto

datenwolf Points 85093

L'orientation des normaux compte. Il semble que l'orientation des faces de votre objet n'est pas constante, donc les normales des faces voisines, avec des plans similaires, pointent dans des directions opposées.

Si vous avez importé ce modèle à partir d'un fichier modèle, je vous suggère de ne pas calculer les normales dans votre code - vous ne devriez pas le faire de toute façon, puisque les artistes peuvent faire des ajustements manuels aux normales pour affiner localement l'éclairage - mais de les stocker également dans le fichier modèle. Tous les modélisateurs 3D disposent d'une fonction permettant de retourner les normales dans une orientation commune. Dans Blender par exemple, cette fonction est accessible avec le raccourci clavier CTRL + N en mode édition.

0voto

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

Cela ne fournit qu'une normale pour chaque visage. Vous avez besoin d'une normale pour chaque vertex .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X