Copyright 2008-2014 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)
#include <cmath>
namespace oglplus {
class CubeExample : public Example
{
private:
    
    shapes::Cube make_cube;
    
    shapes::DrawingInstructions cube_instr;
    
    
    Context gl;
    
    
    
    
    Uniform<Mat4f> projection_matrix, camera_matrix;
    
    
public:
    CubeExample(void)
     : cube_instr(make_cube.Instructions())
     , cube_indices(make_cube.Indices())
     , projection_matrix(prog)
     , camera_matrix(prog)
    {
        
        vs.Source(
            "#version 330\n"
            "uniform mat4 ProjectionMatrix, CameraMatrix;"
            "in vec4 Position;"
            "out vec3 vertColor;"
            "void main(void)"
            "{"
            "   float angle = gl_InstanceID * 10 * 2 * 3.14159 / 360.0;"
            "   float cx = cos(angle);"
            "   float sx = sin(angle);"
            "   mat4 ModelMatrix = mat4("
            "        cx, 0.0,  sx, 0.0,"
            "       0.0, 1.0, 0.0, 0.0,"
            "       -sx, 0.0,  cx, 0.0,"
            "       0.0, 0.0, 0.0, 1.0 "
            "   ) * mat4("
            "        1.0, 0.0, 0.0, 0.0,"
            "        0.0, 1.0, 0.0, 0.0,"
            "        0.0, 0.0, 1.0, 0.0,"
            "       12.0, 0.0, 0.0, 1.0 "
            "   );"
            "   gl_Position = "
            "       ProjectionMatrix *"
            "       CameraMatrix *"
            "       ModelMatrix *"
            "       Position;"
            "   vertColor = abs(normalize((ModelMatrix*Position).xyz));"
            "}"
        );
        
        vs.Compile();
        
        fs.Source(
            "#version 330\n"
            "in vec3 vertColor;"
            "out vec4 fragColor;"
            "void main(void)"
            "{"
            "   fragColor = vec4(vertColor, 1.0);"
            "}"
        );
        
        fs.Compile();
        
        prog.AttachShader(vs);
        prog.AttachShader(fs);
        
        prog.Link();
        prog.Use();
        projection_matrix.BindTo("ProjectionMatrix");
        camera_matrix.BindTo("CameraMatrix");
        
        cube.Bind();
        
        verts.Bind(Buffer::Target::Array);
        {
            std::vector<GLfloat> data;
            GLuint n_per_vertex = make_cube.Positions(data);
            
            Buffer::Data(Buffer::Target::Array, data);
            
            VertexArrayAttrib attr(prog, "Position");
            attr.Setup<GLfloat>(n_per_vertex);
            attr.Enable();
        }
        
        gl.ClearColor(0.9f, 0.9f, 0.9f, 0.0f);
        gl.ClearDepth(1.0f);
    }
    void Reshape(GLuint width, GLuint height)
    {
        gl.Viewport(width, height);
        prog.Use();
        projection_matrix.Set(
                Degrees(70),
                double(width)/height,
                1, 50
            )
        );
    }
    {
        gl.Clear().ColorBuffer().DepthBuffer();
        
        
        camera_matrix.Set(
                18.5,
                Degrees(time * 135),
            )
        );
        
        
        cube_instr.Draw(cube_indices, 36);
    }
    {
        return time < 30.0;
    }
};
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);
}
}