Copyright 2008-2013 Matus Chochlik. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
namespace oglplus {
class CubeExample : public Example
{
private:
    
    Context gl;
    
    
    
    
    
public:
    CubeExample(void)
    {
        
        vs.Source(
            "#version 330\n"
            "uniform mat4 ProjectionMatrix, CameraMatrix;"
            "in vec4 Position;"
            "in vec3 Normal;"
            "out vec3 vertNormal;"
            "void main(void)"
            "{"
            "   vertNormal = Normal;"
            "   gl_Position = ProjectionMatrix *"
            "       CameraMatrix *"
            "       Position;"
            "}"
        );
        
        vs.Compile();
        
        
        fs.Source(
            "#version 330\n"
            "in vec3 vertNormal;"
            "out vec4 fragColor;"
            "void main(void)"
            "{"
            "   fragColor = vec4(abs(vertNormal), 1.0);"
            "}"
        );
        
        fs.Compile();
        
        prog.AttachShader(vs);
        prog.AttachShader(fs);
        
        prog.Link();
        prog.Use();
        
        cube.Bind();
        const GLfloat c[8][3] = {
            {-0.5f, -0.5f, +0.5f},
            {-0.5f, -0.5f, -0.5f},
            {-0.5f, +0.5f, -0.5f},
            {-0.5f, +0.5f, +0.5f},
            {+0.5f, -0.5f, +0.5f},
            {+0.5f, -0.5f, -0.5f},
            {+0.5f, +0.5f, -0.5f},
            {+0.5f, +0.5f, +0.5f}
        };
        const GLuint vertex_count = 6 * 2 * 3;
        const GLfloat cube_vertices[vertex_count * 3] = {
            c[0][0], c[0][1], c[0][2],
            c[2][0], c[2][1], c[2][2],
            c[1][0], c[1][1], c[1][2],
            c[0][0], c[0][1], c[0][2],
            c[3][0], c[3][1], c[3][2],
            c[2][0], c[2][1], c[2][2],
            c[0][0], c[0][1], c[0][2],
            c[1][0], c[1][1], c[1][2],
            c[4][0], c[4][1], c[4][2],
            c[1][0], c[1][1], c[1][2],
            c[5][0], c[5][1], c[5][2],
            c[4][0], c[4][1], c[4][2],
            c[1][0], c[1][1], c[1][2],
            c[2][0], c[2][1], c[2][2],
            c[5][0], c[5][1], c[5][2],
            c[2][0], c[2][1], c[2][2],
            c[6][0], c[6][1], c[6][2],
            c[5][0], c[5][1], c[5][2],
            c[4][0], c[4][1], c[4][2],
            c[5][0], c[5][1], c[5][2],
            c[6][0], c[6][1], c[6][2],
            c[4][0], c[4][1], c[4][2],
            c[6][0], c[6][1], c[6][2],
            c[7][0], c[7][1], c[7][2],
            c[2][0], c[2][1], c[2][2],
            c[3][0], c[3][1], c[3][2],
            c[7][0], c[7][1], c[7][2],
            c[2][0], c[2][1], c[2][2],
            c[7][0], c[7][1], c[7][2],
            c[6][0], c[6][1], c[6][2],
            c[0][0], c[0][1], c[0][2],
            c[4][0], c[4][1], c[4][2],
            c[3][0], c[3][1], c[3][2],
            c[3][0], c[3][1], c[3][2],
            c[4][0], c[4][1], c[4][2],
            c[7][0], c[7][1], c[7][2]
        };
        
        verts.Bind(Buffer::Target::Array);
        
        Buffer::Data(
            Buffer::Target::Array,
            vertex_count * 3,
            cube_vertices
        );
        
        VertexArrayAttrib vert_attr(prog, "Position");
        vert_attr.Setup<
Vec3f>();
        vert_attr.Enable();
        const GLfloat n[6][3] = {
            {-1.0f,  0.0f,  0.0f},
            { 0.0f, -1.0f,  0.0f},
            { 0.0f,  0.0f, -1.0f},
            { 1.0f,  0.0f,  0.0f},
            { 0.0f,  1.0f,  0.0f},
            { 0.0f,  0.0f,  1.0f}
        };
        GLfloat cube_normals[vertex_count * 3];
        for(GLuint f=0;f!=6;++f)
            for(GLuint v=0;v!=6;++v)
                for(GLuint ci=0;ci!=3;++ci)
                    cube_normals[(f*6+v)*3+ci] = n[f][ci];
        
        normals.Bind(Buffer::Target::Array);
        
        Buffer::Data(
            Buffer::Target::Array,
            vertex_count * 3,
            cube_normals
        );
        
        VertexArrayAttrib normal_attr(prog, "Normal");
        normal_attr.Setup<
Vec3f>();
        normal_attr.Enable();
        
        
        Uniform<Mat4f>(prog, 
"CameraMatrix").
Set(
            )
        );
        
        gl.ClearColor(1.0f, 1.0f, 1.0f, 0.0f);
        gl.ClearDepth(1.0f);
    }
    void Reshape(GLuint width, GLuint height)
    {
        gl.Viewport(width, height);
        prog.Use();
        Uniform<Mat4f>(prog, 
"ProjectionMatrix").
Set(
                Degrees(48),
                GLfloat(width)/height,
                1, 100
            )
        );
    }
    {
        gl.Clear().ColorBuffer().DepthBuffer();
    }
};
void setupExample(ExampleParams& ){ }
std::unique_ptr<ExampleThread> makeExampleThread(
    Example& ,
    unsigned ,
    const ExampleParams& 
){ return std::unique_ptr<ExampleThread>(); }
std::unique_ptr<Example> makeExample(const ExampleParams& )
{
    return std::unique_ptr<Example>(new CubeExample);
}
}