-1

给定下面的代码。取自http://pastie.org/pastes/764327/text

    void CreateSphere(int PointRows, int PointsPerRow)
{
    NumVertices = (PointRows-2)*PointsPerRow + 2;
    Vertices = new SVertex[NumVertices];
    IndexVect.clear();  //to be sure it is empty
    float x,y,z;
    int i,j;
    double r;
    for (i = 1; i < (PointRows-1); i++)
    {
        for (j = 0; j < PointsPerRow; j++)
        {
            y = 1.0 - float(i) / float(PointRows-1)*2.0;
            r = sin (acos(y));  //radius of the row
            x = r * sin(float(j) / float(PointsPerRow)*PI*2.0);     
            z = r * cos(float(j) / float(PointsPerRow)*PI*2.0);
        Vertices[(i-1)*PointsPerRow+j].x = x;
        Vertices[(i-1)*PointsPerRow+j].y = y;
        Vertices[(i-1)*PointsPerRow+j].z = z;
        Vertices[(i-1)*PointsPerRow+j].r = (float)(i) / float(PointRows);
        Vertices[(i-1)*PointsPerRow+j].g = 0.7;
        Vertices[(i-1)*PointsPerRow+j].b = (float)(j) / float(PointsPerRow);
    }

}
//The highest and deepest vertices:
Vertices[(PointRows-2)*PointsPerRow].x = 0.0;
Vertices[(PointRows-2)*PointsPerRow].y = 1.0;
Vertices[(PointRows-2)*PointsPerRow].z = 0.0;
Vertices[(PointRows-2)*PointsPerRow].r = 1.0;
Vertices[(PointRows-2)*PointsPerRow].g = 0.7;
Vertices[(PointRows-2)*PointsPerRow].b = 1.0;
Vertices[(PointRows-2)*PointsPerRow+1].x = 0.0;
Vertices[(PointRows-2)*PointsPerRow+1].y = -1.0;
Vertices[(PointRows-2)*PointsPerRow+1].z = 0.0;
Vertices[(PointRows-2)*PointsPerRow+1].r = 1.0;
Vertices[(PointRows-2)*PointsPerRow+1].g = 0.7;
Vertices[(PointRows-2)*PointsPerRow+1].b = 1.0;

for (i = 1; i < (PointRows-2); i++)
{
    for (j = 0; j < (PointsPerRow-1); j++)
    {
        IndexVect.push_back((i-1)*PointsPerRow+j);
        IndexVect.push_back((i-1)*PointsPerRow+j+1);
        IndexVect.push_back((i)*PointsPerRow+j);

        IndexVect.push_back((i-1)*PointsPerRow+j+1);
        IndexVect.push_back((i)*PointsPerRow+j+1);
        IndexVect.push_back((i)*PointsPerRow+j);
    }

    IndexVect.push_back((i-1)*PointsPerRow+PointsPerRow-1);
    IndexVect.push_back((i-1)*PointsPerRow);
    IndexVect.push_back((i)*PointsPerRow+j);

    IndexVect.push_back((i)*PointsPerRow);
    IndexVect.push_back((i-1)*PointsPerRow);
    IndexVect.push_back((i)*PointsPerRow+j);
}       

//The triangles to the highest and deepest vertices:
for (j = 0; j< (PointsPerRow-1); j++)
{
    IndexVect.push_back(j);
    IndexVect.push_back(j+1);
    IndexVect.push_back((PointRows-2)*PointsPerRow);
}
IndexVect.push_back(j);
IndexVect.push_back(0);
IndexVect.push_back((PointRows-2)*PointsPerRow);

for (j = 0; j< (PointsPerRow-1); j++)
{
    IndexVect.push_back((PointRows-3)*PointsPerRow+j);
    IndexVect.push_back((PointRows-3)*PointsPerRow+j+1);
    IndexVect.push_back((PointRows-2)*PointsPerRow+1);
}
IndexVect.push_back((PointRows-3)*PointsPerRow+j);
IndexVect.push_back((PointRows-3)*PointsPerRow);
IndexVect.push_back((PointRows-2)*PointsPerRow+1);
Indices = new GLuint[IndexVect.size()];  //allocate the required memory
for (i = 0; i < IndexVect.size(); i++)
{
    Indices[i] = IndexVect[i];
}
NumIndices = IndexVect.size();
IndexVect.clear();  //no longer needed, takes only memory

}

您将如何使用结果顶点计算法线......?

然后我希望使用 glEnableClientState(GL_NORMAL_ARRAY) 和 glNormalPointer(GL_FLOAT,0, Normals) 以及 glDrawElements 将结果索引与法线一起绘制。

我试过了,但它看起来不对。灯光出现在球体的左侧,而不是下方。

道歉。我在这里没有给出完整的图片。基本上,我试图通过在数据中输入噪声来生成随机形状。

如果我在第一个嵌套循环的末尾使用以下代码:

Normals[(i-1)*PointsPerRow+j].x = x;
Normals[(i-1)*PointsPerRow+j].y = y;
Normals[(i-1)*PointsPerRow+j].z = z;

我能够为球体生成正确的法线,一切看起来都很好。

但是,如果我这样做:

x=x+(noise3(x,y,z));
y=y+(noise3(x,y,z));
z=z+(noise3(x,y,z));

然后尝试使用:

Normals[(i-1)*PointsPerRow+j].x = x;
Normals[(i-1)*PointsPerRow+j].y = y;
Normals[(i-1)*PointsPerRow+j].z = z;

某些面孔的法线看起来是错误的。一旦创建了完整的形状,我想遍历结果索引,然后计算每个点的法线,如果这有任何意义的话....?

好的,这就是我得到的。它似乎不起作用。它可能完全错误,所以放轻松。

  for (j = 0; j < NumIndices-2; j=j+3)
   {

Ax = Vertices[Indices[j]].x;    Bx = Vertices[Indices[j+1]].x;   Cx = Vertices[Indices[j+2]].x;
Ay = Vertices[Indices[j]].y;   By = Vertices[Indices[j+1]].y;   Cy = Vertices[Indices[j+2]].y;
Az = Vertices[Indices[j]].z;   Bz = Vertices[Indices[j+1]].z;   Cz = Vertices[Indices[j+2]].z;

dms::Vector3 p1(Ax,Ay,Az);
dms::Vector3 p2(Bx,By,Bz);
dms::Vector3 p3(Cx,Cy,Cz);
dms::Vector3 V1= (p2 - p1);
dms::Vector3 V2 = (p3 - p1);
dms::Vector3 normal = V1.cross(V2);

Normals[j].x = normal[0];
Normals[j].y = normal[1];
Normals[j].z = normal[2];;

Normals[j+1].x = normal[0];
Normals[j+1].y = normal[1];
Normals[j+1].z = normal[2];;


Normals[j+2].x = normal[0];
Normals[j+2].y = normal[1];
Normals[j+2].z = normal[2];;

}

编辑 - -

通过重新安排计算 2 个向量的部分,我能够获得更好的结果。我更改了以下内容:

dms::Vector3 V1= (p2 - p1);
dms::Vector3 V2 = (p3 - p1);

到:

dms::Vector3 V1= (p2 - p1);
dms::Vector3 V2 = (p1 - p3);

但是看起来还是不太对劲,球体的前面有一条黑色的条带,球体的顶部看起来很奇怪。

非常感谢 Kaganar 的出色回答,我将努力解决我剩下的问题。也非常感谢巴特!

4

1 回答 1

4

根据评论,这是一个可能的答案:

  • 第 1 步:将所有顶点法线设置为零向量。
  • 第二步:计算每个三角形的法线,并将其加到每个三角形的所有顶点上。
  • 第 3 步:归一化所有顶点法线。

关于您在撰写此答案时发布的代码:

  • 目前尚不清楚法线是否被初始化为零向量。
  • 您正在分配,而不是将法线添加到顶点法线。(所以第 2 步不能正常工作。)此外,您添加到顶点法线的法线本身并未标准化。(叉积不会自动标准化——您必须标准化叉积的结果。)
  • 您根本没有执行第 3 步。

进一步注意:当您进行规范化时,请注意传递给规范化函数的接近零长度的向量,尤其是在您使用嘈杂生成的形状时。由于归一化只是划分向量长度的分量,因此通常在进行您通常期望的除法之前检查该长度是否接近于零。如果它接近于零,则这种归一化函数的输出通常只是向上向量(因为在大多数着色模型中,零向量会导致虚假的暗结果。)

于 2012-06-07T13:33:14.293 回答