1

ここでスタックオーバーフローで見つけた球のサンプルコードを実装しようとすると、問題が発生しました。描画コードを使用していないことに注意してくださいvoid SolidSphere。この例の関数を使用して頂点データを作成しています。

これは、参照した例にいくつかの小さな変更を加えた私のコードです。

std::vector<GLfloat> vertices;
std::vector<GLfloat> normals;
std::vector<GLfloat> texcoords;
std::vector<GLushort> indices;

    Sphere(shared_ptr<GL::Shader> _shader, shared_ptr<Material> _material, float radius, unsigned int rings, unsigned int sectors)
{
    this->attachShader(_shader);
    this->attachMaterial(_material);

    /** Implementation from:
    https://stackoverflow.com/questions/5988686/how-do-i-create-a-3d-sphere-in-opengl-using-visual-c?lq=1
    **/

    float const R = 1./(float)(rings-1);
    float const S = 1./(float)(sectors-1);
    int r, s;

    vertices.resize(rings * sectors * 3);
    //normals.resize(rings * sectors * 3);
    texcoords.resize(rings * sectors * 2);
    std::vector<GLfloat>::iterator v = vertices.begin();
    //std::vector<GLfloat>::iterator n = sphere_normals.begin();
    std::vector<GLfloat>::iterator t = texcoords.begin();
    for(r = 0; r < rings; r++) {
        for(s = 0; s < sectors; s++) {
            float const y = sin( -M_PI/2 + M_PI * r * R );
            float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R );
            float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R );

            *t++ = s*S;
            *t++ = r*R;

            *v++ = x * radius;
            *v++ = y * radius;
            *v++ = z * radius;

            //*n++ = x;
            //*n++ = y;
            //*n++ = z;
        }
    }



    indices.resize(rings * sectors * 4);
    std::vector<GLushort>::iterator i = indices.begin();
    for(r = 0; r < rings; r++) {
        for(s = 0; s < sectors; s++) {
            *i++ = r * sectors + s;
            *i++ = r * sectors + (s+1);
            *i++ = (r+1) * sectors + (s+1);
            *i++ = (r+1) * sectors + s;
        }
    }


           /************* THIS IS THE ADDED PART ********/
    for (unsigned int i = 0; i < vertices.size(); i += 3) {
        vertexCoords.push_back(glm::vec4(vertices[i], vertices[i+1], vertices[i+2], 1));
    }

    for (unsigned int i = 0; i < texcoords.size(); i += 2) {
        textureCoords.push_back(glm::vec2(texcoords[i], texcoords[i+1]));
    }
    indexElements = indices;

    cout << "Vertex vector size: " << vertexCoords.size() << endl;
    cout << "Texture vector size: " << textureCoords.size() << endl;
    cout << "Element index vector size: " << indexElements.size() << endl;
}

ここでの唯一の大きな変更点は、M_PI / 2代わりにM_PI_2と 2 つのループを使用して、コードが使用する形式に値をプッシュすることです。

vector <glm::vec4> vertexCoords;
vector <glm::vec2> textureCoords;
vector <GLushort> indexElements;

ここに私がレンダリングしているものの写真があります:

ここに画像の説明を入力

だから私は球の上にこの最後の行を見ています..

これを引き起こす可能性のあるこのコードで間違っていることは明らかですか?

4

3 に答える 3

2

このループでは:

for(r = 0; r < rings; r++) {
    for(s = 0; s < sectors; s++) {
        *i++ = r * sectors + s;
        *i++ = r * sectors + (s+1);
        *i++ = (r+1) * sectors + (s+1);
        *i++ = (r+1) * sectors + s;
    }
}

アクセスr+1s+1ている時間r = rings - 1s = sectors - 1(つまり、ループの最後の繰り返し) は、利用可能なデータよりも 1 つ高くなります。

これは、メモリの初期化されていない領域を指しています。これには何でも含まれる可能性がありますが、この場合はゼロが含まれているように見えます。

「次の」クワッドを描画しているので、これらのループを 1 回前に停止する必要があります。

for(r = 0; r < rings-1; r++) {
    for(s = 0; s < sectors-1; s++) {
于 2012-12-29T12:29:24.800 に答える
1

問題は境界の出力インデックスです。コードのこの部分を修正してみてください。

indices.resize(rings * sectors * 4);
std::vector<GLushort>::iterator i = indices.begin();
for(r = 0; r < rings-1; r++) {
    for(s = 0; s < sectors-1; s++) {
        *i++ = r * sectors + s;
        *i++ = r * sectors + (s+1);
        *i++ = (r+1) * sectors + (s+1);
        *i++ = (r+1) * sectors + s;
    }
}
于 2012-12-29T12:23:13.890 に答える
1

頂点しかありませんrings*sectorsが、インデックスは最大で(rings-1+1)*sectors+(sectors-1+1)=rings*sectors+sectors になります。これはまさにsectors頂点の数が多すぎます。

于 2012-12-29T12:05:26.047 に答える