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;
void scene_structure::initialize()
{
camera_control.initialize(inputs, window); // Give access to the inputs and window global state to the camera controler
//for orbit camera
//camera_control.set_rotation_axis_z();
//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.set_rotation_axis({ 0,0,1 });
//custum function we added to ..first_person_euler
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);
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());
mesh const terrain_mesh = create_terrain_mesh(N_terrain_samples, terrain_length);
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 };
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/texture_grass.jpg",
GL_REPEAT,
GL_MIRRORED_REPEAT);
terrain.supplementary_texture["image_texture_2"].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);
float x = 1.0;
float y = 2.0;
tree.model.translation = { x, y, evaluate_terrain_height(x,y, terrain_length) };
tree_position = generate_positions_on_terrain(num_trees, terrain_length-1);
grass_position = generate_positions_on_terrain(num_grass, terrain_length-1);
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} };
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);
bird1.initialize_bird();
initialize_mvt();
chain1.initialize();
bouncing.initialize();
}
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;
// 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;
}
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
draw(skybox, environment);
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], terrain_length) + 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++) {
tree.model.translation = tree_position[i];
draw(tree, environment);
}
vec3 p = display_mvt();
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
if (gui.display_wireframe)
draw_wireframe(tree, environment);
display_semiTransparent();
}
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(vec3 p)
{
// 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));
// This function must be called before the drawing in order to propagate the deformations through the hierarchy
bat1.bat.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);
bat1.bat["Bat base"].transform_local.rotation = rotation_transform::from_vector_transform({ 0,-1,0 }, normalize(p2 - p));
bat1.bat["Bat base"].transform_local.translation = p;
draw(bat1.bat, environment);
if (gui.display_wireframe) {
draw_wireframe(bat1.bat, environment);
}
}
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
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
334
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++) {
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;
draw(grass, environment);
}
// Don't forget to re-activate the depth-buffer write
glDepthMask(true);
glDisable(GL_BLEND);
}
vec3 scene_structure::display_mvt()
{
// Basic elements of the scene
environment.light = camera_control.camera_model.position();
if (gui.display_frame)
draw(global_frame, environment);
// 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 });
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::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("K", &gui.k, 0.0f, 10.0f);
ImGui::SliderFloat("Speed", &gui.speed, 0.0f, 10.0f);
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
// Display the GUI associated to the key position
keyframe.display_gui();
}
void scene_structure::display_ball() {
bouncing.simulate(timer_chain.scale * 0.01f, terrain_length);
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::mouse_move_event()
{
if (!inputs.keyboard.shift)
camera_control.action_mouse_move(environment.camera_view);
}
void scene_structure::mouse_click_event()
{
camera_control.action_mouse_click(environment.camera_view);
}
void scene_structure::keyboard_event()
{
camera_control.action_keyboard(environment.camera_view);
}
void scene_structure::idle_frame()
{
if (camera_control.inputs->keyboard.ctrl) {
camera_control.idle_frame(environment.camera_view, 10);
}
else {
camera_control.idle_frame(environment.camera_view, gui.speed);
}