2011-10-14 23 views
1

我试图在OpenGL中绘制Steiner的罗马曲面,并且我在获取正确的法线方面遇到了一些麻烦,以便表面正常点亮。我使用维基百科的参数方程:http://en.wikipedia.org/wiki/Roman_surface。对于法线,我对θ进行了偏微分,然后是phi,然后穿过了局部微分得到了正常。在OpenGL中绘制Steiner的罗马曲面

这不允许表面正常点亮,因为罗马表面是不可定向的表面。因此,我想知道是否有办法获得正确的法线,以便表面可以正确点亮。我尝试否定法线,整个表面和部分表面(否定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(); 

    } 
} 
+2

你可以计算出正常的你绘制四边形的平面和使用(如果它不是平面绘制两个三角形来代替),但我很想知道,如果任何人有更好的主意。 – user786653

回答

2

在你与不可定向表面处理(如Steiner的罗马人,还是著名的莫比乌斯带)的情况下,你必须possiblilities:启用双面照明

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(); 
+0

非常感谢,双面照明工作。现在我只需要弄清楚如何为背面着色。 =) –

+0

@ tempestfire2002:为此,你应该真的使用第二种方法。从长远来看,事情变得更容易。 – datenwolf

+0

@ tempestfire2002您也可以使用双面材质(在'glMaterial'调用中使用'GL_FRONT'和'GL_BACK'而不是'GL_FRONT_AND_BACK')来让双方的颜色不同。 –

0

您每生成创建一个具有相同的坐标/法线,但伤口三角形/翻转的其他方式。

+0

从技术上讲,我正在生成四边形,尽管我确实尝试过。看起来好像OpenGL取代了常规而不是添加另一个。 –

0

将多边形分割成两个三角形可能会获得更好的结果 - 每个三角形都将保证为平面。此外,您可以从每个三角形生成法线,或者在相邻三角形之间平滑它们。

另一个技巧是预先生成你的点到一个数组,然后在glVertex调用中引用数组。这样你可以有更多选择来生成法线。此外,您可以使用glBegin(GL_LINES)... glEnd()序列渲染法线本身。

+0

为了详细说明用线绘制法线的(优秀的)调试提示:您通常需要画一条从“M”到“M + N * scale”的线,其中'M'是三角形的几何中心(或你从哪里计算出正常值),“N”表面法线和“比例”是一个适当的因子,可以让你看到发生了什么。 – user786653