From 9832a778b28df2a5592be893e5d41c157fed5cee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?No=C3=A9?= <noe.artru@polytechnique.org>
Date: Sat, 20 May 2023 22:14:44 +0200
Subject: [PATCH] Rassification du code pour projectiles et bats

---
 projet-code/scenes_inf443/base/src/ball.cpp   |  19 +-
 projet-code/scenes_inf443/base/src/ball.hpp   |   4 +-
 projet-code/scenes_inf443/base/src/bat.cpp    | 118 +----------
 projet-code/scenes_inf443/base/src/bat.hpp    |  19 +-
 projet-code/scenes_inf443/base/src/bats.cpp   |  61 ++++++
 projet-code/scenes_inf443/base/src/bats.hpp   |  21 ++
 .../scenes_inf443/base/src/projectile.cpp     |  69 ++-----
 .../scenes_inf443/base/src/projectile.hpp     |  30 ++-
 .../scenes_inf443/base/src/projectiles.cpp    |  43 ++++
 .../scenes_inf443/base/src/projectiles.hpp    |  22 ++
 projet-code/scenes_inf443/base/src/scene.cpp  | 195 +++++-------------
 projet-code/scenes_inf443/base/src/scene.hpp  |  22 +-
 .../scenes_inf443/base/src/terrain.cpp        |  24 +--
 .../scenes_inf443/base/src/terrain.hpp        |   6 +-
 14 files changed, 277 insertions(+), 376 deletions(-)
 create mode 100644 projet-code/scenes_inf443/base/src/bats.cpp
 create mode 100644 projet-code/scenes_inf443/base/src/bats.hpp
 create mode 100644 projet-code/scenes_inf443/base/src/projectiles.cpp
 create mode 100644 projet-code/scenes_inf443/base/src/projectiles.hpp

diff --git a/projet-code/scenes_inf443/base/src/ball.cpp b/projet-code/scenes_inf443/base/src/ball.cpp
index 7a32f47..644d8b8 100644
--- a/projet-code/scenes_inf443/base/src/ball.cpp
+++ b/projet-code/scenes_inf443/base/src/ball.cpp
@@ -1,5 +1,6 @@
 #include "ball.hpp"
 #include "terrain.hpp"
+#include "settings.hpp"
 
 void ball::initialize(int n)
 {
@@ -38,10 +39,10 @@ void ball::add_ball(vec3 new_pos, vec3 new_dir) {
 
 }
 
-void ball::simulate(float dt, float terrain_length) {
+void ball::simulate(float dt) {
 	for (int i = 0; i < N; i++) {
-		if (pos[i][2] < -1 || cgp::abs(pos[i][0]) > terrain_length / 2 || cgp::abs(pos[i][1]) > terrain_length / 2) {
-			pos[i] = { 0,0, evaluate_terrain_height(0,0, terrain_length) };
+		if (pos[i][2] < -1 || cgp::abs(pos[i][0]) > terrain_length() / 2 || cgp::abs(pos[i][1]) > terrain_length() / 2) {
+			pos[i] = { 0,0, evaluate_terrain_height(0,0) };
 			v[i] = { 3 * rand_interval(), 3 * rand_interval(), 4 + i };
 		}
 		else {
@@ -49,8 +50,8 @@ void ball::simulate(float dt, float terrain_length) {
 			v[i][2] -= 10 * dt;
 		}
 
-		if (pos[i][2] < evaluate_terrain_height(pos[i][0], pos[i][1], terrain_length)) {
-			vec3 normal = normalize(terrain_orientation(pos[i][0], pos[i][1], terrain_length));
+		if (pos[i][2] < evaluate_terrain_height(pos[i][0], pos[i][1])) {
+			vec3 normal = normalize(terrain_orientation(pos[i][0], pos[i][1]));
 
 			vec3 temp = v[i] - dot(v[i], normal) * normal;
 
@@ -64,11 +65,11 @@ void ball::simulate(float dt, float terrain_length) {
 	}
 }
 
-vec3 terrain_orientation(float x, float y, float terrain_length) {
-	float z = evaluate_terrain_height(x, y, terrain_length);
+vec3 terrain_orientation(float x, float y) {
+	float z = evaluate_terrain_height(x, y);
 	float step = 0.1f;
-	vec3 u = { step, 0, evaluate_terrain_height(x + step,y, terrain_length) - z };
-	vec3 v = { 0, step, evaluate_terrain_height(x,y + step, terrain_length) - z };
+	vec3 u = { step, 0, evaluate_terrain_height(x + step,y) - z };
+	vec3 v = { 0, step, evaluate_terrain_height(x,y + step) - z };
 
 	return cross(v, u);
 }
diff --git a/projet-code/scenes_inf443/base/src/ball.hpp b/projet-code/scenes_inf443/base/src/ball.hpp
index 1e8fd58..1f82ba9 100644
--- a/projet-code/scenes_inf443/base/src/ball.hpp
+++ b/projet-code/scenes_inf443/base/src/ball.hpp
@@ -14,10 +14,10 @@ struct ball {
 	mesh_drawable mesh;
 
 	void initialize(int n);
-	void simulate(float dt, float terrain_length);
+	void simulate(float dt);
 	void add_ball(vec3 new_pos, vec3 new_dir);
 	void reset();
 };
 
-vec3 terrain_orientation(float x, float y, float terrain_length);
+vec3 terrain_orientation(float x, float y);
 
diff --git a/projet-code/scenes_inf443/base/src/bat.cpp b/projet-code/scenes_inf443/base/src/bat.cpp
index df8518f..1198b79 100644
--- a/projet-code/scenes_inf443/base/src/bat.cpp
+++ b/projet-code/scenes_inf443/base/src/bat.cpp
@@ -4,84 +4,14 @@
 #include "interpolation.hpp"
 #include "terrain.hpp"
 
-void bat::initialize_bat()
+void bat::initialize_mvt(vec3 p, numarray<vec3> key_positions, numarray<float> key_times)
 {
-	
-	// Initialize the temporary mesh_drawable that will be inserted in the hierarchy
-	mesh_drawable body;
-	mesh_drawable wing1;
-	mesh_drawable wing2;
-
-	// Create the geometry of the meshes
-	//   Note: this geometry must be set in their local coordinates with respect to their position in the hierarchy (and with respect to their animation)
-
-	body.initialize_data_on_gpu(mesh_load_file_obj(project::path + "assets/batbodyok.obj"));
-	wing1.initialize_data_on_gpu(mesh_load_file_obj(project::path + "assets/batwingleft.obj"));
-	wing2.initialize_data_on_gpu(mesh_load_file_obj(project::path + "assets/batwingright.obj"));
-
-
-	// Scale the model
-	//body.model.scaling = 0.2f;
-	//wing1.model.scaling = 0.2f;
-	//wing2.model.scaling = 0.2f;
-
-
-
-	// Set the color of some elements
-	body.material.color = { 0.3f,0.3f,0.3f };
-	wing1.material.color = { 0.2f,0.2f,0.2f };
-	wing2.material.color = { 0.2f,0.2f,0.2f };
-
-
-
-
-
-
-
-	// Add the elements in the hierarchy
-	//   The syntax is hierarchy.add(mesh_drawable, "name of the parent element", [optional: local translation in the hierarchy])
-	//   Notes: 
-	//     - An element must necessarily be added after its parent
-	//     - The first element (without explicit name of its parent) is assumed to be the root.
-
-	bat.add(body, "Bat base");
-	bat.add(wing1, "Bat wing left1", "Bat base", { -0.05f,0,0 });
-	bat.add(wing2, "Bat wing right1", "Bat base", { 0.05f,0,0 });
-
-
-	N = 0;
-	size.resize(N);
-	isdead.resize(N);
-	pos.resize(N);
-	pos2.resize(N);
-	keyframe.resize(N);
-}
-
-
-
-void bat::initialize_mvt(vec3 p, int m, float terrain_length)
-{
-	// Definition of the initial data
-	//--------------------------------------//
-
-	// Key 3D positions
-	numarray<vec3> key_positions =
-	{ {-2,1,0}, {0,1,0}, {2,1,0}, {1,3,0}, {2,3,0}, {2,3,1}, {2,2.5,1.5}, {1.5,0,1}, {1.5,0,-1}, {0,0,-1}, {0,-0.5,-1}, {-2,1,-1} };
-
-	float h = 20 + evaluate_terrain_height(0, 0, terrain_length);
 	for (int i = 0; i < key_positions.size(); i++) {
-		key_positions[i] *= size[m];
-		key_positions[i][2] += h;
 		key_positions[i] += p;
 	}
 
-	// Key times (time at which the position must pass in the corresponding position)
-	numarray<float> key_times =
-	{ 0.0f, 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 3.75f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f };
-
 	// Initialize the helping structure to display/interact with these positions
-	keyframe[m].initialize(key_positions, key_times);
-
+	keyframe.initialize(key_positions, key_times);
 
 	// Set timer bounds
 	// The timer must span a time interval on which the interpolation can be conducted
@@ -92,48 +22,20 @@ void bat::initialize_mvt(vec3 p, int m, float terrain_length)
 	timer_mvt.t = timer_mvt.t_min;
 }
 
-void bat::display_mvt()
+void bat::update_mvt()
 {
-
 	// Update the current time
 	timer_mvt.update();
 	float t = timer_mvt.t;
 
+	// clear trajectory when the timer restart
+	if (t < timer_mvt.t_min + 0.1f)
+		keyframe.trajectory.clear();
 
-	for (int m = 0; m < N; m++) {
-		// clear trajectory when the timer restart
-		if (t < timer_mvt.t_min + 0.1f)
-			keyframe[m].trajectory.clear();
-
-		if (t + 0.1f > timer_mvt.t_max) pos2[m] = interpolation(0.01f, keyframe[m].key_positions, keyframe[m].key_times, 0.5f);
-		else pos2[m] = interpolation((t + 0.1f), keyframe[m].key_positions, keyframe[m].key_times, 0.5f);
-
-		// Display the key positions and lines b/w positions
-		//keyframe.display_key_positions(environment);
-
-		// Compute the interpolated position
-		//  This is this function that you need to complete
-		pos[m] = interpolation(t, keyframe[m].key_positions, keyframe[m].key_times, 0.5f);
-
-		// Display the interpolated position (and its trajectory)
-		//keyframe.display_current_position(p, environment);
-	}
-}
-
-
-void bat::add_bat(vec3 new_pos, float terrain_length) {
-	N++;
-	pos.resize(N);
-	pos2.resize(N);
-	isdead.resize(N);
-	size.resize(N);
-	keyframe.resize(N);
-
-
-	pos[N - 1] = new_pos;
-	isdead[N - 1] = false;
-	size[N - 1] = rand_interval(0.05f, 1.0f);;
-	initialize_mvt(new_pos, N - 1, terrain_length);
+	if (t + 0.1f > timer_mvt.t_max) pos_futur = interpolation(0.01f, keyframe.key_positions, keyframe.key_times, 0.5f);
+	else pos_futur = interpolation((t + 0.1f), keyframe.key_positions, keyframe.key_times, 0.5f);
 
+	// Compute the interpolated position
+	pos = interpolation(t, keyframe.key_positions, keyframe.key_times, 0.5f);
 }
 
diff --git a/projet-code/scenes_inf443/base/src/bat.hpp b/projet-code/scenes_inf443/base/src/bat.hpp
index 5cb0a25..2b83f21 100644
--- a/projet-code/scenes_inf443/base/src/bat.hpp
+++ b/projet-code/scenes_inf443/base/src/bat.hpp
@@ -8,20 +8,17 @@ using namespace cgp;
 // The entire hierarchy
 
 struct bat{
-	cgp::hierarchy_mesh_drawable bat;
+	double size;
+	bool isdead;
+	vec3 pos;
+	vec3 pos_futur;
 
-	int N;
-	std::vector<double> size;
-	std::vector<bool> isdead;
-	std::vector<vec3> pos;
-	std::vector<vec3> pos2;
 	// Timer used for the interpolation of the position
 	cgp::timer_interval timer_mvt;
+
 	// A helper structure used to store and display the key positions/time
-	std::vector<keyframe_structure> keyframe;
+	keyframe_structure keyframe;
 
-	void initialize_bat();
-	void add_bat(vec3 new_pos, float terrain_length);
-	void initialize_mvt(vec3 p, int i, float terrain_length);
-	void display_mvt();
+	void initialize_mvt(vec3 p, numarray<vec3> key_positions, numarray<float> key_times);
+	void update_mvt();
 };
\ No newline at end of file
diff --git a/projet-code/scenes_inf443/base/src/bats.cpp b/projet-code/scenes_inf443/base/src/bats.cpp
new file mode 100644
index 0000000..55b5d43
--- /dev/null
+++ b/projet-code/scenes_inf443/base/src/bats.cpp
@@ -0,0 +1,61 @@
+#include "bats.hpp"
+#include "environment.hpp"
+#include "key_positions_structure.hpp"
+#include "interpolation.hpp"
+#include "terrain.hpp"
+
+void bats::initialize_bats()
+{
+	// Initialize the temporary mesh_drawable that will be inserted in the hierarchy
+	mesh_drawable body;
+	mesh_drawable wing1;
+	mesh_drawable wing2;
+
+	// Create the geometry of the meshes
+	//   Note: this geometry must be set in their local coordinates with respect to their position in the hierarchy (and with respect to their animation)
+	body.initialize_data_on_gpu(mesh_load_file_obj(project::path + "assets/batbodyok.obj"));
+	wing1.initialize_data_on_gpu(mesh_load_file_obj(project::path + "assets/batwingleft.obj"));
+	wing2.initialize_data_on_gpu(mesh_load_file_obj(project::path + "assets/batwingright.obj"));
+
+	// Scale the model
+	//body.model.scaling = 0.2f;
+	//wing1.model.scaling = 0.2f;
+	//wing2.model.scaling = 0.2f;
+
+	// Set the color of some elements
+	body.material.color = { 0.3f,0.3f,0.3f };
+	wing1.material.color = { 0.2f,0.2f,0.2f };
+	wing2.material.color = { 0.2f,0.2f,0.2f };
+
+	// Add the elements in the hierarchy
+	//   The syntax is hierarchy.add(mesh_drawable, "name of the parent element", [optional: local translation in the hierarchy])
+	//   Notes: 
+	//     - An element must necessarily be added after its parent
+	//     - The first element (without explicit name of its parent) is assumed to be the root.
+
+	bat_mesh.add(body, "Bat base");
+	bat_mesh.add(wing1, "Bat wing left1", "Bat base");
+	bat_mesh.add(wing2, "Bat wing right1", "Bat base");
+
+	N = 0;
+}
+
+void bats::update_mvt()
+{
+	for (int i = 0; i < N; i++) {
+		bats_prop[i].update_mvt();
+	}
+}
+
+
+void bats::add_bat(vec3 new_pos, float _size, numarray<vec3> key_positions, numarray<float> key_times) {
+	N++;
+	bats_prop.resize(N);
+
+	bats_prop[N - 1].pos = new_pos;
+	bats_prop[N - 1].isdead = false;
+	bats_prop[N - 1].size = _size;
+	bats_prop[N - 1].initialize_mvt(new_pos, key_positions, key_times);
+
+}
+
diff --git a/projet-code/scenes_inf443/base/src/bats.hpp b/projet-code/scenes_inf443/base/src/bats.hpp
new file mode 100644
index 0000000..0b3f147
--- /dev/null
+++ b/projet-code/scenes_inf443/base/src/bats.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "cgp/cgp.hpp"
+#include "key_positions_structure.hpp"
+#include "bat.hpp"
+
+using namespace cgp;
+
+// The entire hierarchy
+
+struct bats{
+	cgp::hierarchy_mesh_drawable bat_mesh;
+
+	int N;
+
+	std::vector<bat> bats_prop;
+	
+	void initialize_bats();
+	void add_bat(vec3 new_pos, float _size, numarray<vec3> key_positions, numarray<float> key_times);
+	void update_mvt();
+};
\ No newline at end of file
diff --git a/projet-code/scenes_inf443/base/src/projectile.cpp b/projet-code/scenes_inf443/base/src/projectile.cpp
index cdb6ced..58c7c00 100644
--- a/projet-code/scenes_inf443/base/src/projectile.cpp
+++ b/projet-code/scenes_inf443/base/src/projectile.cpp
@@ -1,67 +1,22 @@
 #include "projectile.hpp"
 #include "terrain.hpp"
+#include "settings.hpp"
 
-void projectile::initialize()
-{
 
-	N = 0;
-	pos.resize(N);
-	v.resize(N);
-	color.resize(N);
-	elemental_types.resize(N);
 
-	mesh.initialize_data_on_gpu(mesh_primitive_sphere(0.1f));
-
-	
-}
-
-void projectile::reset() {
-	N = 0;
-	pos.resize(N);
-	v.resize(N);
-	color.resize(N);
-}
-
-void projectile::add_ball(vec3 new_pos, vec3 new_dir) {
-	N++;
-	pos.resize(N);
-	v.resize(N);
-	color.resize(N);
-	elemental_types.resize(N);
-
-	
-	pos[N-1] = new_pos;
-	v[N-1] = new_dir;
-	elemental_types[N - 1] = types[N%5];
-	if (elemental_types[N - 1] == projectile_type::fire) {
-		color[N - 1] = {0.886, 0.345, 0.133};
-	}else if (elemental_types[N - 1] == projectile_type::ice) {
-		color[N - 1] = {1,1,1};
-	}else if (elemental_types[N - 1] == projectile_type::rock) {
-		color[N - 1] = {0.3,0.22,0.2};
-	}else if (elemental_types[N - 1] == projectile_type::electric) {
-		color[N - 1] = {1, 1, 0.2 };
-	}else if (elemental_types[N - 1] == projectile_type::water) {
-		color[N - 1] = {0, 0, 1 };
+void projectile::simulateParabolic(float dt) {
+	if (pos[2] < -1 || cgp::abs(pos[0]) > terrain_length() / 2 || cgp::abs(pos[1]) > terrain_length() / 2) {
+		pos = { 0,0, evaluate_terrain_height(0,0) };
+		v = { 3 * rand_interval(), 3 * rand_interval(), 4};
+	}
+	else {
+		pos += v * dt;
+		v[2] -= 10 * dt;
 	}
 
-}
-
-void projectile::simulate(float dt, float terrain_length) {
-	for (int i = 0; i < N; i++) {
-		if (pos[i][2] < -1 || cgp::abs(pos[i][0]) > terrain_length / 2 || cgp::abs(pos[i][1]) > terrain_length / 2) {
-			pos[i] = { 0,0, evaluate_terrain_height(0,0, terrain_length) };
-			v[i] = { 3 * rand_interval(), 3 * rand_interval(), 4 + i };
-		}
-		else {
-			pos[i] += v[i] * dt;
-			v[i][2] -= 10 * dt;
-		}
-
-		if (pos[i][2] < evaluate_terrain_height(pos[i][0], pos[i][1], terrain_length)) {
-			pos[i] = { 0, 0, -1};
-			v[i] = { 0,0,0 };
-		}
+	if (pos[2] < evaluate_terrain_height(pos[0], pos[1])) {
+		pos = { 0, 0, -1};
+		v = { 0,0,0 };
 	}
 }
 
diff --git a/projet-code/scenes_inf443/base/src/projectile.hpp b/projet-code/scenes_inf443/base/src/projectile.hpp
index dea718e..ad67623 100644
--- a/projet-code/scenes_inf443/base/src/projectile.hpp
+++ b/projet-code/scenes_inf443/base/src/projectile.hpp
@@ -5,22 +5,16 @@
 using namespace cgp;
 
 struct projectile {
-	int N;
-
-	std::vector<vec3> v;
-	std::vector<vec3> pos;
-	std::vector<vec3> color;
-	
-
-	mesh_drawable mesh;
-
-	enum class projectile_type {fire, ice, electric, rock, water};
-	std::vector<projectile_type> elemental_types;
-
-	std::vector<projectile_type> types = { projectile_type::fire, projectile_type::ice, projectile_type::rock, projectile_type::electric, projectile_type::water };
-
-	void initialize();
-	void simulate(float dt, float terrain_length);
-	void add_ball(vec3 new_pos, vec3 new_dir);
-	void reset();
+	vec3 v;
+	vec3 pos;
+	vec3 color;
+	float size;
+
+	//projectile types, in global so projectiles also can access it
+	enum class projectile_type { fire, ice, electric, rock, water };
+	//for ease of use
+	std::vector<projectile_type> el_types = { projectile_type::fire, projectile_type::ice, projectile_type::rock, projectile_type::electric, projectile_type::water };
+	projectile_type elemental_type;
+
+	void simulateParabolic(float dt);
 };
diff --git a/projet-code/scenes_inf443/base/src/projectiles.cpp b/projet-code/scenes_inf443/base/src/projectiles.cpp
new file mode 100644
index 0000000..84c2b82
--- /dev/null
+++ b/projet-code/scenes_inf443/base/src/projectiles.cpp
@@ -0,0 +1,43 @@
+#include "projectiles.hpp"
+#include "terrain.hpp"
+
+void projectiles::initialize()
+{
+	N = 0;
+	projectiles_prop.resize(N);
+
+	mesh.initialize_data_on_gpu(mesh_primitive_sphere(0.1f));
+}
+
+void projectiles::reset() {
+	N = 0;
+	projectiles_prop.resize(N);
+}
+
+void projectiles::add_ball(vec3 new_pos, vec3 new_dir) {
+	N++;
+	projectiles_prop.resize(N);
+	
+	projectiles_prop[N - 1].pos = new_pos;
+	projectiles_prop[N - 1].v = new_dir;
+	projectiles_prop[N - 1].elemental_type = el_types[N%5];
+	if (projectiles_prop[N - 1].elemental_type == projectile::projectile_type::fire) {
+		projectiles_prop[N - 1].color = {0.886, 0.345, 0.133};
+	}else if (projectiles_prop[N - 1].elemental_type == projectile::projectile_type::ice) {
+		projectiles_prop[N - 1].color = {1,1,1};
+	}else if (projectiles_prop[N - 1].elemental_type == projectile::projectile_type::rock) {
+		projectiles_prop[N - 1].color = {0.3,0.22,0.2};
+	}else if (projectiles_prop[N - 1].elemental_type == projectile::projectile_type::electric) {
+		projectiles_prop[N - 1].color = {1, 1, 0.2 };
+	}else if (projectiles_prop[N - 1].elemental_type == projectile::projectile_type::water) {
+		projectiles_prop[N - 1].color = {0, 0, 1 };
+	}
+
+}
+
+void projectiles::simulate(float dt) {
+	for (int i = 0; i < N; i++) {
+		projectiles_prop[i].simulateParabolic(dt);
+	}
+}
+
diff --git a/projet-code/scenes_inf443/base/src/projectiles.hpp b/projet-code/scenes_inf443/base/src/projectiles.hpp
new file mode 100644
index 0000000..10bb78e
--- /dev/null
+++ b/projet-code/scenes_inf443/base/src/projectiles.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "cgp/cgp.hpp"
+#include "projectile.hpp"
+
+using namespace cgp;
+
+
+struct projectiles {
+	int N;
+
+	std::vector<projectile> projectiles_prop;
+
+	std::vector<projectile::projectile_type> el_types = { projectile::projectile_type::fire, projectile::projectile_type::ice, projectile::projectile_type::rock, projectile::projectile_type::electric, projectile::projectile_type::water };
+
+	mesh_drawable mesh;
+	
+	void initialize();
+	void simulate(float dt);
+	void add_ball(vec3 new_pos, vec3 new_dir);
+	void reset();
+};
diff --git a/projet-code/scenes_inf443/base/src/scene.cpp b/projet-code/scenes_inf443/base/src/scene.cpp
index a8a94b6..42b330b 100644
--- a/projet-code/scenes_inf443/base/src/scene.cpp
+++ b/projet-code/scenes_inf443/base/src/scene.cpp
@@ -8,17 +8,16 @@
 #include "terrain.hpp"
 #include "projectile.hpp"
 #include "sapin.hpp"
+#include "settings.hpp"
 
 using namespace cgp;
-int num_trees = 200;
-int num_grass = 200;
+
 std::vector<vec3> tree_position;
 std::vector<vec3> grass_position;
-float terrain_length = 250;
 
 void scene_structure::initialize()
 {
-	
+	//CAMERA
 	camera_control.initialize(inputs, window); // Give access to the inputs and window global state to the camera controler
 
 	//for orbit camera
@@ -26,11 +25,13 @@ void scene_structure::initialize()
 	//camera_control.look_at({ 20.0f,15.0f,15.0f }, {0,0,0});
 	
 	//for first person camera
-	camera_control.camera_model.position_camera = { 0,0,evaluate_terrain_height(0,0,terrain_length)+10};
+	camera_control.camera_model.position_camera = { 0,0,evaluate_terrain_height(0,0)+10};
 	camera_control.camera_model.set_rotation_axis({ 0,0,1 });
 	//custum function we added to ..first_person_euler
 	global_frame.initialize_data_on_gpu(mesh_primitive_frame());
 
+
+	//SKYBOX
 	//skybox_debug.png for debugging
 	image_structure image_skybox_template = image_load_file("assets/skybox2.jpg");
 	std::vector<image_structure> image_grid = image_split_grid(image_skybox_template, 4, 3);
@@ -45,8 +46,10 @@ void scene_structure::initialize()
 
 
 
+
+	//TERRAIN
 	int N_terrain_samples = 500;
-	mesh const terrain_mesh = create_terrain_mesh(N_terrain_samples, terrain_length);
+	mesh const terrain_mesh = create_terrain_mesh(N_terrain_samples);
 	terrain.initialize_data_on_gpu(terrain_mesh);
 	// terrain.material.color = { 0.6f,0.85f,0.5f }; terrain de couleur de base verte
 	terrain.material.color = { 1,1,1 };
@@ -60,6 +63,8 @@ void scene_structure::initialize()
 		GL_REPEAT,
 		GL_MIRRORED_REPEAT);
 
+
+	//OBJECTS
 	int r = 1;
 	int h = 5;
 	mesh cyl_mesh = create_cylinder_mesh(r, h);
@@ -81,12 +86,12 @@ void scene_structure::initialize()
 
 	float x = 1.0;
 	float y = 2.0;
-	tree.model.translation = { x, y, evaluate_terrain_height(x,y, terrain_length) };
+	tree.model.translation = { x, y, evaluate_terrain_height(x,y) };
 
-	tree_position = generate_positions_on_terrain(num_trees, terrain_length-1);
+	tree_position = generate_positions_on_terrain(num_trees());
 
 
-	grass_position = generate_positions_on_terrain(num_grass, terrain_length-1);
+	grass_position = generate_positions_on_terrain(num_grass());
 	mesh quadrangle_mesh;
 	quadrangle_mesh.position = { {0,0,0},{1, 0, 0}, {1,0,1},  {0, 0,1} };
 	quadrangle_mesh.uv = { {0,0},{1,0}, {1,1}, {0,1} };
@@ -98,49 +103,27 @@ void scene_structure::initialize()
 		GL_CLAMP_TO_BORDER,
 		GL_CLAMP_TO_BORDER);
 
-	bird1.initialize_bird();
-	//initialize_mvt();
 	chain1.initialize();
 	bouncing.initialize(10); //10 balls
-	bat1.initialize_bat();
-	bat1.add_bat({0,0,0}, terrain_length);
-	projectiles.initialize();
-	sapin1.initialize_sapin();
-	sapin1.sapin["Trunk"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, Pi / 2);
-}
-
-/*
-void scene_structure::initialize_mvt()
-{
-	// Definition of the initial data
-	//--------------------------------------//
-
-	// Key 3D positions
-	numarray<vec3> key_positions =
-	{ {-1,1,0}, {0,1,0}, {1,1,0}, {1,2,0}, {2,2,0}, {2,2,1}, {2,0,1.5}, {1.5,-1,1}, {1.5,-1,0}, {1,-1,0}, {0,-0.5,0}, {-1,1,0} };
 
-	float h = 20+evaluate_terrain_height(0,0,terrain_length);
-	for (int i = 0; i < key_positions.size(); i++) key_positions[i][2] += h;
+	bats.initialize_bats();
 
-	// Key times (time at which the position must pass in the corresponding position)
-	numarray<float> key_times =
-	{ 0.0f, 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 3.75f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f };
-
-	// Initialize the helping structure to display/interact with these positions
-	keyframe.initialize(key_positions, key_times);
-
-
-	// Set timer bounds
-	// The timer must span a time interval on which the interpolation can be conducted
-	// By default, set the minimal time to be key_times[1], and the maximal time to be key_time[N-2] (enables cubic interpolation)
-	int N = key_times.size();
-	timer_mvt.t_min = key_times[0];
-	timer_mvt.t_max = key_times[N - 1];
-	timer_mvt.t = timer_mvt.t_min;
+	vec3 bat_pos1 = { 0,0,evaluate_terrain_height(0,0) + 20 };
+	float bat_size1 = 0.2f;
+	numarray<vec3> bat_keypos1 = { {-1,1,0}, {0,1,0}, {1,1,0}, {1,2,0}, {2,2,0}, {2,2,1}, {2,0,1.5}, {1.5,-1,1}, {1.5,-1,0}, {1,-1,0}, {0,-0.5,0}, {-1,1,0} };
+	numarray<float> bat_keytimes1 = { 0.0f, 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 3.75f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f };
+	bats.add_bat(bat_pos1, bat_size1, bat_keypos1, bat_keytimes1);
+	
+	vec3 bat_pos2 = { 5,5,evaluate_terrain_height(0,0) + 10 };
+	float bat_size2 = 0.3f;
+	numarray<vec3> bat_keypos2 = { {-1,1,0}, {0,1,0}, {1,1,0}, {1,2,0}, {2,2,0}, {2,2,1}, {2,0,1.5}, {1.5,-1,1}, {1.5,-1,0}, {1,-1,0}, {0,-0.5,0}, {-1,1,0} };
+	numarray<float> bat_keytimes2 = { 0.0f, 1.0f, 2.0f, 2.5f, 3.0f, 3.5f, 3.75f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f };
+	bats.add_bat(bat_pos2, bat_size2, bat_keypos2, bat_keytimes2);
 
+	projectiles.initialize();
+	sapin1.initialize_sapin();
+	sapin1.sapin["Trunk"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, Pi / 2);
 }
-*/
-
 
 void scene_structure::display_frame()
 {
@@ -155,7 +138,7 @@ void scene_structure::display_frame()
 	//Walking on ground
 	if (!gui.fly) {
 		vec3 eye_level = camera_control.camera_model.position_camera;
-		eye_level[2] = evaluate_terrain_height(eye_level[0], eye_level[1], terrain_length) + 0.75;
+		eye_level[2] = evaluate_terrain_height(eye_level[0], eye_level[1]) + 0.75;
 		camera_control.camera_model.position_camera = eye_level;
 	}
 
@@ -169,7 +152,7 @@ void scene_structure::display_frame()
 	if (gui.display_wireframe)
 		draw_wireframe(terrain, environment);
 
-	for (int i = 0; i < num_trees; i++) {
+	for (int i = 0; i < num_trees(); i++) {
 		//tree.model.translation = tree_position[i];
 		//draw(tree, environment);
 		sapin1.sapin["Trunk"].transform_local.translation = tree_position[i];
@@ -180,7 +163,7 @@ void scene_structure::display_frame()
 	//display_bird(p);
 	//display_chain(p);
 	display_ball();
-	display_bat();
+	display_bats();
 	display_projectiles();
 
 
@@ -191,71 +174,30 @@ void scene_structure::display_frame()
 
 }
 
-/*
-void scene_structure::display_bird(vec3 p)
-{
-	// Apply transformation to some elements of the hierarchy
-	bird1.bird["Bird head"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0 }, 0.3 * cos(timer.t));
-	bird1.bird["Bird wing left1"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, 0.5 * cos(5 * timer.t));
-	bird1.bird["Bird wing left2"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, 0.7 * cos(5 * timer.t));
-	bird1.bird["Bird wing right1"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, -0.5 * cos(5 * timer.t));
-	bird1.bird["Bird wing right2"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, -0.7 * cos(5 * timer.t));
-
-
-	// This function must be called before the drawing in order to propagate the deformations through the hierarchy
-	bird1.bird.update_local_to_global_coordinates();
-	
-	//Orientation and position of the bird along the path
-	float t = timer_mvt.t;
-	vec3 p2;
-	if(t+0.1f > timer_mvt.t_max) p2 = interpolation(0.01f, keyframe.key_positions, keyframe.key_times, gui.k);
-	else p2 = interpolation((t + 0.1f), keyframe.key_positions, keyframe.key_times, gui.k);
-	bird1.bird["Bird base"].transform_local.rotation = rotation_transform::from_vector_transform({1,0,0}, normalize(p2 - p));
-	bird1.bird["Bird base"].transform_local.translation = p;
-
-	/* Exemple TD5
-	hierarchy["Cylinder1"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,0,1 }, timer.t);
-	hierarchy["Cube1"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, -3 * timer.t);
-	hierarchy["Cyl2"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,0,1 }, 6 * timer.t);
-	hierarchy["Cyl3"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,0,1 }, 6 * timer.t);
-	hierarchy["Cube base"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0 }, 0.8 * cos(3 * timer.t));
-
-	hierarchy.update_local_to_global_coordinates();
-	
-
-	draw(bird1.bird, environment);
-	if (gui.display_wireframe) {
-		//draw_wireframe(hierarchy, environment);
-		draw_wireframe(bird1.bird, environment);
-	}
-
-
-}
-*/
-
-void scene_structure::display_bat()
+void scene_structure::display_bats()
 {
-	// Apply transformation to some elements of the hierarchy
-	bat1.bat["Bat wing left1"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0 }, 0.5 * cos(5 * timer.t));
-	bat1.bat["Bat wing right1"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0 }, -0.5 * cos(5 * timer.t));
-
+	bats.update_mvt();
 
-	// This function must be called before the drawing in order to propagate the deformations through the hierarchy
-	bat1.bat.update_local_to_global_coordinates();
-
-	bat1.display_mvt();
-	for (int m = 0; m < bat1.N; m++) {
+	for (int i = 0; i < bats.N; i++) {
+		//Wing animation
+		bats.bat_mesh["Bat wing left1"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0 }, 0.5 * cos(5 * bats.bats_prop[i].timer_mvt.t));
+		bats.bat_mesh["Bat wing right1"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0 }, -0.5 * cos(5 * bats.bats_prop[i].timer_mvt.t));
 		//Rescale
-		bat1.bat["Bat base"].drawable.model.scaling = bat1.size[m];
-		bat1.bat["Bat wing left1"].drawable.model.scaling = bat1.size[m];
-		bat1.bat["Bat wing right1"].drawable.model.scaling = bat1.size[m];
+		bats.bat_mesh["Bat base"].drawable.model.scaling = bats.bats_prop[i].size;
+		bats.bat_mesh["Bat wing left1"].drawable.model.scaling = bats.bats_prop[i].size;
+		bats.bat_mesh["Bat wing right1"].drawable.model.scaling = bats.bats_prop[i].size;
+		//Make sure wings are at the right distance
+		bats.bat_mesh["Bat wing left1"].transform_local.translation = { -0.25f * bats.bats_prop[i].size, 0, 0 };
+		bats.bat_mesh["Bat wing right1"].transform_local.translation = { 0.25f * bats.bats_prop[i].size, 0, 0 };
+
 		//Orientation and position of the bat along the path
-		bat1.bat["Bat base"].transform_local.rotation = rotation_transform::from_vector_transform({ 0,-1,0 }, normalize(bat1.pos2[m] - bat1.pos[m]));
-		bat1.bat["Bat base"].transform_local.translation = bat1.pos[m];
+		bats.bat_mesh["Bat base"].transform_local.rotation = rotation_transform::from_vector_transform({ 0,-1,0 }, normalize(bats.bats_prop[i].pos_futur - bats.bats_prop[i].pos));
+		bats.bat_mesh["Bat base"].transform_local.translation = bats.bats_prop[i].pos;
 
-		if (!bat1.isdead[m])	draw(bat1.bat, environment);
+		bats.bat_mesh.update_local_to_global_coordinates();
+		if (!bats.bats_prop[i].isdead)	draw(bats.bat_mesh, environment);
 		if (gui.display_wireframe) {
-			draw_wireframe(bat1.bat, environment);
+			draw_wireframe(bats.bat_mesh, environment);
 		}
 	}
 }
@@ -280,7 +222,7 @@ void scene_structure::display_semiTransparent()
 	vec3 const right = camera.right();
 	// Rotation such that the grass follows the right-vector of the camera, while pointing toward the z-direction
 	
-	for (int i = 0; i < num_grass; i++) {
+	for (int i = 0; i < num_grass(); i++) {
 		grass.model.translation = grass_position[i];
 		rotation_transform R = rotation_transform::from_frame_transform({ 1,0,0 }, { 0,0,1 }, right, { 0,0,1 });
 		grass.model.rotation = R;
@@ -292,33 +234,6 @@ void scene_structure::display_semiTransparent()
 	glDisable(GL_BLEND);
 }
 
-
-
-
-/*
-vec3 scene_structure::display_mvt()
-{
-
-	// Update the current time
-	timer_mvt.update();
-	float t = timer_mvt.t;
-
-	// clear trajectory when the timer restart
-	if (t < timer_mvt.t_min + 0.1f)
-		keyframe.trajectory.clear();
-
-	// Display the key positions and lines b/w positions
-	keyframe.display_key_positions(environment);
-
-	// Compute the interpolated position
-	//  This is this function that you need to complete
-	return interpolation(t, keyframe.key_positions, keyframe.key_times, gui.k);
-
-	// Display the interpolated position (and its trajectory)
-	//keyframe.display_current_position(p, environment);
-}
-*/
-
 void scene_structure::draw_segment(vec3 const& a, vec3 const& b)
 {
 	chain1.segment.vbo_position.update(numarray<vec3>{ a, b });
@@ -363,7 +278,7 @@ void scene_structure::display_gui()
 
 void scene_structure::display_ball() {
 
-	bouncing.simulate(timer.scale * 0.01f, terrain_length);
+	bouncing.simulate(timer.scale * 0.01f);
 	for (int i = 0; i < bouncing.N; i++) {	
 		bouncing.mesh.model.translation = bouncing.pos[i];
 		bouncing.mesh.material.color = bouncing.color[i];
@@ -373,10 +288,10 @@ void scene_structure::display_ball() {
 
 void scene_structure::display_projectiles() {
 
-	projectiles.simulate(timer.scale * 0.03f, terrain_length);
+	projectiles.simulate(timer.scale * 0.03f);
 	for (int i = 0; i < projectiles.N; i++) {
-		projectiles.mesh.model.translation = projectiles.pos[i];
-		projectiles.mesh.material.color = projectiles.color[i];
+		projectiles.mesh.model.translation = projectiles.projectiles_prop[i].pos;
+		projectiles.mesh.material.color = projectiles.projectiles_prop[i].color;
 		draw(projectiles.mesh, environment);
 	}
 }
diff --git a/projet-code/scenes_inf443/base/src/scene.hpp b/projet-code/scenes_inf443/base/src/scene.hpp
index 3e65910..a92f825 100644
--- a/projet-code/scenes_inf443/base/src/scene.hpp
+++ b/projet-code/scenes_inf443/base/src/scene.hpp
@@ -7,8 +7,8 @@
 #include "ball.hpp"
 #include "bird.hpp"
 #include "chain.hpp"
-#include "bat.hpp"
-#include "projectile.hpp"
+#include "bats.hpp"
+#include "projectiles.hpp"
 #include "sapin.hpp"
 
 
@@ -58,11 +58,6 @@ struct scene_structure : cgp::scene_inputs_generic {
 	cgp::mesh_drawable cone;
 	cgp::mesh_drawable tree;
 	cgp::mesh_drawable grass;
-	
-
-
-
-
 
 	// Timer used for the animation
 	timer_basic timer_chain;
@@ -70,8 +65,8 @@ struct scene_structure : cgp::scene_inputs_generic {
 	ball bouncing;
 	bird bird1;
 	chain chain1;
-	bat bat1;
-	projectile projectiles;
+	bats bats;
+	projectiles projectiles;
 	sapin sapin1;
 
 	// ****************************** //
@@ -82,12 +77,9 @@ struct scene_structure : cgp::scene_inputs_generic {
 	void display_frame(); // The frame display to be called within the animation loop
 	void display_gui();   // The display of the GUI, also called within the animation loop
 	void display_semiTransparent();
-	void display_chain(vec3 bird_pos);
-	void display_bird(vec3 p);
-	void display_bat();
-
-	void initialize_mvt();
-	vec3 display_mvt();
+	void display_chain(vec3 end_pos);
+	//void display_bird(vec3 p);
+	void display_bats();
 
 	void mouse_move_event();
 	void mouse_click_event();
diff --git a/projet-code/scenes_inf443/base/src/terrain.cpp b/projet-code/scenes_inf443/base/src/terrain.cpp
index 13f56bf..739a9ab 100644
--- a/projet-code/scenes_inf443/base/src/terrain.cpp
+++ b/projet-code/scenes_inf443/base/src/terrain.cpp
@@ -1,12 +1,11 @@
-
 #include "terrain.hpp"
-
+#include "settings.hpp"
 
 using namespace cgp;
 
 
 // Evaluate 3D position of the terrain for any (x,y)
-float evaluate_terrain_height(float x, float y, float terrain_length)
+float evaluate_terrain_height(float x, float y)
 {
     //p, h, sigma -> positions, heights and wideness of bell curves
     vec2 p[] = { {-10, -10}, {5, 5}, {-3, 4}, {6, 4} };
@@ -24,15 +23,14 @@ float evaluate_terrain_height(float x, float y, float terrain_length)
     parameters.frequency_gain = 2.4;
     parameters.persistency = 0.33;
     
-
-    float perlin_noise = parameters.terrain_height * noise_perlin(vec2(3*x / terrain_length, 3*y / terrain_length), parameters.octave, parameters.persistency, parameters.frequency_gain);
+    float perlin_noise = parameters.terrain_height * noise_perlin(vec2(3*x / terrain_length(), 3 * y / terrain_length()), parameters.octave, parameters.persistency, parameters.frequency_gain);
 
 
     return perlin_noise;
 }
 
 
-mesh create_terrain_mesh(int N, float terrain_length)
+mesh create_terrain_mesh(int N)
 {
 
     mesh terrain; // temporary terrain storage (CPU only)
@@ -58,18 +56,18 @@ mesh create_terrain_mesh(int N, float terrain_length)
             float v = kv/(N-1.0f);
 
             // Compute the real coordinates (x,y) of the terrain in [-terrain_length/2, +terrain_length/2]
-            float x = (u - 0.5f) * terrain_length;
-            float y = (v - 0.5f) * terrain_length;
+            float x = (u - 0.5f) * terrain_length();
+            float y = (v - 0.5f) * terrain_length();
 
             // Compute the surface height function at the given sampled coordinate
-            float z = evaluate_terrain_height(x,y, terrain_length);
+            float z = evaluate_terrain_height(x,y);
 
             // Store vertex coordinates
             terrain.position[kv+N*ku] = {x,y,z};
             terrain.uv[kv+N*ku] = {x,y};
 
             //blending parameter for color
-            perlin_noise = parameters.terrain_height * noise_perlin(vec2(3 * x / terrain_length, 3 * y / terrain_length), parameters.octave, parameters.persistency, parameters.frequency_gain);
+            perlin_noise = parameters.terrain_height * noise_perlin(vec2(3 * x / terrain_length(), 3 * y / terrain_length()), parameters.octave, parameters.persistency, parameters.frequency_gain);
             float b = std::min(1.0, exp((z + perlin_noise - 20) / 2) / exp(6));
             terrain.color[kv + N * ku] = std::max(0.0f,(1-b))*vec3(0,0.3f,0) + b * 1.5 * vec3(1, 1, 1);
             
@@ -98,14 +96,14 @@ mesh create_terrain_mesh(int N, float terrain_length)
     return terrain;
 }
 
-std::vector<cgp::vec3> generate_positions_on_terrain(int N, float terrain_length) {
+std::vector<cgp::vec3> generate_positions_on_terrain(int N) {
     std::vector<vec3> rand_pos;
     float x, y;
-    float d = terrain_length / 2.0f;
+    float d = terrain_length() / 2.0f;
     for (int i = 0; i < N; i++) {
         x = rand_interval(-d, d);
         y = rand_interval(-d, d);
-        rand_pos.push_back({ x,y, evaluate_terrain_height(x, y, terrain_length) });
+        rand_pos.push_back({ x,y, evaluate_terrain_height(x, y) });
     }
 
     return rand_pos;
diff --git a/projet-code/scenes_inf443/base/src/terrain.hpp b/projet-code/scenes_inf443/base/src/terrain.hpp
index 96f8be2..9ced8dc 100644
--- a/projet-code/scenes_inf443/base/src/terrain.hpp
+++ b/projet-code/scenes_inf443/base/src/terrain.hpp
@@ -10,13 +10,13 @@ struct perlin_noise_parameters
 	float terrain_height = 0.5f;
 };
 
-float evaluate_terrain_height(float x, float y, float terrain_length);
+float evaluate_terrain_height(float x, float y);
 
 /** Compute a terrain mesh 
 	The (x,y) coordinates of the terrain are set in [-length/2, length/2].
 	The z coordinates of the vertices are computed using evaluate_terrain_height(x,y).
 	The vertices are sampled along a regular grid structure in (x,y) directions. 
 	The total number of vertices is N*N (N along each direction x/y) 	*/
-cgp::mesh create_terrain_mesh(int N, float length);
+cgp::mesh create_terrain_mesh(int N);
 
-std::vector<cgp::vec3> generate_positions_on_terrain(int N, float terrain_length);
\ No newline at end of file
+std::vector<cgp::vec3> generate_positions_on_terrain(int N);
\ No newline at end of file
-- 
GitLab