我正在尝试手工绘制一个十二面体(没有过剩函数调用),但我有问题让脸部正确显示(我也没有使用背面剔除所以我理解它背后的数学)当我尝试使用键盘将变换应用到形状上时,它没有任何效果。
这是我的代码:
#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 :(得分:0)
您的代码有几个问题:
您始终在显示功能中重新初始化模型视图矩阵。因此,键盘功能中的任何矩阵修改都将无效。
您可能希望在glOrtho
之后执行glMatrixMode(GL_PROJECTION)
来电,因为您想在那里设置投影。
您也可以删除所有推送和弹出矩阵,因为您只需要修改当前矩阵,而不需要恢复以前的状态。
您需要键盘功能glutPostRedisplay
才能触发重新显示。
您旋转0.01°,这是一个非常小的数量。尝试10°作为初学者,一旦你对所有其他人感到满意就进行调整。
您应该绘制GL_LINE_STRIP
而不是GL_LINES
,因为您不重复顶点。但即使这样,你也需要重复每个五边形的第一个顶点来关闭它。
您的isForwardFacing
函数未考虑当前模型视图矩阵,因此会导致缺少面。我想我会将脸部剔除到OpenGL,或者只是渲染所有脸部。
如果您禁用向前检查,则由于您没有glEnable(GL_DEPTH_TEST)
,您可能会从前面的对象中获取对象。
您的glOrtho
电话不考虑窗口的宽高比。
标题应称为<GL/glut.h>
而不是<gl/glut.h>
。在操作系统中,案例对文件名有所不同,这很重要。
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;
}