在我的程序中,我试图将 .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
这是我的代码的一部分。(它不是很干净......)