Introduction Ani3D

Code Download

Download the code of the labs from

Introductory scene

Compile and execute the code in the directory scenes_epita_ani3d/01_introduction/
Note: If you are not familiar with C++/OpenGL compilation on your system, follow first these instructions to compile the scene: Detailed Installation and Compilation Instructions
Notes on the requirements
Use of IDE
The library contains multiples files. Make sure you use a sufficiently advanced (or well parameterized) IDE to have
A camera model is already provided. The camera is defined by a position and an orientation relative to a center around which it can rotate. You should be able to interactively control the parameters of the camera as follow:

General information on the code structure and editing

General structure of the code

Role of the different high level directories

Use of the code library and program structure

Adding a shape in the scene

We will see an example of creating and adding a shape (a triangulated sphere) in the 3D sphere. This is done in 3 steps using the files scene.cpp and scene.hpp:
mesh_drawable sphere;
mesh sphere_mesh = mesh_primitive_sphere();
sphere.initialize_data_on_gpu(sphere_mesh);
draw(sphere, environment);
> Recompile and run the new code, a white sphere should appear at the origin of the scene.
Note that there is two type of mesh structures in use
In the case of the example:

Modification of the sphere

You can adapt some global parameter attach to the shape such as its material (color, shading), and model matrix (translation, rotation, scaling) in modifying pre-defined variables of the mesh_drawable class. For instance, write in the initialize() function (after the line sphere.initialize_data_on_gpu(...)):
// to add after "sphere.initialize(sphere_mesh, "Sphere");"
sphere.model.scaling = 0.2f; // coordinates are multiplied by 0.2 in the shader
sphere.model.translation = {1,2,0}; // coordinates are offseted by {1,2,0} in the shader
sphere.material.color = { 1,0.5f,0.5f }; // sphere will appear red (r,g,b components in [0,1])
> Re-compile and run again the code to observe the modification.
assets/sphere.jpg
Notes:

Load external mesh

CGP library provides pre-coded basic primitives (spheres, cube, cylinder, cone, etc) via the call "mesh_primitive_xxx". For more complex shapes, you can also load a mesh from an external file (dowloaded file or created from 3D modeler such as Blender) using the obj file loader provided by default.
This example shows the load of a file representing a camel.
mesh_drawable camel;
// mesh_load_file_obj: read a .obj file and return a mesh structure
mesh camel_mesh = mesh_load_file_obj(project::path+"assets/camel.obj");

// Classical initialization of a mesh_drawable structure
camel.initialize_data_on_gpu(camel_mesh);

// Adjusting size and position of the shape
camel.model.scaling = 0.5f;
camel.model.translation = { -1,1,0.5f };
draw(camel, environment);
assets/camel.jpg

Wireframe draw

It is often usefull to visualize the mesh in wireframe to better understand the triangulation structure and/or debuging. The function draw_wireframe(mesh_drawable, environment) is provided by the library to this end.
Add the following lines in the display_frame() et observe the additional wireframe display.
draw_wireframe(ground, environment);
draw_wireframe(sphere, environment);
draw_wireframe(cube, environment);
draw_wireframe(camel, environment);
assets/camel_wireframe.jpg
Note that the wireframe is displayed in blue color by default. A specific (r,g,b) color can be set when calling the function as in the following:
// Wireframe displayed in red thanks to the third argument {r,g,b}
draw_wireframe(camel, environment, {1,0,0});

Checkbox interface

We will now add a GUI checkbox (button that can be checked) to activate/deactivate the wireframe display of the sphere. The principle is the following:
struct gui_parameters {
    ...
    bool display_wireframe = false;
};
ImGui::Checkbox("Wireframe", &gui.display_wireframe);
if (gui.display_wireframe) {
    draw_wireframe(ground, environment);
    draw_wireframe(sphere, environment);
    draw_wireframe(cube, environment);
    draw_wireframe(camel, environment);
}

Placing several similar elements

// (In the scene_structure header)
std::vector<vec3> cone_positions;
mesh_drawable cone;
// (In the initialization function)
cone.initialize_data_on_gpu( mesh_primitive_cone(0.1f, 0.2f) );
const int N_cone = 40;
for (int k = 0; k < N_cone; ++k)
{
    float x = rand_interval(-2, 2);
    float y = rand_interval(-2, 2);

    cone_positions.push_back({ x,y,-0.51 });
}
// (In the display_frame function)
for (int k = 0; k < cone_positions.size(); ++k)
{
    cone.model.translation = cone_positions[k];
    draw(cone, environment);
}
Display the scene and observe the result (you should see a set of cones on the floor)
Note that

Exercise