我正在尝试在OpenGL中绘制Steiner的罗马曲面,而我在获得正确的法线方面遇到了一些麻烦,因此表面会正常亮起。我使用维基百科的参数方程:http://en.wikipedia.org/wiki/Roman_surface。对于法线,我对theta进行了部分区分,然后是phi,然后越过偏微分来获得正常。
由于罗马表面是不可定向的表面,因此不允许表面正确点亮。因此,我想知道是否有办法让正常的法线出来,以便表面可以正确点亮。我已经尝试否定法线,整个表面和表面的一部分(否定n的第一个和最后一个四分之一),但它似乎不起作用。
我目前的代码如下:
double getRad(double deg, double n){
return deg * M_PI / n;
}
int n = 24;
for(int i = 0; i < n; i++){
for(int j = 0; j < 2*n; j++){
glBegin(GL_POLYGON);
double x = -pow(r,4) * cos(2*getRad(i+0.5,n)) * pow(cos(getRad(j+0.5,n)),2) * cos(2*getRad(j+0.5,n)) * sin(getRad(i+0.5,n)) - 2 * pow(r,4) * pow(cos(getRad(i+0.5,n)),2) * pow(cos(getRad(j+0.5,n)),2) * sin(getRad(i+0.5,n)) * pow(sin(getRad(j+0.5,n)),2);
double y = pow(r,4) * cos(getRad(i+0.5,n)) * cos(2*getRad(i+0.5,n)) * pow(cos(getRad(j+0.5,n)),2) * cos(2*getRad(j+0.5,n)) - 2 * pow(r,4) * cos(getRad(i+0.5,n)) * pow(cos(getRad(j+0.5,n)),2) * pow(sin(getRad(i+0.5,n)),2) * pow(sin(getRad(j+0.5,n)),2);
double z = -pow(r,4) * pow(cos(getRad(i+0.5,n)),2) * cos(getRad(j+0.5,n)) * cos(2*getRad(j+0.5,n)) * sin(getRad(j+0.5,n)) - pow(r,4) * cos(getRad(j+0.5,n)) * cos(2*getRad(j+0.5,n)) * pow(sin(getRad(i+0.5,n)),2) * sin(getRad(j+0.5,n));
glNormal3d(x, y, z);
glVertex3d(r*r*cos(getRad(i,n))*cos(getRad(j,n))*sin(getRad(j,n)),r*r*sin(getRad(i,n))*cos(getRad(j,n))*sin(getRad(j,n)),r*r*cos(getRad(i,n))*sin(getRad(i,n))*cos(getRad(j,n))*cos(getRad(j,n)));
glVertex3d(r*r*cos(getRad(i+1,n))*cos(getRad(j,n))*sin(getRad(j,n)),r*r*sin(getRad(i+1,n))*cos(getRad(j,n))*sin(getRad(j,n)),r*r*cos(getRad(i+1,n))*sin(getRad(i+1,n))*cos(getRad(j,n))*cos(getRad(j,n)));
glVertex3d(r*r*cos(getRad(i+1,n))*cos(getRad(j+1,n))*sin(getRad(j+1,n)),r*r*sin(getRad(i+1,n))*cos(getRad(j+1,n))*sin(getRad(j+1,n)),r*r*cos(getRad(i+1,n))*sin(getRad(i+1,n))*cos(getRad(j+1,n))*cos(getRad(j+1,n)));
glVertex3d(r*r*cos(getRad(i,n))*cos(getRad(j+1,n))*sin(getRad(j+1,n)),r*r*sin(getRad(i,n))*cos(getRad(j+1,n))*sin(getRad(j+1,n)),r*r*cos(getRad(i,n))*sin(getRad(i,n))*cos(getRad(j+1,n))*cos(getRad(j+1,n)));
glEnd();
glFlush();
}
}
答案 0 :(得分:2)
如果您正在处理不可移动的表面(如Steiner's Romans或着名的Möbius条带),您必须具备以下功能:启用双面照明
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
或者启用面部剔除并使用两次传递(正面和背面)渲染曲面 - 您必须否定背面传递的法线。
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); // backside faces are NOT rendered
draw_with_positive_normals();
glCullFace(GL_FRONT);
draw_with_negative_normals();
答案 1 :(得分:0)
对于您生成的每个三角形,创建一个具有相同坐标/法线的三角形,但以另一种方式缠绕/翻转。
答案 2 :(得分:0)
通过将多边形分成两个三角形,您可能会得到更好的结果 - 每个三角形都可以保证是平面的。此外,您可以从每个三角形生成法线,或者在相邻三角形之间平滑它们。
另一个技巧是将您的点预先生成一个数组,然后在glVertex调用中引用该数组。这样你就可以有更多关于如何生成法线的选项。
此外,您可以使用glBegin(GL_LINES)... glEnd()序列渲染法线。