Cube using single GL_TRIANGLE_STRIP
Asked Answered
S

6

21

Is it possible to draw a whole cube using just a single GL_TRIANGLE_STRIP?

Obviously it's just the cube combinatorics I'm concerned about here, it might as well be stretched into any kind of box or similar object.

Sienese answered 6/2, 2015 at 21:46 Comment(2)
in other word unfold the cube into a single line,Sherer
And to draw multiple disconnected strips check out primitive restart: khronos.org/registry/webgl/specs/latest/2.0/…Colloquium
A
31

From the paper Optimizing Triangle Strips for Fast Rendering by Evans, Skiena, and Varshney:

triangle strip diagram

Asperse answered 9/8, 2016 at 16:23 Comment(0)
B
16

For those of you who are lazy (like me), here's a copy-paste version of rob mayoff's answer ;)

static const GLfloat cube_strip[] = {
    -1.f, 1.f, 1.f,     // Front-top-left
    1.f, 1.f, 1.f,      // Front-top-right
    -1.f, -1.f, 1.f,    // Front-bottom-left
    1.f, -1.f, 1.f,     // Front-bottom-right
    1.f, -1.f, -1.f,    // Back-bottom-right
    1.f, 1.f, 1.f,      // Front-top-right
    1.f, 1.f, -1.f,     // Back-top-right
    -1.f, 1.f, 1.f,     // Front-top-left
    -1.f, 1.f, -1.f,    // Back-top-left
    -1.f, -1.f, 1.f,    // Front-bottom-left
    -1.f, -1.f, -1.f,   // Back-bottom-left
    1.f, -1.f, -1.f,    // Back-bottom-right
    -1.f, 1.f, -1.f,    // Back-top-left
    1.f, 1.f, -1.f      // Back-top-right
};
Boob answered 2/9, 2017 at 17:37 Comment(3)
Have you tested it? It doesn't produce correct geometryGriego
Yes I've tested it and use it profusely. Your problem is elsewhere.Boob
Note that this triangle strip is front-facing only when viewed from INSIDE the cube. If you want to view the cube from the outside, flip the sign of one of the axes.Sunk
S
6

Yes, after a bit of experimenting I found the answer myself. Imagine the corners of your cube are colored alternatingly black and white. Draw a triangle edge along each face between the two black corners. That way, the diagonals form a tetrahedron inside the cube. For the [0,1]³ cube, a possible sequence of coordinates would be the following:

Vertex  Triangle    Face
------+-----------+-----
0 0 0
0 1 0
1 0 0  000 010 100  **0
1 1 0  100 010 110  **0
1 1 1  100 110 111  1**
0 1 0  111 110 010  *1*
0 1 1  111 010 011  *1*
0 0 1  011 010 001  0**
1 1 1  011 001 111  **1
1 0 1  111 001 101  **1
1 0 0  111 101 100  1**
0 0 1  100 101 001  *0*
0 0 0  100 001 000  *0*
0 1 0  000 001 010  0**
Sienese answered 6/2, 2015 at 21:46 Comment(0)
S
3

May be useful to some, here's a geometry shader that will take in a point and output a triangle strip of a unit cube

#version 410

layout(points) in;
layout(triangle_strip, max_vertices = 12) out;

uniform mat4 mvp;

void main() {
    vec4 center = gl_in[0].gl_Position;

    vec4 dx = mvp[0];
    vec4 dy = mvp[1];
    vec4 dz = mvp[2];

    vec4 p1 = center;
    vec4 p2 = center + dx;
    vec4 p3 = center + dy;
    vec4 p4 = p2 + dy;
    vec4 p5 = p1 + dz;
    vec4 p6 = p2 + dz;
    vec4 p7 = p3 + dz;
    vec4 p8 = p4 + dz;

    gl_Position = p7;
    EmitVertex();

    gl_Position = p8;
    EmitVertex();

    gl_Position = p5;
    EmitVertex();

    gl_Position = p6;
    EmitVertex();

    gl_Position = p2;
    EmitVertex();

    gl_Position = p8;
    EmitVertex();

    gl_Position = p4;
    EmitVertex();

    gl_Position = p7;
    EmitVertex();

    gl_Position = p3;
    EmitVertex();

    gl_Position = p5;
    EmitVertex();

    gl_Position = p1;
    EmitVertex();

    gl_Position = p2;
    EmitVertex();

    gl_Position = p3;
    EmitVertex();

    gl_Position = p4;
    EmitVertex();

}
Shanelleshaner answered 13/3, 2019 at 7:37 Comment(1)
You are missing an 'EndPrimitive()' call at the end I believeTrilbie
C
2

The paper mentioned above has the triangles wound in the wrong direction however is there is a simple correction, reverse the order of vertices, and it will become front-facing-outward (not inward).

1 2 5 6 7 2 4 1 3 5 8 7 3 4

And here is a set of vertices for a unit-cube. You can apply a transformation to this and render your bounding-boxes (axis-aligned or oriented).

    static const std::array<float> cube_strip = {
        +0.5, +0.5, -0.5, // Back-top-right
        -0.5, +0.5, -0.5, // Back-top-left
        +0.5, -0.5, -0.5, // Back-bottom-right
        -0.5, -0.5, -0.5, // Back-bottom-left
        -0.5, -0.5, +0.5, // Front-bottom-left
        -0.5, +0.5, -0.5, // Back-top-left
        -0.5, +0.5, +0.5, // Front-top-left
        +0.5, +0.5, -0.5, // Back-top-right
        +0.5, +0.5, +0.5, // Front-top-right
        +0.5, -0.5, -0.5, // Back-bottom-right
        +0.5, -0.5, +0.5, // Front-bottom-right
        -0.5, -0.5, +0.5, // Front-bottom-left
        +0.5, +0.5, +0.5, // Front-top-right
        -0.5, +0.5, +0.5, // Front-top-left
    };
Congratulation answered 3/12, 2021 at 19:26 Comment(0)
S
1

This version also has texture coordinates and normals just in case you need those.

I tested this with WebGL and the cube is texture mapped correctly but has peculiarities due to the fact that you really need three texture coordinates for each corner - one for each face. Because of this you can use these UVs to texture map 4 sides of the cube, but the top and bottom will not have proper textures.

const Cube = function () {
    const u0 = 0;
    const u1 = 1;

    const v0 = 0;
    const v1 = 1 / 3;
    const v2 = 2 / 3;
    const v3 = 1;

    const verticies = [
        +1, +1, -1,
        -1, +1, -1,
        +1, -1, -1,
        -1, -1, -1,
        +1, +1, +1,
        -1, +1, +1,
        -1, -1, +1,
        +1, -1, +1,
    ];

    const uvs = [
        u0, v3,
        u0, v0,
        u0, v2,
        u0, v1,
        u1, v3,
        u1, v0,
        u1, v1,
        u1, v2,
    ];

    const indexes = [3, 2, 6, 7, 4, 2, 0, 3, 1, 6, 5, 4, 1, 0];

    const v = [];
    const u = [];
    for (var i = 0; i < indexes.length; i++) {
        const corner = indexes[i];
        v.push(verticies[corner * 3 + 0]);
        v.push(verticies[corner * 3 + 1]);
        v.push(verticies[corner * 3 + 2]);

        u.push(uvs[corner * 2 + 0]);
        u.push(uvs[corner * 2 + 1]);
    }

    return {
        verticies: v, 
        uvs: u,
        normals: v
    };
};
Shiflett answered 19/3, 2021 at 3:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.