Introduction to CGP library

The next exercises will be using a set of helper function provided as a library named CGP.

Files of the scene

Information on the library

CGP library provides a set of functionalities to ease 3D graphics programming such as
The library tries to be as lightweight as possible. It is written to ease 3D graphics programming, and to not hide underlying working state. Although this is not required, you should be able to understand every part of the code.
It keeps in particular the following principles

General structure of the code

Role of the different high level directories

Code editor

Use of the code library and program structure

Adding a sphere

In this first part we display a new sphere to the scene.
cgp::mesh_drawable sphere; 
mesh sphere_mesh = mesh_primitive_sphere(0.5f);
sphere.initialize(sphere_mesh, "new Sphere");
sphere.initialize(mesh_primitive_sphere(0.5f), "new Sphere");
draw(sphere, environment);
sphere.shading.color = vec3(1+std::cos(time), 1+std::sin(time), 2.0)/2.0f;

Checkbox interface

We will now add a GUI checkbox (button that can be checked) to activate/deactivate the wireframe display of the sphere.
bool display_wireframe = false;
ImGui::Checkbox("Wireframe", &gui.display_wireframe);
The last step consists in adapting the behavior of the display.
  if (gui.display_wireframe)
    draw_wireframe(sphere, environment, { 1,1,0 });

Deforming vertices of a surface

The following example show a case where mesh position are modified in the C++ code and need to be updated at each frame.
  cgp::mesh shape;
  cgp::buffer<cgp::vec3> initial_position;
  cgp::mesh_drawable shape_visual;
int N = 100;
shape = mesh_primitive_grid({ 0,0,0 }, { 1,0,0 }, { 1,1,0 }, { 0,1,0 }, N, N);
initial_position = shape.position;
shape_visual.initialize(shape, "Deforming shape");
shape_visual.shading.color = { 0.6f, 0.6f, 0.9f };
draw(shape_visual, environment);
if (gui.display_wireframe)
    draw_wireframe(shape_visual, environment, { 0,0,0 });
void scene_structure::evolve_shape()
{
    size_t const N = initial_position.size();
    for(size_t k=0; k<N; ++k)
    {
        vec3 const& p0 = initial_position[k];
        vec3& p        = shape.position[k];
        p.z = p0.z + 0.1f * std::cos(10 * p.x + 4 * timer.t);
    }
}
shape_visual.update_position(shape.position);
// Recompute normals on the CPU (given the position and the connectivity currently in the mesh structure)
shape.compute_normal();
// Send updated normals on the GPU
shape_visual.update_normal(shape.normal);
float const dz = 0.3f * noise_perlin({ p0.x + 0.2f * timer.t, p0.y, 0 }, 2) 
  + 0.015f * noise_perlin({ 4 * p0.x, 4 * p0.y, timer.t }, 2);

Texture

Textures images can also be associated to surface
Note that the per-vertex uv coordinates need to be defined correctly to get the mapping of the image on the surface.
// Reset the color of the shape to white (only the texture image will be seen)
shape_visual.shading.color = {1,1,1};

// Load the image and associate the texture id to the structure
shape_visual.texture = opengl_texture_to_gpu(image_load_png("assets/squirrel.jpg"));