void HexagonMirrorApp::draw()
{
    // clear the window
    gl::clear();

    // activate our camera
    gl::pushMatrices();
    gl::setMatrices( mCamera.getCamera() );

    // set render states
    gl::enable( GL_CULL_FACE );
    gl::enableDepthRead();
    gl::enableDepthWrite();
    gl::color( Color::white() );

    if( mVboMesh && mShaderInstanced && mBuffer )
    {
        // bind webcam image
        if( mWebcamTexture )
            mWebcamTexture.bind(0);

        // bind the shader, which will do all the hard work for us
        mShaderInstanced.bind();
        mShaderInstanced.uniform( "texture", 0 );
        mShaderInstanced.uniform( "scale", Vec2f( 1.0f / (3.0f * INSTANCES_PER_ROW), 1.0f / (3.0f * INSTANCES_PER_ROW) ) );

        // bind the buffer containing the model matrix for each instance,
        // this will allow us to pass this information as a vertex shader attribute.
        // See: initializeBuffer()
        glBindVertexArray(mVAO);

        // we do all positioning in the shader, and therefor we only need
        // a single draw call to render all instances.
        drawInstanced( mVboMesh, NUM_INSTANCES );

        // make sure our VBO is no longer bound
        mVboMesh.unbindBuffers();

        // unbind vertex array object containing our buffer
        glBindVertexArray(0);

        // unbind shader
        mShaderInstanced.unbind();

        if( mWebcamTexture )
            mWebcamTexture.unbind();
    }

    // reset render states
    gl::disableDepthWrite();
    gl::disableDepthRead();
    gl::disable( GL_CULL_FACE );

    // restore 2D drawing
    gl::popMatrices();
}
void RepulsionApp::createSphere( gl::VboMesh &vbo, int res )
{
	float X = 0.525731112119f; 
	float Z = 0.850650808352f;
	
	static Vec3f verts[12] = {
		Vec3f( -X, 0.0f, Z ), Vec3f( X, 0.0f, Z ), Vec3f( -X, 0.0f, -Z ), Vec3f( X, 0.0f, -Z ),
		Vec3f( 0.0f, Z, X ), Vec3f( 0.0f, Z, -X ), Vec3f( 0.0f, -Z, X ), Vec3f( 0.0f, -Z, -X ),
		Vec3f( Z, X, 0.0f ), Vec3f( -Z, X, 0.0f ), Vec3f( Z, -X, 0.0f ), Vec3f( -Z, -X, 0.0f ) };
	
	static GLuint triIndices[20][3] = { 
		{0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1}, {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
		{7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6}, {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
	
	gl::VboMesh::Layout layout;
	layout.setStaticPositions();
	layout.setStaticNormals();
	layout.setStaticColorsRGB();
	
	mPosCoords.clear();
	mNormals.clear();
	mColors.clear();
	
	float invWidth = 1.0f/(float)FBO_WIDTH;
	float invHeight = 1.0f/(float)FBO_HEIGHT;
	for( int x = 0; x < FBO_WIDTH; ++x ) {
		for( int y = 0; y < FBO_HEIGHT; ++y ) {
			float u = ( (float)x + 0.5f ) * invWidth;
			float v = ( (float)y + 0.5f ) * invHeight;
			Colorf c = Colorf( u, v, 0.0f );
			
			for( int i=0; i<20; i++ ){
				drawSphereTri( verts[triIndices[i][0]], verts[triIndices[i][1]], verts[triIndices[i][2]], res, c );
			}
		}
	}
	vbo = gl::VboMesh( mPosCoords.size(), 0, layout, GL_TRIANGLES );	
	vbo.bufferPositions( mPosCoords );
	vbo.bufferNormals( mNormals );
	vbo.bufferColorsRGB( mColors );
	vbo.unbindBuffers();
}
void CatalogApp::initFaintVbo()
{
	gl::VboMesh::Layout layout;
	layout.setStaticPositions();
	layout.setStaticColorsRGB();
	
	int numFaintStars	= mFaintStars.size();
	mFaintVbo			= gl::VboMesh( numFaintStars, 0, layout, GL_POINTS );
	vector<Vec3f> positions;
	vector<Color> colors;

	for( int i=0; i<numFaintStars; i++ ){
		positions.push_back( mFaintStars[i]->mPos );
		colors.push_back( Color( mFaintStars[i]->mColor, 0.0f, 0.0f ) );
	}
	
	mFaintVbo.bufferPositions( positions );
	mFaintVbo.bufferColorsRGB( colors );
	mFaintVbo.unbindBuffers();
}
void CatalogApp::initBrightVbo()
{
	gl::VboMesh::Layout layout;
	layout.setStaticPositions();
	layout.setStaticTexCoords2d();
	layout.setStaticColorsRGB();
	
	int numVertices = FBO_WIDTH * FBO_HEIGHT;
	// 1 quad per particle
	// 2 triangles make up the quad
	// 3 points per triangle
	mBrightVbo		= gl::VboMesh( numVertices * 2 * 3, 0, layout, GL_TRIANGLES );
	
	float s = 0.5f;
	Vec3f p0( -s, -s, 0.0f );
	Vec3f p1( -s,  s, 0.0f );
	Vec3f p2(  s,  s, 0.0f );
	Vec3f p3(  s, -s, 0.0f );
	
	Vec2f t0( 0.0f, 0.0f );
	Vec2f t1( 0.0f, 1.0f );
	Vec2f t2( 1.0f, 1.0f );
	Vec2f t3( 1.0f, 0.0f );
	
	vector<Vec3f>		positions;
	vector<Vec2f>		texCoords;
	vector<Color>		colors;
	
	for( int x = 0; x < FBO_WIDTH; ++x ) {
		for( int y = 0; y < FBO_HEIGHT; ++y ) {
			float u = (float)x/(float)FBO_WIDTH;
			float v = (float)y/(float)FBO_HEIGHT;
			Color c = Color( u, v, 0.0f );
			
			positions.push_back( p0 );
			positions.push_back( p1 );
			positions.push_back( p2 );
			texCoords.push_back( t0 );
			texCoords.push_back( t1 );
			texCoords.push_back( t2 );
			colors.push_back( c );
			colors.push_back( c );
			colors.push_back( c );
			
			positions.push_back( p0 );
			positions.push_back( p2 );
			positions.push_back( p3 );
			texCoords.push_back( t0 );
			texCoords.push_back( t2 );
			texCoords.push_back( t3 );
			colors.push_back( c );
			colors.push_back( c );
			colors.push_back( c );
		}
	}
	
	mBrightVbo.bufferPositions( positions );
	mBrightVbo.bufferTexCoords2d( 0, texCoords );
	mBrightVbo.bufferColorsRGB( colors );
	mBrightVbo.unbindBuffers();
}