1

在我的程序中,我试图将 .obj 文件导入 OpenGL,但是如果我计算法线并使用它们,我会得到错误的结果:(计算法线,对我来说接缝没问题,但结果不是我想要的)

结果

 void CalcNormals(float * normals_ptr, float vertex_array[8000], int face_array[8000], int face_counter)
 {

   int counter = 0;

   float normalx = 0;
   float normaly = 0;
   float normalz = 0;

   float x0 = 0;
   float y0 = 0;
   float z0 = 0;

   float x1 = 0;
   float y1 = 0;
   float z1 = 0;

   float x2 = 0;
   float y2 = 0;
   float z2 = 0;


   while(counter < face_counter)
   {
     x0 = vertex_array[face_array[counter+0]*3+0];
     y0 = vertex_array[face_array[counter+0]*3+1];
     z0 = vertex_array[face_array[counter+0]*3+2];

     x1 = vertex_array[face_array[counter+1]*3+0];
     y1 = vertex_array[face_array[counter+1]*3+1];
     z1 = vertex_array[face_array[counter+1]*3+2];

     x2 = vertex_array[face_array[counter+2]*3+0];
     y2 = vertex_array[face_array[counter+2]*3+1];
     z2 = vertex_array[face_array[counter+2]*3+2];

     normalx = (y1-y0)*(z2-z0)-(z1-z0)*(y2-y0);
     normaly = (z1-z0)*(x2-x0)-(x1-x0)*(z2-z0);
     normalz = (x1-x0)*(y2-y0)-(y1-y0)*(x2-x0);


     normals_ptr[counter+0] = normalx;
     normals_ptr[counter+1] = normaly;
     normals_ptr[counter+2] = normalz;

     printf("TEST : %f   %f   %f\n", normalx, normaly, normalz);

     printf("FACES : %i\n", face_array[counter]);
     counter += 3;
   }

 }

void LoadObject(char * path, int size,
        float vector_array[80000], int * vector_counter, int * vector_loop,
        int face_array[80000], int * face_counter, int * face_loop,
        float normals_array[80000], int * normals_counter, int * normals_loop 
           )
{
  FILE * file;  
  char * fobj;
  fobj = malloc(size);
  int fpos = 0;

  file = fopen(path, "r");
  fread(fobj, 1, 8*size, file);

  int length_counter = 0;

  fpos = 0;
  void PrintFile()
  {
    int fpos_ = 0;
    while(fpos_ < size)
    {
      fpos_ += 1;
    }
  }


  fpos = 0;

    fpos += 7;
      while(fpos < size) //SOLANGE KEIN NEUES OBJEKT BEGINNT :
      {

    ///////////////////////////VERTEX-ARRAY////////////////////////////

    if(fobj[fpos+0] == 'v' && //WEN EIN NEUER VEKTOR BEGINNT :
       fobj[fpos+1] == ' '  )
    {
      fpos += 2;
      // WIRD DIESER IN DAS DAFÜR VORGESEHENE VEKTOR-ARRAY GESCHRIEBEN
      (*vector_loop) = 0;
      while( (*vector_loop) < 3 )
      {
        if(fobj[fpos] == '-') //wenn das vozeichen ein 'MINUS' ist wird ein buchstabe mehr genommen:
        {
          vector_array[(*vector_counter)] = strtof( &fobj[fpos], NULL );

          *vector_counter += 1;

          fpos += 10;
        }
        else // wenn kein vorzeichen vorhanden ist werden nur 8 buchstaben genommen :
        {
          vector_array[(*vector_counter)] = strtof( &(fobj[fpos]), NULL );

          (*vector_counter) += 1;

          fpos += 9;
        }
        (*vector_loop) += 1;
      }

    }

    ////////////////////////NORMALS-ARRAY///////////////////////////


    else if(fobj[fpos+0] == 'v' && //WEN EIN NEUER NORMAL-VEKTOR BEGINNT :
        fobj[fpos+1] == 'n' &&
        fobj[fpos+2] == ' '  )
    {
      fpos += 3;
      // WIRD DIESER IN DAS DAFÜR VORGESEHENE NORMALS-ARRAY GESCHRIEBEN
      (*normals_loop) = 0;
      while( (*normals_loop) < 3 )
      {
        if(fobj[fpos] == '-') //wenn das vozeichen ein 'MINUS' ist wird ein buchstabe mehr genommen:
        {
          //normals_array[(*normals_counter)] = strtof( &fobj[fpos], NULL );

          (*normals_counter) += 1;

          fpos += 10;
        }
        else // wenn kein vorzeichen vorhanden ist werden nur 8 buchstaben genommen :
        {
          //normals_array[(*normals_counter)] = strtof( &(fobj[fpos]), NULL );

          (*normals_counter) += 1;

          fpos += 9;
        }
        (*normals_loop) += 1;
      }
    }


    ////////////////////////////FACE-ARRAY///////////////////////////////

    else if(fobj[fpos+0] == 'f' &&  //wenn ein 'FACE' erkannt wird :
        fobj[fpos+1] == ' '  )
    {
      fpos += 2; //damit das 'f ' nicht mit in das Auslesen der 'FACES' einfiest.

      *face_loop = 0;
      while((*face_loop) < 3)
      {
        //wird der 1. wert in das face_array geschrieben :
        face_array[(*face_counter)] = (strtol(&fobj[fpos], NULL, 10)-1);
        printf("1.WERT : %i\n", face_array[*face_counter]);
        //wird nach einem Leerzeichen oder einem NL-Zeichen gesucht :
        length_counter = 0; //davor wird die aktuelle länge zurückgesetzt damit nicht an der falschen stelle gesucht wird.
        while(fobj[fpos+length_counter] != ' ' && fobj[fpos+length_counter] != '\n')
        {
          length_counter += 1;
        }
        fpos += length_counter+1; // '+1' weil das Leerzeichen/NL-Zeichen übersprungen werden muss da sonst die aktuelle länge = 0 ist.
        (*face_counter) += 1;
       (*face_loop)+= 1;
      }
     (*face_loop)= 0;

    }

    else // wenn kein neuer vektor beginnt : 
    {
      fpos += 1;
    }
      }
}



void InitOpt()
{

  // LIGHTING
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glShadeModel(GL_FLAT);
  //glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);


  glEnable(GL_NORMALIZE);

  glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_color);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_color);
  glLightfv(GL_LIGHT0, GL_SPECULAR, specular_color);

  glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);

  glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 3);
  glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0);
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 360);

  printf("LIGHTING : %i\n", glIsEnabled(GL_LIGHTING));
  printf("LIGHT0 : %i\n", glIsEnabled(GL_LIGHT0));

  // COLORING
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

  glEnable(GL_BLEND);

  // ENABLE CLIENTSTATES FOR CALLING MULTIBLE VALUES AT ONCE
  glEnableClientState(GL_VERTEX_ARRAY); // ENABLE GL_VERTEX_ARRAY
  glEnableClientState(GL_NORMAL_ARRAY); // ENABLE GL_NORMAL_ARRAY


  // MATERIAL

  //glEnable(GL_COLOR_MATERIAL);

  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);

  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);

  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, std_color_gray);
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, std_color_gray);
  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, std_color_black);
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular_color);
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128);



}

void RenderScene()
{



    KeyFunction();
    RotateCam(alpha_angle, beta_angle);

    spot_direction[0] = centerX-eyeX;
    spot_direction[1] = centerY-eyeY;
    spot_direction[2] = centerZ-eyeZ;

    light_position[0] = eyeX;
    light_position[1] = eyeY;
    light_position[2] = eyeZ;

    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90, aspect, near, far); //SET PERSPECTIVE

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(eyeX, eyeY, eyeZ, //SET CAMERA POSITION
          centerX, centerY, centerZ,
          upX, upY, upZ);



    // bougth clientstates have to be enabled

    int counter = 0;

    /*
    animation0 += (2*3.1415926535)/36;
    if(animation0 >= (2*3.1415923535) )
    {
      animation0 = 0;
    }
    */

    animation1 += 0.5;
    if(animation1 >= 360)
    {
      animation1 = 0;
    }


    //glRotatef(animation1, 0, 0, 1);


      glVertexPointer(3, GL_FLOAT, 0, vector_array_p0); //SET POINTER TO THE GL_VERTEX_ARRAY (p0)
      glNormalPointer(GL_FLOAT, 0, normals_array_p0); //SET NORMALS ARRAY (p1)
      glDrawElements(GL_TRIANGLES, face_counter_p0, GL_UNSIGNED_INT, face_array_p0); //DRAWS 'KURBELWELLE'


    /*
    glTranslatef(0.7, 0, -0.5);
    glRotatef(animation1*(-1), 0, 0, 1);

      glRotatef(cos(grad*animation1)*( 16), 0, 0, 1);

        glVertexPointer(3, GL_FLOAT, 0, vector_array_p1); //SET POINTER TO THE GL_VERTEX_ARRAY (p1)
        glNormalPointer(GL_FLOAT, 0, normals_array_p1); //SET NORMALS ARRAY (p1)
        glDrawElements(GL_TRIANGLES, face_counter_p1, GL_UNSIGNED_INT, face_array_p1); //DRAWS 'ZYLINDER 0'

      glRotatef(cos(grad*animation1)*(-16), 0, 0, 1);

        glTranslatef(cos(grad*animation1)*(-0.7), 2.5, 0);

          glVertexPointer(3, GL_FLOAT, 0, vector_array_p2); //SET POINTER TO THE GL_VERTEX_ARRAY (p2)
          glNormalPointer(GL_FLOAT, 0, normals_array_p2); //SET NORMALS ARRAY (p2)
          glDrawElements(GL_TRIANGLES, face_counter_p2, GL_UNSIGNED_INT, face_array_p2); //DRAWS 'ZYLINDER-KOPF 0'

        glTranslatef(cos(grad*animation1)*( 0.7), -2.5, 0);

    glRotatef(animation1, 0, 0, 1);
    glTranslatef(-0.7, 0, 0.5);


    glTranslatef(-0.7, 0, 0.5);
    glRotatef(animation1*(-1), 0, 0, 1);

      glRotatef(cos(grad*animation1)*(-16), 0, 0, 1);

        glVertexPointer(3, GL_FLOAT, 0, vector_array_p1); //SET POINTER TO THE GL_VERTEX_ARRAY (p1)
        glNormalPointer(GL_FLOAT, 0, normals_array_p1); //SET NORMALS ARRAY (p1)
        glDrawElements(GL_TRIANGLES, face_counter_p1, GL_UNSIGNED_INT, face_array_p1); //DRAWS 'ZYLINDER 1'

      glRotatef(cos(grad*animation1)*( 16), 0, 0, 1);

        glTranslatef(cos(grad*animation1)*( 0.7), 2.5, 0);

          glVertexPointer(3, GL_FLOAT, 0, vector_array_p2); //SET POINTER TO THE GL_VERTEX_ARRAY (p2)
          glNormalPointer(GL_FLOAT, 0, normals_array_p2); //SET NORMALS ARRAY (p2)
          glDrawElements(GL_TRIANGLES, face_counter_p2, GL_UNSIGNED_INT, face_array_p2); //DRAWS 'ZYLINDER-KOPF 1'

        glTranslatef(cos(grad*animation1)*(-0.7), -2.5, 0);
     */


    while( time_mark > clock() )
    {
          ;
    }
    if( time_mark <= clock() )
    {
      time_mark = clock() + (CLOCKS_PER_SEC*0.01);
      SwapBuffers();
    }
}

void CreateWindow()
{
  glutInitWindowSize(960, 540);
  glutInitWindowPosition(100, 100);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  window_id = glutCreateWindow("FACE");
}

int main(int argc, char ** argv)
{ 
  float time = (float) clock()/CLOCKS_PER_SEC;
  printf("TRY ONE : ........................…\n.............................\n\n");
  printf("LOADING...\n");

  LoadObject("/home/nikolaij/Schreibtisch/MOTOR/pyramide.obj", 800000,
         vector_array_p0, &vector_counter_p0, &vector_loop_p0,
         face_array_p0, &face_counter_p0, &face_loop_p0,
         normals_array_p0, &normals_counter_p0, &normals_loop_p0
        );

  CalcNormals(normals_array_p0, vector_array_p0, face_array_p0, face_counter_p0);

  /*
  LoadObject("/home/nikolaij/Schreibtisch/MOTOR/zylinder.obj", 800000,
         vector_array_p1, &vector_counter_p1, &vector_loop_p1,
         face_array_p1, &face_counter_p1, &face_loop_p1,
         normals_array_p1, &normals_counter_p1, &normals_loop_p1
        );

  LoadObject("/home/nikolaij/Schreibtisch/MOTOR/zylinder_kopf.obj", 800000,
         vector_array_p2, &vector_counter_p2, &vector_loop_p2,
         face_array_p2, &face_counter_p2, &face_loop_p2,
         normals_array_p2, &normals_counter_p2, &normals_loop_p2
        );
  */
  printf("TIME : %f   FACES : %i\n", (float) clock()/CLOCKS_PER_SEC - time, face_counter_p1 + face_counter_p2);
  printf("INITIALISATION\n");

  glutInit(&argc, argv);
  CreateWindow();

  printf("InitOpt\n");
  InitOpt();

  //printf("LOADING SHADER\n");
  //UseShader("/home/nikolaij/Schreibtisch/Drunken_Monkey/Shader/simple_shader.frag", 63);
  //printf("END\n");

  glutDisplayFunc(RenderScene);
  glutIdleFunc(RenderScene);

  glutReshapeFunc(ReshapeFunc);

  glutKeyboardFunc(KeyPressed);
  glutKeyboardUpFunc(KeyReleased);

  glutPassiveMotionFunc(MotionFunc);

  printf("FINISHED\n");

  glutMainLoop();

  return(0);
}

简单的 .obj 文件(立方体):

# Blender v2.76 (sub 0) OBJ File: ''
# www.blender.org
o Cube.004_Cube.005
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 1.000000 0.000000
s off
f 4//1 3//1 1//1
f 8//2 7//2 3//2
f 6//3 5//3 7//3
f 2//4 1//4 5//4
f 3//5 7//5 5//5
f 8//6 4//6 2//6
f 2//1 4//1 1//1
f 4//2 8//2 3//2
f 8//3 6//3 7//3
f 6//4 2//4 5//4
f 1//5 3//5 5//5
f 6//6 8//6 2//6

这是我的代码的一部分。(它不是很干净......)

4

0 回答 0