2015-03-08 136 views
-1

我试图用手画一个十二面体(没有过度的函数调用),但我遇到了问题让人脸正确显示(我也没有使用背面剔除所以我理解它背后的数学),当我尝试使用键盘将变形应用到形状上时,它不起作用。Dodecahedron无法正确显示

这里是我的代码:

#include <cstdlib> //just in case 
#include <stdlib.h> //just in case 
#include <math.h> //powers, square roots, and trig functions are used 
#include <gl/glut.h> 
#ifndef magic 
#define magic 1.618033989 
#endif 
#ifndef magic2 
#define magic2 0.618033989 
#endif 
#ifndef PI 
#define PI 3.1415926535 
#endif 
int faces[12][5] = 
{ 
    {0, 16, 2, 10, 8}, 
    {0, 8, 4, 14, 12}, 
    {16, 17, 1, 12, 0}, 
    {1, 9, 11, 3, 17}, 
    {1, 12, 14, 5, 9}, 
    {2, 13, 15, 6, 10}, 
    {13, 3, 17, 16, 2}, 
    {3, 11, 7, 15, 13}, 
    {4, 8, 10, 6, 18}, 
    {14, 5, 19, 18, 4}, 
    {5, 19, 7, 11, 9}, 
    {15, 7, 19, 18, 6} 
}; 
double points[20][3] = 
{ 
    {1, 1, 1}, 
    {1, 1, -1}, 
    {1, -1, 1}, 
    {1, -1, -1}, 
    {-1, 1, 1}, 
    {-1, 1, -1}, 
    {-1, -1, 1}, 
    {-1, -1, -1}, 
    {0, magic2, magic}, 
    {0, magic2, -magic}, 
    {0, -magic2, magic}, 
    {0, -magic2, -magic}, 
    {magic2, magic, 0}, 
    {magic2, -magic, 0}, 
    {-magic2, magic, 0}, 
    {-magic2, -magic, 0}, 
    {magic, 0, magic2}, 
    {magic, 0, -magic2}, 
    {-magic, 0, magic2}, 
    {-magic, 0, -magic2} 
}; 
/*double radians(double d){ return d * PI/180; } 
double up[3][3] = 
{ 
    {cos(radians(0.01)), -sin(radians(0.01)), 0}, 
    {sin(radians(0.01)), cos(radians(0.01)), 0}, 
    {0, 0, 1} 
}; //up rotation matrix 
double down[3][3] = 
{ 
    {cos(radians(-0.01)), -sin(radians(-0.01)), 0}, 
    {sin(radians(-0.01)), cos(radians(-0.01)), 0}, 
    {0, 0, 1} 
}; //down rotation matrix 
double left[3][3] = 
{ 
    {cos(radians(-0.01)), 0, sin(radians(-0.01))}, 
    {0, 1, 0}, 
    {-sin(radians(-0.01)), 0, cos(radians(-0.01))} 
}; //left rotation matrix 
double right[3][3] = 
{ 
    {cos(radians(0.01)), 0, sin(radians(0.01))}, 
    {0, 1, 0}, 
    {-sin(radians(0.01)), 0, cos(radians(0.01))} 
}; //right rotation matrix 
*/ 
void cross(double a[], double b[], double vec1[]){ //gets the cross product of a and b and stores it in vec1 
    vec1[0] = a[1] * b[2] - a[2] * b[1]; 
    vec1[1] = a[2] * b[0] - a[0] * b[2]; 
    vec1[2] = a[0] * b[1] - a[1] * b[0]; 
} 
void getNormal(int n, int m, int x, double vec1[]){ //gets the normal vector 
    double a[] = {points[m][0] - points[n][0], points[m][1] - points[n][1], points[m][2] - points[n][2]}; 
    double b[] = {points[m][0] - points[x][0], points[m][1] - points[x][1], points[m][2] - points[x][2]}; 
    cross(a, b, vec1); 
} 
double dot(double a[], double b[]){ //dot product 
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 
} 
double mag(double a[]){ //magnitude of given vector 
    return sqrt(pow(a[0], 2) + pow(a[1], 2) + pow(a[2], 2)); 
} 
bool isForwardFacing(int face[5]){ 
    double vec1[3]; 
    getNormal(face[0], face[1], face[2], vec1); //vec1 is the normal vector 
    double vec2[] = {points[face[1]][0], points[face[1]][1], points[face[1]][2]}; 
    double test = dot(vec1, vec2)/(mag(vec1) * mag(vec2)); 
    if(test > 0) 
     return true; 
    else 
     return false; 
} 
//these rotations rotate the shape by 0.01 degrees 
/*void rotateUp(){ //positive rotation about z axis 
    for(int i = 0; i < 20; i++){ 
     for(int j = 0; j < 3; j++){ 
      points[i][j] = points[i][0] * up[0][j] + points[i][1] * up[1][j] + points[i][2] * up[2][j]; 
     } 
    } 
} 
void rotateLeft(){ //negative rotation about y axis 
    for(int i = 0; i < 20; i++){ 
     for(int j = 0; j < 3; j++){ 
      points[i][j] = points[i][0] * left[0][j] + points[i][1] * left[1][j] + points[i][2] * left[2][j]; 
     } 
    } 
} 
void rotateDown(){ //negative rotation about z axis 
    for(int i = 0; i < 20; i++){ 
     for(int j = 0; j < 3; j++){ 
      points[i][j] = points[i][0] * down[0][j] + points[i][1] * down[1][j] + points[i][2] * down[2][j]; 
     } 
    } 
} 
void rotateRight(){ //positive rotation about y axis 
    for(int i = 0; i < 20; i++){ 
     for(int j = 0; j < 3; j++){ 
      points[i][j] = points[i][0] * right[0][j] + points[i][1] * right[1][j] + points[i][2] * right[2][j]; 
     } 
    } 
} */ 
void myFunc(unsigned char key, int x, int y){ 
    if(key == 'w' || key == 'W'){ 
     glPopMatrix(); 
     glRotated(0.01, 0.0, 0.0, 1.0); 
      glPushMatrix(); 
    } 
    else if(key == 'a' || key == 'A'){ 
     glPopMatrix(); 
     glRotated(0.01, 0.0, -1.0, 0.0); 
      glPushMatrix(); 
    } 
    else if(key == 's' || key == 'S'){ 
     glPopMatrix(); 
     glRotated(0.01, 0.0, 0.0, -1.0); 
      glPushMatrix(); 
    } 
    else if(key == 'd' || key == 'D'){ 
     glPopMatrix(); 
     glRotated(0.01, 0.0, 1.0, 0.0); 
      glPushMatrix(); 
    } 
} 
void display(){ 
    glClear(GL_COLOR_BUFFER_BIT); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glOrtho(-3.0, 3.0, -3.0, 3.0, -3.0, 3.0); 

    glPushMatrix(); 

    for(int i = 0; i < 12; i++){ 
     if(isForwardFacing(faces[i])){ 
      glColor3f(1.0,0.0,0.0); 
      glBegin(GL_TRIANGLE_FAN); 
      for(int x = 0; x < 5; x++) 
       glVertex3dv(points[faces[i][x]]); 
      glEnd(); 
      glColor3f(0.0,1.0,0.0); 
      glBegin(GL_LINES); 
      for(int x = 0; x < 5; x++) 
       glVertex3dv(points[faces[i][x]]); 
      glEnd(); 
     } 
    } 
    glFlush(); 
} 
int main(int argc, char **argv){ 
    //boilerplate stuff 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
    glutInitWindowSize(1000, 1000); 
    glutCreateWindow("Dodecahedron"); 
    glutDisplayFunc(display); 
    glutKeyboardFunc(myFunc); //animation function 
    glutMainLoop(); 
    return 0; 
} 
+0

由于这个问题表示,这是形式的请求“这里是我的代码,请帮我修复”。这通常是不被接受的,因为一方面它要求SO成员为你解决问题,另一方面这意味着这个问题及其答案可能不会对任何人有利,除了你。在这种情况下,我确实回答了这个问题,因为我曾希望核心问题是一个几何问题,但坐标解决得很好,所以事后我认为这不是一个特别有用的问题。因此,我的downvote。未来,集中力量*单一问题*。 – MvG 2015-03-09 13:07:43

回答

0

有几件事情你的代码错误:

  1. 你总是在重新初始化显示功能模型视图矩阵。因此,键盘功能中的任何矩阵修改都将无效。

  2. 您可能想要在glMatrixMode(GL_PROJECTION)之后执行glOrtho调用,因为您要在其中设置投影。

  3. 你可能会放弃所有的推动和弹出的矩阵,因为你只修改当前矩阵,并且从不需要恢复以前的状态。

  4. 您需要在键盘功能glutPostRedisplay触发重新显示。

  5. 您正在旋转0.01°,这是一个非常小的数量。尝试10°的初学者,一旦你对所有其他人感到满意,就调整一下。

  6. 由于您不重复顶点,因此您应该绘制GL_LINE_STRIP而不是GL_LINES。但即使如此,您仍然需要重复每个五边形的第一个顶点来关闭它。

  7. 您的isForwardFacing函数不考虑当前的模型视图矩阵,所以它会导致缺少面。我想我会离开脸部剔除OpenGL,或者只是渲染所有面部。

  8. 如果你禁用了前向检查,你可能会从场景后面得到对象,因为你没有glEnable(GL_DEPTH_TEST)

  9. 您不需要为您的glOrtho呼叫考虑窗口的宽高比。

  10. 标题应该被称为<GL/glut.h>而不是<gl/glut.h>。在操作系统上,对于文件名称而言,这很重要。

  11. myFunc是一个相当不具名的函数名称。

你可以尝试这样的事情:

void myFunc(unsigned char key, int x, int y){ 
    if(key == 'w' || key == 'W') 
     glRotated(10.0, 0.0, 0.0, 1.0);       // changed 
    else if(key == 'a' || key == 'A') 
     glRotated(10.0, 0.0, -1.0, 0.0);      // changed 
    else if(key == 's' || key == 'S') 
     glRotated(10.0, 0.0, 0.0, -1.0);      // changed 
    else if(key == 'd' || key == 'D') 
     glRotated(10.0, 0.0, 1.0, 0.0);       // changed 
    // all glPopMatrix() and glPushMatrix() calls removed  // removed 
    glutPostRedisplay();          // added 
} 

void reshape(int w, int h){          // added 
    double aspect = double(w)/double(h);      // added 
    glEnable(GL_DEPTH_TEST);         // added 
    glMatrixMode(GL_PROJECTION);        // added 
    glOrtho(-3.0 * aspect, 3.0 * aspect, -3.0, 3.0, -3.0, 3.0); // changed 
    glMatrixMode(GL_MODELVIEW); // rotations apply to this 
} 

void display(){ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // changed 
    for (int i = 0; i < 12; i++) { 
     // if (!isForwardFacing(faces[i])) continue;   // removed 
     glColor3f(1.0,0.0,0.0); 
     glBegin(GL_TRIANGLE_FAN); 
     for(int x = 0; x < 5; x++) 
      glVertex3dv(points[faces[i][x]]); 
     glEnd(); 
     glColor3f(0.0,1.0,0.0); 
     glBegin(GL_LINE_STRIP);         // changed 
     for(int x = 0; x < 5; x++) 
      glVertex3dv(points[faces[i][x]]); 
     glVertex3dv(points[faces[i][0]]);      // added 
     glEnd(); 
    } 
    glFlush(); 
} 

int main(int argc, char **argv){ 
    //boilerplate stuff 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
    glutInitWindowSize(1000, 1000); 
    glutCreateWindow("Dodecahedron"); 
    glutDisplayFunc(display); 
    glutReshapeFunc(reshape);         // added 
    glutKeyboardFunc(myFunc); 
    glutMainLoop(); 
    return 0; 
}