#include "ball.hpp" #include "terrain.hpp" #include "settings.hpp" void ball::initialize(int n) { N = n; pos.resize(N); v.resize(N); color.resize(N); mesh.initialize_data_on_gpu(mesh_primitive_sphere(0.1f)); for (int i = 0; i < N; i++) { color[i] = { rand_interval(0.0f, 1.0f), rand_interval(0.0f, 1.0f), rand_interval(0.0f, 1.0f) }; pos[i] = { 0,0,40 }; v[i] = { 2 * cos(360 * i / N) ,2 * sin(360 * i / N),10 }; } } void ball::reset() { N = 0; pos.resize(N); v.resize(N); color.resize(N); } void ball::add_ball(vec3 new_pos, vec3 new_dir) { N++; pos.resize(N); v.resize(N); color.resize(N); color[N-1] = { rand_interval(0.0f, 1.0f), rand_interval(0.0f, 1.0f), rand_interval(0.0f, 1.0f) }; pos[N-1] = new_pos; v[N-1] = new_dir; } 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) }; 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])) { vec3 normal = normalize(terrain_orientation(pos[i][0], pos[i][1])); vec3 temp = v[i] - dot(v[i], normal) * normal; v[i] -= 2 * temp; v[i] = -v[i]; float diffusion = 1.1; v[i] /= diffusion; } } } 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) - z }; vec3 v = { 0, step, evaluate_terrain_height(x,y + step) - z }; return cross(v, u); }