我对OpenGL和C ++一般都比较陌生,而且我一直在研究一个自定义框架,我要求它渲染球体。我已经完成了研究并设法生成了一个由点组成的有点球体。我想尽可能改进它,这样我就可以得到一个由具有半径等属性的三角形组成的实际球体。我用来生成由点组成的球体的代码如下:
Mesh* Mesh::GenerateSphere()
{
const int Y_SEGMENT= 10;
const int X_SEGMENT = 20;
//const float count;
Mesh*m = new Mesh();
m->numVertices = (X_SEGMENT+1)*(Y_SEGMENT+1);
m->type = GL_POINTS;
m->vertices = new Vector3[m->numVertices];
//s->GenerateTriangle();
for (int i = 0; i < Y_SEGMENT+1;i++)
{
float angleY = PI*i / Y_SEGMENT;
float y = cos(angleY);
float xz = sin(angleY);
for (int j = 0; j < X_SEGMENT+1; j++)
{
float angleX = 2*PI*j / X_SEGMENT;
float x = xz*cos(angleX);
float z = xz*sin(angleX);
Vector3 v(x,y,z);
m->vertices[i * (X_SEGMENT+1)+j] = v;
}
}
m->BufferData();
return m;
}
答案 0 :(得分:0)
这是我在一段时间之前编写很久很久的代码。我用三角形风扇绘制了两极周围的区域,并用四条带绘制了球体的其余部分。你当然可以使用三角形代替四边形,但由于三角形对仍然是平面的,它看起来不会有什么不同,除非我弄错了 - 自从我触及任何东西以来已经很长时间了GL。
正如molbdnilo指出的那样,通过以不同的方式计算你的分数,你将获得更好的领域。如果目的是对球体进行纹理贴图,那么如果细分和平滑立方体,则会再次获得更好的效果,因为这可以避免“捏合”。在两极附近。 这是一篇很好的文章,讨论了这个:http://www.iquilezles.org/www/articles/patchedsphere/patchedsphere.htm
我还应该指出,我计算法线的方式存在问题,或者在旋转时进行变换 - 我曾经在旋转时查看球体时得到时髦的光照效果。 (我认为这与法线有关) 另外,现在查看正常的代码,我不确定我是否正确计算了所需的顶点数量 - 您必须仔细检查它。看起来好像我没有&#39 ; t存储数组中任一极点的顶点。
修改强> 这是输出的图片:
typedef struct {
GLfloat x, y, z;
}vec3;
void myGlutBall(float radius, int numStacks, int numSides)
{
// vec3 points[sides * (sides-1)];
GLfloat curRadius, curTheta, curRho, deltaTheta, deltaRho, curX,curY,curZ;
int curStack, curSlice, numVerts = (numStacks-1)*numSides;
vec3 points[numVerts];
int curVert = 0;
int t;
deltaTheta = (2*M_PI) / numSides;
deltaRho = M_PI / numStacks;
for (curStack=1; curStack<numStacks; curStack++)
{
curRho = (3.141/2.0) - curStack*deltaRho;
curY = sin(curRho) * radius;
curRadius = cos(curRho) * radius;
for (curSlice=0; curSlice<numSides; curSlice++)
{
curTheta = curSlice * deltaTheta;
curX = curRadius * cos(curTheta);
curZ = -curRadius * sin(curTheta);
points[curVert++] = vec3{curX,curY,curZ};
}
}
// option 1 - points only
/*
glBegin(GL_POINTS);
glNormal3d(0,1,0);
glVertex3d(0,radius,0);
for (t=0; t<numVerts; t++)
{
curX = points[t].x;
curY = points[t].y;
curZ = points[t].z;
glNormal3d(curX, curY, curZ);
glVertex3d(curX, curY, curZ);
}
glNormal3d(0,-1,0);
glVertex3d(0,-radius,0);
glEnd();
*/
///////////////////////////////
// option 2 - solid
///////////////////////////////
// part A - draw the top 'lid' (tris)
glBegin(GL_TRIANGLE_FAN);
glNormal3d(0,1,0);
glVertex3d(0,radius,0);
for (t=0; t<numSides; t++)
{
curX = points[t].x;
curY = points[t].y;
curZ = points[t].z;
glNormal3d(curX, curY, curZ);
glVertex3d(curX, curY, curZ);
}
curX = points[0].x;
curY = points[0].y;
curZ = points[0].z;
glNormal3d(curX, curY, curZ);
glVertex3d(curX, curY, curZ);
glEnd();
// part B - draw the 'sides' (quads)
int vertIndex;
for (curStack=0; curStack<numStacks-2; curStack++)
{
vertIndex = curStack * numSides;
glBegin(GL_QUAD_STRIP);
for (curSlice=0; curSlice<numSides; curSlice++)
{
glNormal3d(points[vertIndex+curSlice].x, points[vertIndex+curSlice].y, points[vertIndex+curSlice].z);
glVertex3d(points[vertIndex+curSlice].x, points[vertIndex+curSlice].y, points[vertIndex+curSlice].z);
glNormal3d(points[vertIndex+numSides+curSlice].x, points[vertIndex+numSides+curSlice].y, points[vertIndex+numSides+curSlice].z);
glVertex3d(points[vertIndex+numSides+curSlice].x, points[vertIndex+numSides+curSlice].y, points[vertIndex+numSides+curSlice].z);
}
glNormal3d(points[vertIndex].x, points[vertIndex].y, points[vertIndex].z);
glVertex3d(points[vertIndex].x, points[vertIndex].y, points[vertIndex].z);
glNormal3d(points[vertIndex+numSides].x, points[vertIndex+numSides].y, points[vertIndex+numSides].z);
glVertex3d(points[vertIndex+numSides].x, points[vertIndex+numSides].y, points[vertIndex+numSides].z);
glEnd();
}
// part C - draw the bottom 'lid' (tris)
glBegin(GL_TRIANGLE_FAN);
glNormal3d(0,-1,0);
glVertex3d(0,-radius,0);
for (t=0; t<numSides-1; t++)
{
curX = points[numVerts-1-t].x;
curY = points[numVerts-1-t].y;
curZ = points[numVerts-1-t].z;
glNormal3d(curX, curY, curZ);
glVertex3d(curX, curY, curZ);
}
curX = points[numVerts-1].x;
curY = points[numVerts-1].y;
curZ = points[numVerts-1].z;
glNormal3d(curX, curY, curZ);
glVertex3d(curX, curY, curZ);
glEnd();
}
答案 1 :(得分:0)
在我的渲染课中,我被教导将球体想象为圆形网格。首先,您要在 x 和 y 中实现尺寸为 1 的网格,其中心位于(0,0, 0)将细分为 n -rows( rowMax )和 m -columns( colMax ):
// Aux function
inline int index (int i, int j)
{
return i + j*(m_colMax + 1);
}
float numCoords = 3*rowMax*colMax; // Array size
float *coordData = new float[numCoords]; // Array with coordinate positions
// Fill coordinate positions [to change]
for (int j = 0; j <= rowMax; j++) {
for (int i = 0; i <= colMax; i++) {
int k = index(i, j);
coordData[k] = (float)i / m_colMax - (0.5f);
coordData[k + 1] = (float)j / m_rowMax - (0.5f);
coordData[k + 2] = 0;
}
}
// Fill index
int k = 0;
GLuint *indexData = new GLuint[numCoords]; // Array with indexing data
for (int j = 0; j < rowMax; j++) {
for (int i = 0; i < colMax; i++) {
indexData[k++] = index (i, j);
indexData[k++] = index (i + 1, j + 1);
indexData[k++] = index (i, j + 1);
indexData[k++] = index (i, j);
indexData[k++] = index (i + 1, j);
indexData[k++] = index (i + 1, j + 1);
}
}
使用此数据,请记住使用 DrawElements()和 GL_TRIANGLES 来考虑索引(第二个链接具有此方法的清晰图像)。由于您不熟悉OpenGL,因此这两个链接可以总结您需要学习的内容:
[1]使用不带着色器的OGL 2.1:http://www.songho.ca/opengl/gl_vertexarray.html
[2]使用更高级的技术(又名,OGL 3.3+与核心/兼容性配置文件)http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
现在,要做你需要的,只需更改第一个 for 循环中的代码:
// Fill coordinate positions
// Pi variable can be a define or declared somewhere in your code
float radius = 1.0f;
for (int j = 0; j <= rowMax; j++) {
for (int i = 0; i <= colMax; i++) {
int k = index(i, j);
float teta = ((float)i / m_colMax) * 2 * (float)Pi;
float fi = ((float)j / m_rowMax)*(float)Pi;
coordData[k] = radius*(cos (teta))*(sin (fi));
coordData[k + 1] = radius*(cos (fi));
coordData[k + 2] = 1.0f*(sin (teta))*(sin (fi));
}
}
你的球体坐标与索引一致。使用 for 循环在旧的OpenGL管道(2.1或兼容性配置文件)上绘制它,或在新的OpenGL管道(核心配置文件)上设置缓冲区(VAO,VBO)。