Concept [ edit ]

We analyze the object:

Minimum coordinates in X, Y and Z

Maximum coordinates in X, Y and Z

We compute the size necessary for the object: max-min in X, Y and Z

in X, Y and Z We compute the center of the object: (min+max)/2 in X, Y and Z

We compute of cube around the object:

We prepare a cube of size 1 (1x1x1), centered on the origin

We scale it by the size of the object

We center it on the object

To draw the cube:

We draw the front face using 1 looping line

We draw the back face using 1 looping line

We draw 4 orthogonal lines to join both faces

Code [ edit ]

void draw_bbox ( struct mesh * mesh ) { if ( mesh -> vertices . size () == 0 ) return ; // Cube 1x1x1, centered on origin GLfloat vertices [] = { - 0.5 , - 0.5 , - 0.5 , 1.0 , 0.5 , - 0.5 , - 0.5 , 1.0 , 0.5 , 0.5 , - 0.5 , 1.0 , - 0.5 , 0.5 , - 0.5 , 1.0 , - 0.5 , - 0.5 , 0.5 , 1.0 , 0.5 , - 0.5 , 0.5 , 1.0 , 0.5 , 0.5 , 0.5 , 1.0 , - 0.5 , 0.5 , 0.5 , 1.0 , }; GLuint vbo_vertices ; glGenBuffers ( 1 , & vbo_vertices ); glBindBuffer ( GL_ARRAY_BUFFER , vbo_vertices ); glBufferData ( GL_ARRAY_BUFFER , sizeof ( vertices ), vertices , GL_STATIC_DRAW ); glBindBuffer ( GL_ARRAY_BUFFER , 0 ); GLushort elements [] = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 0 , 4 , 1 , 5 , 2 , 6 , 3 , 7 }; GLuint ibo_elements ; glGenBuffers ( 1 , & ibo_elements ); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , ibo_elements ); glBufferData ( GL_ELEMENT_ARRAY_BUFFER , sizeof ( elements ), elements , GL_STATIC_DRAW ); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ); GLfloat min_x , max_x , min_y , max_y , min_z , max_z ; min_x = max_x = mesh -> vertices [ 0 ]. x ; min_y = max_y = mesh -> vertices [ 0 ]. y ; min_z = max_z = mesh -> vertices [ 0 ]. z ; for ( int i = 0 ; i < mesh -> vertices . size (); i ++ ) { if ( mesh -> vertices [ i ]. x < min_x ) min_x = mesh -> vertices [ i ]. x ; if ( mesh -> vertices [ i ]. x > max_x ) max_x = mesh -> vertices [ i ]. x ; if ( mesh -> vertices [ i ]. y < min_y ) min_y = mesh -> vertices [ i ]. y ; if ( mesh -> vertices [ i ]. y > max_y ) max_y = mesh -> vertices [ i ]. y ; if ( mesh -> vertices [ i ]. z < min_z ) min_z = mesh -> vertices [ i ]. z ; if ( mesh -> vertices [ i ]. z > max_z ) max_z = mesh -> vertices [ i ]. z ; } glm :: vec3 size = glm :: vec3 ( max_x - min_x , max_y - min_y , max_z - min_z ); glm :: vec3 center = glm :: vec3 (( min_x + max_x ) / 2 , ( min_y + max_y ) / 2 , ( min_z + max_z ) / 2 ); glm :: mat4 transform = glm :: translate ( glm :: mat4 ( 1 ), center ) * glm :: scale ( glm :: mat4 ( 1 ), size ); /* Apply object's transformation matrix */ glm :: mat4 m = mesh -> object2world * transform ; glUniformMatrix4fv ( uniform_m , 1 , GL_FALSE , glm :: value_ptr ( m )); glBindBuffer ( GL_ARRAY_BUFFER , vbo_vertices ); glEnableVertexAttribArray ( attribute_v_coord ); glVertexAttribPointer ( attribute_v_coord , // attribute 4 , // number of elements per vertex, here (x,y,z,w) GL_FLOAT , // the type of each element GL_FALSE , // take our values as-is 0 , // no extra data between each position 0 // offset of first element ); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , ibo_elements ); glDrawElements ( GL_LINE_LOOP , 4 , GL_UNSIGNED_SHORT , 0 ); glDrawElements ( GL_LINE_LOOP , 4 , GL_UNSIGNED_SHORT , ( GLvoid * )( 4 * sizeof ( GLushort ))); glDrawElements ( GL_LINES , 8 , GL_UNSIGNED_SHORT , ( GLvoid * )( 8 * sizeof ( GLushort ))); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ); glDisableVertexAttribArray ( attribute_v_coord ); glBindBuffer ( GL_ARRAY_BUFFER , 0 ); glDeleteBuffers ( 1 , & vbo_vertices ); glDeleteBuffers ( 1 , & ibo_elements ); }

Intersection with surfaces [ edit ]

As seen in Scientific tutorial 05, you can improve situations where lines and surfaces are mixing, by using:

/* main */ glEnable ( GL_POLYGON_OFFSET_FILL ); glPolygonOffset ( 1 , 0 );

Keep GL_POLYGON_OFFSET_FILL enabled even after you draw the lines, it needs to be enabled when drawing the surfaces as well.

Bounding box for a sphere

You can also increase the line thickness if need be:

glLineWidth ( 2 );