Gambarkan separuh tengah bola secara pemrograman


10

Saya mencoba membuat setengah bagian tengah bola. Pada dasarnya untuk membuat bola, nomor stack dan nomor irisan diberikan, dan ada dua variabel phi(untuk irisan) dan theta(untuk tumpukan) yang bertanggung jawab untuk berapa banyak untuk maju. Dan prosesnya dibagi menjadi pembuatan topi bagian bawah, badan, dan tutup atas (seperti yang terlihat di bawah). Untuk mencapai setengah bagian tengah ( thetadari tengah 50% seperti di bawah ini), kita perlu menghilangkan penutup, dan entah bagaimana memodifikasi tubuh. Saya bermain-main dengan nomor tumpukan ( 1/4*stackNumbers to 3/4*stackNumbers) tetapi tidak memberikan hasil yang saya inginkan.

Bagaimana saya harus memodifikasi generasi bola untuk mencapai setengah bagian tengah ( pi/4 <theta <pi*3/4)? Masalah saya secara keseluruhan adalah bagaimana saya bisa membagi bola menjadi 3 bagian berbeda 25% atas, tengah 50%, dan bawah 25%?

Berikut ini adalah kode populer untuk membuat bola secara terprogram:

masukkan deskripsi gambar di sini

private void generateSphere(int stackNumber, int sliceNumber, boolean facingOut) {
    int capVertexNumber = 3 * sliceNumber;
    int bodyVertexNumber = 4 * sliceNumber * (stackNumber - 2);
    int vertexNumber = (2 * capVertexNumber) + bodyVertexNumber;
    int triangleNumber = (2 * capVertexNumber) + (6 * sliceNumber * (stackNumber - 2));

    vertices = new float[3 * vertexNumber];
    normals = new float[3 * vertexNumber];
    texCoords = new float[2 * vertexNumber];
    indices = new char[triangleNumber];

    // bottom cap
    // createCap(stackNumber, sliceNumber, false, facingOut);

    // body
    createBody(stackNumber, sliceNumber, facingOut);

    // top cap
    createCap(stackNumber, sliceNumber, true, facingOut);
}

private void createCap(int stackNumber, int sliceNumber, boolean top, boolean facingOut) {

    float stackPercentage0;
    float stackPercentage1;

    if (!top) {
        stackPercentage0 = ((float) (stackNumber - 1) / stackNumber);
        stackPercentage1 = 1.0f;

    } else {
        stackPercentage0 = (1.0f / stackNumber);
        stackPercentage1 = 0.0f;
    }

    float t0 = stackPercentage0;
    float t1 = stackPercentage1;
    double theta0 = stackPercentage0 * Math.PI;
    double theta1 = stackPercentage1 * Math.PI;
    double cosTheta0 = Math.cos(theta0);
    double sinTheta0 = Math.sin(theta0);
    double cosTheta1 = Math.cos(theta1);
    double sinTheta1 = Math.sin(theta1);

    for (int slice = 0; slice < sliceNumber; slice++) {
        float slicePercentage0 = ((float) (slice) / sliceNumber);
        float slicePercentage1 = ((float) (slice + 1) / sliceNumber);
        double phi0 = slicePercentage0 * 2.0 * Math.PI;
        double phi1 = slicePercentage1 * 2.0 * Math.PI;
        float s0, s1;
        if (facingOut) {
            s0 = 1 - slicePercentage0;
            s1 = 1 - slicePercentage1;
        } else {
            s0 = slicePercentage0;
            s1 = slicePercentage1;
        }
        float s2 = (s0 + s1) / 2.0f;
        double cosPhi0 = Math.cos(phi0);
        double sinPhi0 = Math.sin(phi0);
        double cosPhi1 = Math.cos(phi1);
        double sinPhi1 = Math.sin(phi1);

        float x0 = (float) (sinTheta0 * cosPhi0);
        float y0 = (float) cosTheta0;
        float z0 = (float) (sinTheta0 * sinPhi0);

        float x1 = (float) (sinTheta0 * cosPhi1);
        float y1 = (float) cosTheta0;
        float z1 = (float) (sinTheta0 * sinPhi1);

        float x2 = (float) (sinTheta1 * cosPhi0);
        float y2 = (float) cosTheta1;
        float z2 = (float) (sinTheta1 * sinPhi0);

        vertices[vertexCount + 0] = x0;
        vertices[vertexCount + 1] = y0;
        vertices[vertexCount + 2] = z0;

        vertices[vertexCount + 3] = x1;
        vertices[vertexCount + 4] = y1;
        vertices[vertexCount + 5] = z1;

        vertices[vertexCount + 6] = x2;
        vertices[vertexCount + 7] = y2;
        vertices[vertexCount + 8] = z2;

        if (facingOut) {
            normals[vertexCount + 0] = x0;
            normals[vertexCount + 1] = y0;
            normals[vertexCount + 2] = z0;

            normals[vertexCount + 3] = x1;
            normals[vertexCount + 4] = y1;
            normals[vertexCount + 5] = z1;

            normals[vertexCount + 6] = x2;
            normals[vertexCount + 7] = y2;
            normals[vertexCount + 8] = z2;
        } else {
            normals[vertexCount + 0] = -x0;
            normals[vertexCount + 1] = -y0;
            normals[vertexCount + 2] = -z0;

            normals[vertexCount + 3] = -x1;
            normals[vertexCount + 4] = -y1;
            normals[vertexCount + 5] = -z1;

            normals[vertexCount + 6] = -x2;
            normals[vertexCount + 7] = -y2;
            normals[vertexCount + 8] = -z2;
        }

        texCoords[texCoordCount + 0] = s0;
        texCoords[texCoordCount + 1] = t0;
        texCoords[texCoordCount + 2] = s1;
        texCoords[texCoordCount + 3] = t0;
        texCoords[texCoordCount + 4] = s2;
        texCoords[texCoordCount + 5] = t1;

        if ((facingOut && top) || (!facingOut && !top)) {
            indices[indexCount + 0] = (char) (triangleCount + 1);
            indices[indexCount + 1] = (char) (triangleCount + 0);
            indices[indexCount + 2] = (char) (triangleCount + 2);
        } else {
            indices[indexCount + 0] = (char) (triangleCount + 0);
            indices[indexCount + 1] = (char) (triangleCount + 1);
            indices[indexCount + 2] = (char) (triangleCount + 2);
        }

        vertexCount += 9;
        texCoordCount += 6;
        indexCount += 3;
        triangleCount += 3;
    }

}

private void createBody(int stackNumber, int sliceNumber, boolean facingOut) {
    for (int stack = 1; stack < stackNumber - 1; stack++) {
        float stackPercentage0 = ((float) (stack) / stackNumber);
        float stackPercentage1 = ((float) (stack + 1) / stackNumber);

        float t0 = stackPercentage0;
        float t1 = stackPercentage1;

        double theta0 = stackPercentage0 * Math.PI;
        double theta1 = stackPercentage1 * Math.PI;
        double cosTheta0 = Math.cos(theta0);
        double sinTheta0 = Math.sin(theta0);
        double cosTheta1 = Math.cos(theta1);
        double sinTheta1 = Math.sin(theta1);

        for (int slice = 0; slice < sliceNumber; slice++) {
            float slicePercentage0 = ((float) (slice) / sliceNumber);
            float slicePercentage1 = ((float) (slice + 1) / sliceNumber);
            double phi0 = slicePercentage0 * 2.0 * Math.PI;
            double phi1 = slicePercentage1 * 2.0 * Math.PI;
            float s0, s1;
            if (facingOut) {
                s0 = 1.0f - slicePercentage0;
                s1 = 1.0f - slicePercentage1;
            } else {
                s0 = slicePercentage0;
                s1 = slicePercentage1;
            }
            double cosPhi0 = Math.cos(phi0);
            double sinPhi0 = Math.sin(phi0);
            double cosPhi1 = Math.cos(phi1);
            double sinPhi1 = Math.sin(phi1);

            float x0 = (float) (sinTheta0 * cosPhi0);
            float y0 = (float) cosTheta0;
            float z0 = (float) (sinTheta0 * sinPhi0);

            float x1 = (float) (sinTheta0 * cosPhi1);
            float y1 = (float) cosTheta0;
            float z1 = (float) (sinTheta0 * sinPhi1);

            float x2 = (float) (sinTheta1 * cosPhi0);
            float y2 = (float) cosTheta1;
            float z2 = (float) (sinTheta1 * sinPhi0);

            float x3 = (float) (sinTheta1 * cosPhi1);
            float y3 = (float) cosTheta1;
            float z3 = (float) (sinTheta1 * sinPhi1);

            vertices[vertexCount + 0] = x0;
            vertices[vertexCount + 1] = y0;
            vertices[vertexCount + 2] = z0;

            vertices[vertexCount + 3] = x1;
            vertices[vertexCount + 4] = y1;
            vertices[vertexCount + 5] = z1;

            vertices[vertexCount + 6] = x2;
            vertices[vertexCount + 7] = y2;
            vertices[vertexCount + 8] = z2;

            vertices[vertexCount + 9] = x3;
            vertices[vertexCount + 10] = y3;
            vertices[vertexCount + 11] = z3;

            if (facingOut) {
                normals[vertexCount + 0] = x0;
                normals[vertexCount + 1] = y0;
                normals[vertexCount + 2] = z0;

                normals[vertexCount + 3] = x1;
                normals[vertexCount + 4] = y1;
                normals[vertexCount + 5] = z1;

                normals[vertexCount + 6] = x2;
                normals[vertexCount + 7] = y2;
                normals[vertexCount + 8] = z2;

                normals[vertexCount + 9] = x3;
                normals[vertexCount + 10] = y3;
                normals[vertexCount + 11] = z3;
            } else {
                normals[vertexCount + 0] = -x0;
                normals[vertexCount + 1] = -y0;
                normals[vertexCount + 2] = -z0;

                normals[vertexCount + 3] = -x1;
                normals[vertexCount + 4] = -y1;
                normals[vertexCount + 5] = -z1;

                normals[vertexCount + 6] = -x2;
                normals[vertexCount + 7] = -y2;
                normals[vertexCount + 8] = -z2;

                normals[vertexCount + 9] = -x3;
                normals[vertexCount + 10] = -y3;
                normals[vertexCount + 11] = -z3;
            }

            texCoords[texCoordCount + 0] = s0;
            texCoords[texCoordCount + 1] = t0;
            texCoords[texCoordCount + 2] = s1;
            texCoords[texCoordCount + 3] = t0;
            texCoords[texCoordCount + 4] = s0;
            texCoords[texCoordCount + 5] = t1;
            texCoords[texCoordCount + 6] = s1;
            texCoords[texCoordCount + 7] = t1;

            // one quad looking from outside toward center
            //
            // @formatter:off
            //
            // s1 --> s0
            //
            // t0 1-----0
            // | | |
            // v | |
            // t1 3-----2
            //
            // @formatter:on
            //
            // Note that tex_coord t increase from top to bottom because the
            // texture image is loaded upside down.
            if (facingOut) {
                indices[indexCount + 0] = (char) (triangleCount + 0);
                indices[indexCount + 1] = (char) (triangleCount + 1);
                indices[indexCount + 2] = (char) (triangleCount + 2);

                indices[indexCount + 3] = (char) (triangleCount + 2);
                indices[indexCount + 4] = (char) (triangleCount + 1);
                indices[indexCount + 5] = (char) (triangleCount + 3);
            } else {
                indices[indexCount + 0] = (char) (triangleCount + 0);
                indices[indexCount + 1] = (char) (triangleCount + 2);
                indices[indexCount + 2] = (char) (triangleCount + 1);

                indices[indexCount + 3] = (char) (triangleCount + 2);
                indices[indexCount + 4] = (char) (triangleCount + 3);
                indices[indexCount + 5] = (char) (triangleCount + 1);
            }

            vertexCount += 12;
            texCoordCount += 8;
            indexCount += 6;
            triangleCount += 4;
        }
    }

} 

Jawaban:


1

Pikirkan pertanyaan Anda dalam hal tessellation dengan bola Anda yang dibentuk oleh cincin. Jika Anda memiliki faktor tessellation 5, Anda akan memiliki topi atas, 2 bagian tengah, dan tutup bawah. Dua cincin bawah tessellation menjadi tutup bawah 25% dan tessellation atas dua cincin tutup atas 25%. Oleh karena itu pusatnya adalah satu cincin di garis katulistiwa dengan satu set wajah di kedua sisi sebesar 50%. Berikut ini adalah contoh cara melakukan tessellate sphere dengan terlebih dahulu menghitung cincin di setiap ketinggian dan kemudian menghasilkan wajah di antara masing-masing cincin.

float radius = 1.0f;
const int tesselationFactor = 5;

for (int i = 0; i <= tesselationFactor; i++)
{
    const float PI = 3.14159265359f;
    const float PIDIV2 = PI / 2.0f;

    // find height of ring
    float height = (i*PI / tesselationFactor) - PIDIV2;
    float dy = sinf(height);
    float theta = cosf(height);

    // locate verticies equally around center to form a ring
    for (int j = 0; j <= tessellation * 2; j++)
    {

        float longitude = static_cast<float>(j) * PIDIV2 / (tessellation * 2);
        float dx = sinf(longitude) * theta;
        float dz = cosf(longitude) * theta;

        Vector normal{ dx, dy, dz }; // initialize vector
        vertices.push_back(VertexPositionNormal(normal * radius, normal));
    }
}
// Fill the index buffer with triangles joining each pair of latitude rings.
int stride = tessellation * 2 + 1;
for (int i = 0; i < tesselationFactor; i++) // verticle rings
{
    for (int j = 0; j <= tessellation * 2; j++) // horizontal verticies
    {
        // 
        int i1 = i + 1;
        int j1 = (j + 1) % stride;
        /* connecting face */
         // triangle 1
        index_push_back(indices, i * stride + j);
        index_push_back(indices, i1 * stride + j);
        index_push_back(indices, i * stride + j1);
         // triangle 2
        index_push_back(indices, i * stride + j1);
        index_push_back(indices, i1 * stride + j);
        index_push_back(indices, i1 * stride + j1);
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.