Newer
Older
#include "scene.hpp"
#include "tree.hpp"
#include "interpolation.hpp"
#include "ball.hpp"
#include "bird.hpp"
std::vector<vec3> tree_position;
std::vector<vec3> grass_position;
camera_control.initialize(inputs, window); // Give access to the inputs and window global state to the camera controler
//camera_control.set_rotation_axis_z();
//camera_control.look_at({ 20.0f,15.0f,15.0f }, {0,0,0});
camera_control.camera_model.position_camera = { 0,0,evaluate_terrain_height(0,0)+10};
//camera_control.camera_model.position_camera = { 0,-5,0};
camera_control.camera_model.set_rotation_axis({ 0,0,1 });
global_frame.initialize_data_on_gpu(mesh_primitive_frame());
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);
image_structure image_skybox_template2 = image_load_file("assets/skyboxNight.jpeg");
std::vector<image_structure> image_grid2 = image_split_grid(image_skybox_template2, 4, 3);
skybox.initialize_data_on_gpu();
//x neg, x pos, y neg, y pos, z neg, z pos
skybox.texture.initialize_cubemap_on_gpu(image_grid[7].rotate_90_degrees_counterclockwise(), image_grid[1].rotate_90_degrees_clockwise(), image_grid[4].rotate_90_degrees_clockwise().rotate_90_degrees_clockwise(), image_grid[10], image_grid[3], image_grid[5].rotate_90_degrees_clockwise().rotate_90_degrees_clockwise());
skybox.texture2.initialize_cubemap_on_gpu(image_grid2[7].rotate_90_degrees_counterclockwise(), image_grid2[1].rotate_90_degrees_clockwise(), image_grid2[4].rotate_90_degrees_clockwise().rotate_90_degrees_clockwise(), image_grid2[10], image_grid2[3], image_grid2[5].rotate_90_degrees_clockwise().rotate_90_degrees_clockwise());
mesh const terrain_mesh = create_terrain_mesh(N_terrain_samples);
// terrain.material.color = { 0.6f,0.85f,0.5f }; terrain de couleur de base verte
terrain.material.color = { 1,1,1 };
terrain.material.phong.specular = 0.0f; // non-specular terrain material
terrain.shader.load(project::path + "shaders/mesh_multi_texture/mesh_multi_texture.vert.glsl", project::path + "shaders/mesh_multi_texture/mesh_multi_texture.frag.glsl");
terrain.texture.load_and_initialize_texture_2d_on_gpu(project::path + "assets/grass.jpg",
terrain.supplementary_texture["image_texture_rock"].load_and_initialize_texture_2d_on_gpu(project::path + "assets/rocks3.jpg",
GL_REPEAT,
GL_MIRRORED_REPEAT);
terrain.supplementary_texture["image_texture_snow"].load_and_initialize_texture_2d_on_gpu(project::path + "assets/snow.jpg",
int r = 1;
int h = 5;
mesh cyl_mesh = create_cylinder_mesh(r, h);
cyl.initialize_data_on_gpu(cyl_mesh);
cyl.material.color = { 0.58f,0.294f,0.0f };
cyl.material.phong.specular = 0.0f;
r = 3;
h = 2;
int z = 3;
mesh cone_mesh = create_cone_mesh(r, h, z);
cone.initialize_data_on_gpu(cone_mesh);
cone.material.color = { 0.0f,0.8f,0.0f };
cone.material.phong.specular = 0.0f;
mesh tree_mesh = create_tree();
tree.initialize_data_on_gpu(tree_mesh);
tree.model.translation = { x, y, evaluate_terrain_height(x,y) };
tree_position = generate_positions_on_terrain(num_trees());
grass_position = generate_positions_on_terrain(num_grass());
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} };
quadrangle_mesh.connectivity = { {0,1,2}, {0,2,3} };
quadrangle_mesh.fill_empty_field(); // (fill with some default values the other buffers (colors, normals) that we didn't filled before)
// Convert the mesh structure into a mesh_drawable structure
grass.initialize_data_on_gpu(quadrangle_mesh);
grass.texture.load_and_initialize_texture_2d_on_gpu(project::path + "assets/grass.png",
GL_CLAMP_TO_BORDER,
GL_CLAMP_TO_BORDER);
chain1.initialize();
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 };
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 };
dragons.add_dragon(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);
hitbox_sphere.initialize_data_on_gpu(mesh_primitive_sphere(1));
}
void scene_structure::display_frame()
{
// Update the current time
timer.update();
// Must be called before drawing the other shapes and without writing in the Depth Buffer
glDepthMask(GL_FALSE); // disable depth-buffer writing
glDepthMask(GL_TRUE); // re-activate depth-buffer write
//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]) + 0.75;
camera_control.camera_model.position_camera = eye_level;
}
// Set the light to the current position of the camera
environment.light = camera_control.camera_model.position();
if (gui.display_frame)
draw(global_frame, environment);
draw(terrain, environment);
if (gui.display_wireframe)
draw_wireframe(terrain, environment);
for (int i = 0; i < num_trees(); i++) {
if (norm(tree_position[i]-camera_control.camera_model.position_camera) < 75 ) {
sapin1.sapin["Trunk"].transform_local.translation = tree_position[i];
sapin1.sapin.update_local_to_global_coordinates();
draw(sapin1.sapin, environment);
}
display_semiTransparent(); //Important to draw grass before projectiles (otherwise you see them through projectiles)
if (gui.display_wireframe)
draw_wireframe(tree, environment);
void scene_structure::display_bats()
Marie AUDOUARD
committed
if (!bats.bats_prop[i].isdead) {
//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
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
rotation_transform rot = 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.rotation = rot;
bats.bat_mesh["Bat base"].transform_local.translation = bats.bats_prop[i].pos;
bats.bat_mesh.update_local_to_global_coordinates();
draw(bats.bat_mesh, environment);
if (gui.display_wireframe) {
draw_wireframe(bats.bat_mesh, environment);
}
Marie AUDOUARD
committed
if (gui.display_hitbox) {
display_hitbox(bats.bats_prop[i].bat_hitbox, bats.bats_prop[i].pos, rot);
}
}
}
}
void scene_structure::display_dragons()
{
dragons.update_mvt();
for (int i = 0; i < bats.N; i++) {
Marie AUDOUARD
committed
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
if (!dragons.dragons_prop[i].isdead) {
//Wing animation
dragons.dragon_mesh["Dragon wing left"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0.5 }, 0.5 * cos(5 * dragons.dragons_prop[i].timer_mvt.t));
dragons.dragon_mesh["Dragon wing right"].transform_local.rotation = rotation_transform::from_axis_angle({ 1,0,0.5 }, -0.5 * cos(5 * dragons.dragons_prop[i].timer_mvt.t));
//Mouth animation
dragons.dragon_mesh["Dragon mouth"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0 }, 0.05 * cos(dragons.dragons_prop[i].timer_mvt.t));
//Tail animation
dragons.dragon_mesh["Dragon tailmiddle"].transform_local.rotation = rotation_transform::from_axis_angle({ 0,1,0.5 }, 0.05 * cos(2 * dragons.dragons_prop[i].timer_mvt.t));
dragons.dragon_mesh["Dragon tailend"].transform_local.rotation = rotation_transform::from_axis_angle({ 0.5,1,0.5 }, -0.01 * cos(2 * dragons.dragons_prop[i].timer_mvt.t));
//Rescale
dragons.dragon_mesh["Dragon base"].drawable.model.scaling = dragons.dragons_prop[i].size;
dragons.dragon_mesh["Dragon wing left"].drawable.model.scaling = dragons.dragons_prop[i].size;
dragons.dragon_mesh["Dragon wing right"].drawable.model.scaling = dragons.dragons_prop[i].size;
dragons.dragon_mesh["Dragon mouth"].drawable.model.scaling = dragons.dragons_prop[i].size;
dragons.dragon_mesh["Dragon tailmiddle"].drawable.model.scaling = dragons.dragons_prop[i].size;
dragons.dragon_mesh["Dragon tailend"].drawable.model.scaling = dragons.dragons_prop[i].size;
//Make sure wings are at the right distance
dragons.dragon_mesh["Dragon wing left"].transform_local.translation = { 0, -0.3f * dragons.dragons_prop[i].size, 0 };
dragons.dragon_mesh["Dragon wing right"].transform_local.translation = { 0, 0.3f * dragons.dragons_prop[i].size, 0 };
//Orientation and position of the bat along the path
rotation_transform rot = rotation_transform::from_vector_transform({ 1,0,0 }, normalize(dragons.dragons_prop[i].pos_futur - dragons.dragons_prop[i].pos));
dragons.dragon_mesh["Dragon base"].transform_local.rotation = rot;
dragons.dragon_mesh["Dragon base"].transform_local.translation = dragons.dragons_prop[i].pos;
dragons.dragon_mesh.update_local_to_global_coordinates();
draw(dragons.dragon_mesh, environment);
if (gui.display_wireframe) {
draw_wireframe(dragons.dragon_mesh, environment);
}
Marie AUDOUARD
committed
if (gui.display_hitbox) {
display_hitbox(dragons.dragons_prop[i].dragon_hitbox, dragons.dragons_prop[i].pos, rot);
}
}
}
}
void scene_structure::display_hitbox(hitbox H, vec3 shift, rotation_transform rot) {
for (int i = 0; i < H.N; i++) {
hitbox_sphere.model.scaling = H.r[i];
hitbox_sphere.model.translation = rot * H.center[i] + shift;
draw_wireframe(hitbox_sphere, environment);
void scene_structure::display_semiTransparent()
{
// Enable use of alpha component as color blending for transparent elements
// alpha = current_color.alpha
// new color = previous_color * alpha + current_color * (1-alpha)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Disable depth buffer writing
// - Transparent elements cannot use depth buffer
// - They are supposed to be display from furest to nearest elements
glDepthMask(false);
auto const& camera = camera_control.camera_model;
// Re-orient the grass shape to always face the camera direction
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++) {
rotation_transform R = rotation_transform::from_frame_transform({ 1,0,0 }, { 0,0,1}, right, {0,0,1});
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
grass.model.rotation = R;
draw(grass, environment);
}
// Don't forget to re-activate the depth-buffer write
glDepthMask(true);
glDisable(GL_BLEND);
}
void scene_structure::draw_segment(vec3 const& a, vec3 const& b)
{
chain1.segment.vbo_position.update(numarray<vec3>{ a, b });
draw(chain1.segment, environment);
}
void scene_structure::display_chain(vec3 bird_pos)
{
// Update the current time
timer_chain.update();
chain1.simulation_step(timer_chain.scale * 0.01f, bird_pos);
for (int i = 0; i < chain1.n; i++) {
chain1.particle_sphere.model.translation = chain1.p[i];
chain1.particle_sphere.material.color = { (float)i / chain1.n,(float)i / chain1.n,0 };
draw(chain1.particle_sphere, environment);
}
for (int i = 0; i < chain1.n - 1; i++) {
draw_segment(chain1.p[i], chain1.p[i + 1]);
}
}
void scene_structure::display_gui()
{
ImGui::Checkbox("Frame", &gui.display_frame);
ImGui::Checkbox("Wireframe", &gui.display_wireframe);
ImGui::Checkbox("Hitbox", &gui.display_hitbox);
//ImGui::SliderFloat("Time", &timer_mvt.t, timer_mvt.t_min, timer_mvt.t_max);
//ImGui::SliderFloat("Time scale", &timer_mvt.scale, 0.0f, 2.0f);
ImGui::SliderFloat("Speed", &gui.speed, 0.0f, 10.0f);
// Display the GUI associated to the key position
}
void scene_structure::display_ball() {
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];
draw(bouncing.mesh, environment);
}
}
void scene_structure::display_projectiles() {
vec3 const right = camera_control.camera_model.right();
rotation_transform R = rotation_transform::from_frame_transform({ cos(ball_turn_speed * timer.t + 90),sin(ball_turn_speed * timer.t + 90),0 }, { 0,0,1 }, right, { 0,0,1 });
rotation_transform R2 = rotation_transform::from_frame_transform({ cos(ball_turn_speed * timer.t -90), sin(ball_turn_speed * timer.t - 90),0 }, { 0,0,1 }, right, { 0,0,1 });
projectiles.simulate(timer.scale * 0.03f);
for (int i = 0; i < projectiles.N; i++) {
if (bats.bats_prop[j].bat_hitbox.is_in_hitbox(projectiles.projectiles_prop[i].pos, bats.bats_prop[j].pos)) bats.bats_prop[j].isdead = true;
Marie AUDOUARD
committed
if (dragons.dragons_prop[j].dragon_hitbox.is_in_hitbox(projectiles.projectiles_prop[i].pos, dragons.dragons_prop[j].pos)) dragons.dragons_prop[j].isdead = true;
projectiles.mesh.model.translation = projectiles.projectiles_prop[i].pos;
projectiles.mesh.material.color = projectiles.projectiles_prop[i].color;
draw(projectiles.mesh, environment);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
if (projectiles.projectiles_prop[i].elemental_type == projectile::projectile_type::fire) {
if (fmod(timer.t, ball_reset_speed) > 0.1) projectiles.projectiles_prop[i].change_animation = true;
if (fmod(timer.t, ball_reset_speed) < 0.1 && projectiles.projectiles_prop[i].change_animation) {
projectiles.projectiles_prop[i].change_animation = false;
projectiles.fireball.texture.update(projectiles.fire_grid[std::rand()%12]);
}
projectiles.fireball.model.translation = projectiles.projectiles_prop[i].pos;
draw(projectiles.fireball, environment);
projectiles.fireball.model.rotation = R;
draw(projectiles.fireball, environment);
projectiles.fireball.model.rotation = R2;
draw(projectiles.fireball, environment);
}
else if (projectiles.projectiles_prop[i].elemental_type == projectile::projectile_type::water) {
if (fmod(timer.t, ball_reset_speed) > 0.1) projectiles.projectiles_prop[i].change_animation = true;
if (fmod(timer.t, ball_reset_speed) < 0.1 && projectiles.projectiles_prop[i].change_animation) {
projectiles.projectiles_prop[i].change_animation = false;
projectiles.waterball.texture.update(projectiles.water_grid[std::rand() % 6]);
}
projectiles.waterball.model.translation = projectiles.projectiles_prop[i].pos;
draw(projectiles.waterball, environment);
projectiles.waterball.model.rotation = R;
draw(projectiles.waterball, environment);
projectiles.waterball.model.rotation = R2;
draw(projectiles.waterball, environment);
}
else if (projectiles.projectiles_prop[i].elemental_type == projectile::projectile_type::ice) {
if (fmod(timer.t, ball_reset_speed) > 0.1) projectiles.projectiles_prop[i].change_animation = true;
if (fmod(timer.t, ball_reset_speed) < 0.1 && projectiles.projectiles_prop[i].change_animation) {
projectiles.projectiles_prop[i].change_animation = false;
projectiles.iceball.texture.update(projectiles.ice_grid[std::rand() % 6]);
}
projectiles.iceball.model.translation = projectiles.projectiles_prop[i].pos;
draw(projectiles.iceball, environment);
projectiles.iceball.model.rotation = R;
draw(projectiles.iceball, environment);
projectiles.iceball.model.rotation = R2;
draw(projectiles.iceball, environment);
}
else if (projectiles.projectiles_prop[i].elemental_type == projectile::projectile_type::electric) {
projectiles.electroball.model.translation = projectiles.projectiles_prop[i].pos;
draw(projectiles.electroball, environment);
projectiles.electroball.model.rotation = R;
draw(projectiles.electroball, environment);
projectiles.electroball.model.rotation = R2;
draw(projectiles.electroball, environment);
}
else if (projectiles.projectiles_prop[i].elemental_type == projectile::projectile_type::rock) {
projectiles.rockball.model.translation = projectiles.projectiles_prop[i].pos;
draw(projectiles.rockball, environment);
projectiles.rockball.model.rotation = R;
draw(projectiles.rockball, environment);
projectiles.rockball.model.rotation = R2;
draw(projectiles.rockball, environment);
}
glDepthMask(true);
glDisable(GL_BLEND);
void scene_structure::mouse_move_event()
{
if (!inputs.keyboard.shift)
camera_control.action_mouse_move(environment.camera_view);
}
void scene_structure::mouse_click_event()
{
if (camera_control.inputs->mouse.click.left){
projectiles.add_ball(camera_control.camera_model.position_camera + 2*camera_control.camera_model.front(), 20*camera_control.camera_model.front());
}
camera_control.action_mouse_click(environment.camera_view);
}
void scene_structure::keyboard_event()
{
camera_control.action_keyboard(environment.camera_view);
if(camera_control.inputs->keyboard.shift) {
projectiles.reset();
}
if (camera_control.inputs->keyboard.ctrl) {
camera_control.idle_frame(environment.camera_view, 10);
}
else {
camera_control.idle_frame(environment.camera_view, gui.speed);
}