以下のコードを考えます。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;
一部の面では法線が正しく見えません。完全な形状が作成されたら、結果のインデックスをループしてから、各ポイントの法線を計算します。
OK、これが私が得たものです。それはおそらく完全に間違っているので、簡単に行ってください。
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の優れた回答に感謝します。バートにも感謝します!