Introduction to INF585 exercises

Download INF585 exercises

Download any of these archive containing all the necessary codes
    • Do not use the "Code \(\rightarrow\) Download Zip" option from github as you would not get the library
Notes on the requirements

Introductory scene

Information on the library (only general information, no exercise)

CGP library provides a set of functionalities to ease 3D graphics programming such as
Structures and functions of the library are accessible in the namespace cgp::
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 You may look at the files in the cgp/ directory to understand how things works, but in normal cases you should not have to modify these files.

Code editor

Use of the code library and program structure (the exercise starts here)

In the following you will only modify code in the file scene.cpp (and scene.hpp).

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_data_on_gpu(sphere_mesh);
  • (or variant: simply in one line without explicitely storing the mesh variable)
sphere.initialize_data_on_gpu(mesh_primitive_sphere(0.5f));
draw(sphere, environment);
sphere.material.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 the 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.
  mesh shape;
  numarray<vec3> initial_position;
  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_data_on_gpu(shape);
shape_visual.material.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(float time)
{
    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 * time);
    }
}
shape_visual.vbo_position.update(shape.position);
// Recompute normals on the CPU (given the position and the connectivity currently in the mesh structure)
shape.normal_update();
// Send updated normals on the GPU
shape_visual.vbo_normal.update(shape.normal);
float const dz = 0.3f * noise_perlin({ p0.x + 0.2f * time, p0.y, 0 }, 2) + 0.015f * noise_perlin({ 4 * p0.x, 4 * p0.y, time }, 2);
p = p0 + vec3(0, 0, dz);

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.material.color = {1,1,1};

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