在OpenGL中绘制斯坦纳的罗马曲面
Drawing Steiner's Roman Surface in OpenGL
我正试图在OpenGL中绘制施泰纳的罗马表面,并且我遇到了一些问题,以获得正确的法线,以便表面正确点亮。我使用了维基百科上的参数方程:http://en.wikipedia.org/wiki/Roman_surface。对于法线,我对做偏微分,然后是,然后交叉偏微分得到法线。
由于罗马曲面是一个不可定向的曲面,这使得表面不能正常发光。因此,我想知道是否有一种方法可以得到正确的法线,以便表面可以正确点亮。我试过对整个曲面和部分曲面的法线取负(对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();
}
}
如果你正在处理不可定向的表面(如斯坦纳的罗马人,或著名的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();
将多边形分成两个三角形可能会得到更好的结果-然后每个三角形都保证是平面的。此外,您可以从每个三角形生成法线,或者在相邻三角形之间平滑它们。
另一个技巧是将你的点预生成到一个数组中,然后在glVertex调用中引用该数组。这样你就有更多关于如何生成法线的选择。
同样,你可以用glBegin(GL_LINES)来渲染法线本身…glEnd()序列。
对于您生成的每个三角形,创建一个具有相同坐标/法线,但缠绕/翻转方向相反的三角形
相关文章:
- OpenCascade:从 IGES 读取修剪曲面
- CGAL:如何创建填充边界曲线的曲面网格?
- 如何从 3D 曲面网格中删除自相交三角形?
- 在使用 SDL2 从曲面创建的纹理上渲染纹理
- 如何在 DirectX 11 中使用曲面细分绘制虚线图案 3D 线
- 如何在三角形曲面细分评估着色器中插值 UV 映射坐标?
- CGAL 曲面网格 - 修改顶点坐标
- 如何将三角孔贴片转换为曲面网格
- 使用 gnuplot 制作 3D 曲面图
- 在曲面中插入边-CGAL错误:断言冲突
- 为什么我创建的曲面无法加载?
- SDL在析构函数上释放曲面失败
- 在 openGL 中绘制平面曲面
- 碰撞后从方向抵消曲面轴
- C++ 罗马加法形式转换
- 将曲面保存到不带DirectX的文件(d3dx9_43.dll)
- 复制PCL点云,同时保留组织或Ransac+曲面法线计算
- 局部曲面拟合到 3d 点
- OpenGL:具有三角测量的贝塞尔曲面
- 在OpenGL中绘制斯坦纳的罗马曲面