Basic vbo mesh question


#1

I’m trying to understand VboMesh by drawing a cube but am having difficulty with normals. I’ve got a camera set up, and I’m drawing a cube, here called Box. Below is my Box definition and a screenshot of the results. What might I be doing wrong?

#include "cinder/app/App.h"
#include "Box.h"

using namespace ci;
using namespace std;

Box::Box() {}

void Box::init() {
    
    vector < uint32_t >    mIndices;
    vector < vec3 >         mPositions;
    vector < vec3 >         mNormals;
    
    gl::VboMeshRef        mBox;
    gl::GlslProgRef         mShader;
    
    float X = 1.0f;
    float Y = 1.0f;
    float Z = 1.0f;
    
    mPositions.push_back( vec3( -X, -Y, -Z ) );
    mPositions.push_back( vec3( -X, -Y, Z  ) );
    mPositions.push_back( vec3( X, -Y, Z ) );
    mPositions.push_back( vec3( X, -Y, -Z ) );
    mPositions.push_back( vec3( -X, Y, -Z ) );
    mPositions.push_back( vec3( -X, Y, Z ) );
    mPositions.push_back( vec3( X, Y, Z ) );
    mPositions.push_back( vec3( X, Y, -Z ) );
    
    mIndices.push_back( 0 );
    mIndices.push_back( 1 );
    mIndices.push_back( 3 );
    
    mIndices.push_back( 1 );
    mIndices.push_back( 2 );
    mIndices.push_back( 3 );
    
    mIndices.push_back( 4 );
    mIndices.push_back( 7 );
    mIndices.push_back( 5 );
    
    mIndices.push_back( 7 );
    mIndices.push_back( 6 );
    mIndices.push_back( 5 );
    
    mIndices.push_back( 0 );
    mIndices.push_back( 4 );
    mIndices.push_back( 1 );
    
    mIndices.push_back( 4 );
    mIndices.push_back( 5 );
    mIndices.push_back( 1 );
    
    mIndices.push_back( 2 );
    mIndices.push_back( 6 );
    mIndices.push_back( 3 );
    
    mIndices.push_back( 6 );
    mIndices.push_back( 7 );
    mIndices.push_back( 3 );
    
    mIndices.push_back( 1 );
    mIndices.push_back( 5 );
    mIndices.push_back( 2 );
    
    mIndices.push_back( 5 );
    mIndices.push_back( 6 );
    mIndices.push_back( 2 );
    
    mIndices.push_back( 3 );
    mIndices.push_back( 7 );
    mIndices.push_back( 0 );
    
    mIndices.push_back( 7 );
    mIndices.push_back( 4 );
    mIndices.push_back( 0 );
    
    mNormals.push_back( vec3( 0, -1, 0 ) );
    mNormals.push_back( vec3( 0, 1, 0 ) );
    mNormals.push_back( vec3( -1, 0, 0 ) );
    mNormals.push_back( vec3( 1, 0, 0 ) );
    mNormals.push_back( vec3( 0, 0, 1 ) );
    mNormals.push_back( vec3( 0, 0, -1 ) );

    
    vector < gl::VboMesh::Layout > bufferLayout = {
    gl::VboMesh::Layout().usage( GL_STATIC_DRAW ).attrib( geom::Attrib::POSITION , 3 ),
    gl::VboMesh::Layout().usage( GL_STATIC_DRAW ).attrib( geom::Attrib::NORMAL , 3 )
    };
    
    mBox = gl::VboMesh::create( mPositions.size(), GL_TRIANGLES, bufferLayout, mIndices.size(), GL_UNSIGNED_INT );
    
    mBox->bufferAttrib( geom::Attrib::POSITION, mPositions );
    mBox->bufferAttrib( geom::Attrib::NORMAL, mNormals );
    mBox->bufferIndices( mIndices.size() * sizeof( uint32_t ), mIndices.data() );
    
    auto scale = geom::Scale(3,3,3);                            // scale from normalized space to viewing space
    mShader = gl::getStockShader( gl::ShaderDef().lambert() );  // using a Cinder generic shader, since we always need a shader to draw
    mBatch = gl::Batch::create( mBox , mShader );
    
}

void Box::draw() {
    mBatch->draw();
}


#2

You actually need more vertices and normals than you think for a cube. Each corner needs to have 3 separate normals to work correctly; i.e one that runs along each of the 3 axes.

Have a look at the vertices and normals that the geom::Cube() primitive generates to see what I mean.

Looking at your code, it seems to me that this is more an educational exercise to work with VboMeshes directly, but just in case all you’re after is a cube, I should tell you you can do the following and save yourself a lot of trouble.

    mShader = gl::getStockShader( gl::ShaderDef().lambert() );  // using a Cinder generic shader, since we always need a shader to draw
    mBatch = gl::Batch::create( geom::Cube() >> geom::Scale(3,3,3) , mShader );

#3

Correct, a proper cube requires 24 vertices and normals (6 faces * 4 vertices). Apart from that, your code is flawless.

Want another interesting challenge? Try a cone. You’ll find out it’s much harder than you think.


#4

Ah, okay. Yes, I’m doing this as a vbo mesh to learn things like this about working in OpenGL and Cinder. Thank you both so much.