Compare commits

...

14 commits

16 changed files with 147 additions and 68 deletions

View file

@ -5,10 +5,11 @@
bool bouncing = true;
double stop_bouncing;
Ball::Ball(const Point& _center, double _min_height, double _v_x, double _v_z,
double _p, double _q) :
Ball::Ball(const Point& _center, const Ground* _ground, double _min_height,
double _v_x, double _v_z, double _p, double _q) :
Center(_center),
surface(_center, _min_height, _p, _q),
ground(_ground),
radius(_p),
init_h(_center.y),
min_height(_min_height),
@ -24,24 +25,26 @@ Ball::Ball(const Point& _center, double _min_height, double _v_x, double _v_z,
}
void Ball::_compute_pos(double dt) {
double height = (*ground)(Center.x, Center.z);
if (bouncing) {
Center.y = fmax(
min_height,
A + B * crt_time - (G_CTE / 2) * crt_time * crt_time + min_height
min_height + height,
A + B * crt_time - (G_CTE / 2) * crt_time * crt_time + min_height
);
} else {
double n_time = crt_time - stop_bouncing;
double min_rad = radius - min_height;
Center.y = min_height + ((min_rad * (1.0 - exp(-n_time)) + min_rad )/2.) +
(min_rad - ((min_rad* (1- exp(-n_time)) + min_rad)/2.)) * sin(5. *
n_time);
v_x *= 0.8;
v_z *= 0.8;
Center.y = height + min_height + ((min_rad * (1.0 - exp(-n_time)) + min_rad )/2.) +
(min_rad - ((min_rad* (1- exp(-n_time)) + min_rad)/2.)) * sin(5. *
n_time);
}
Center.x += dt * v_x;
Center.z += dt * v_z;
std::cout << (*this) <<"\n";
surface.update_center_pos(Center);
surface.check_horizontal_plan_collision(0.0);
surface.check_ground_collision(ground);
}
void Ball::_compute_T_n() {
@ -61,21 +64,23 @@ void Ball::_compute_U_n() {
}
void Ball::_compute_v_x(Point normal) {
double factor = normal.x / (4*(normal.x + normal.z));
double factor = 0;
if (normal.x + normal.z != 0) {
factor = normal.x / (4*(normal.x + normal.z));
}
v_x *= (0.5 + factor);
}
void Ball::_compute_v_z(Point normal) {
double factor = normal.z / (4*(normal.x + normal.z));
double factor = 0;
if (normal.x + normal.z != 0) {
factor = normal.z / (4*(normal.x + normal.z));
}
v_z *= (0.5 + factor);
}
void Ball::update_pos(double dt) {
crt_time += dt;
if ((bouncing) && (crt_time >= T)) {
double old_t = T;
double max_t;
Point normal = surface.getNormalVector();
void Ball::_compute_parameters() {
Point normal = (*ground).get_normal(Center.x, Center.z);
bounce_number += 1;
_compute_U_n();
_compute_A_n();
@ -85,6 +90,18 @@ void Ball::update_pos(double dt) {
_compute_v_z(normal);
min_height = fmin(radius, min_height + 0.2 * (radius - min_height));
std::cout << "U:" << U << "\n";
std::cout << "B:" << B << "\n";
std::cout << "A:" << A << "\n";
std::cout << "T:" << T << "\n";
}
void Ball::update_pos(double dt) {
//double height = (*ground)(Center.x, Center.z);
crt_time += dt;
if ((bouncing) && (crt_time >= T)) {
double old_t = T;
double max_t;
_compute_parameters();
max_t = (T - old_t)/2.0 + old_t;
if (((A + B * max_t - (G_CTE / 2) * max_t * max_t + min_height) < radius)) {

View file

@ -12,6 +12,8 @@
#pragma once
#include <cstddef>
#include "spheroid.hpp"
#include "FlatGround.hpp"
#include "PerlinGround.hpp"
#define G_CTE 9.81
@ -19,6 +21,7 @@ class Ball {
private:
Point Center;
Spheroid surface;
const Ground* ground;
double radius;
double init_h;
double min_height;
@ -27,6 +30,7 @@ class Ball {
double A, B, U, T; // Coefficients for the physical model.
double v_x, v_z;
void _compute_pos(double dt);
void _compute_parameters();
void _compute_v_x(Point normal);
void _compute_v_z(Point normal);
void _compute_A_n();
@ -34,7 +38,7 @@ class Ball {
void _compute_U_n();
void _compute_T_n();
public:
Ball(const Point& _center, double _min_height, double _v_x,
Ball(const Point& _center, const Ground* ground, double _min_height, double _v_x,
double _v_z, double p, double q);
void update_pos(double dt);
Point getCenter() const {return Center;}

10
FlatGround.cpp Normal file
View file

@ -0,0 +1,10 @@
#include "FlatGround.hpp"
double FlatGround::operator() (double, double) const {
return 0. ;
}
Point FlatGround::get_normal(double, double) const {
return Point(0, 1, 0);
}

8
FlatGround.hpp Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include "Ground.hpp"
class FlatGround : public Ground {
public:
double operator() (double, double) const;
Point get_normal(double x, double y) const;
};

0
Ground.cpp Normal file
View file

9
Ground.hpp Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#include "common_structures.hpp"
class Ground {
public:
virtual double operator() (double, double) const = 0;
virtual Point get_normal(double x, double y) const = 0;
};

View file

@ -11,6 +11,9 @@ OBJS=Implicit.o \
Mesh.o \
spheroid.o \
Ball.o \
Ground.o \
FlatGround.o \
PerlinGround.o \
PerlinNoise.o \
util/ObjParser.o \
MarchingCubes.o \

View file

@ -5,6 +5,8 @@
#include "GL/gl.h"
#include "GL/gl.h"
MarchingCubes::MarchingCubes(
const ImplicitSurface& surface,
const Cuboid& box,

14
PerlinGround.cpp Normal file
View file

@ -0,0 +1,14 @@
#include "PerlinGround.hpp"
PerlinGround::PerlinGround() : surface(PerlinNoise()) {}
PerlinGround::PerlinGround(unsigned int seed) : surface(PerlinNoise(seed)) {}
double PerlinGround::operator() (double x, double z) const {
return surface.noise(x, z);
}
Point PerlinGround::get_normal(double x, double z) const {
const Point pt(x, surface.noise(x, z), z);
return surface.normal_at(pt);
}

14
PerlinGround.hpp Normal file
View file

@ -0,0 +1,14 @@
#pragma once
#include "Ground.hpp"
#include "PerlinNoise.hpp"
class PerlinGround : public Ground {
public:
PerlinGround();
PerlinGround(unsigned int seed);
double operator() (double, double) const;
Point get_normal(double x, double y) const;
PerlinNoise* get_surface() { return &surface;}
private:
PerlinNoise surface;
};

View file

@ -44,7 +44,7 @@ PerlinNoise::PerlinNoise(unsigned int seed) : ImplicitSurface(Point(0,0,0)) {
}
double PerlinNoise::operator() (double x, double y, double z) const {
return z - noise(x, y, 0);
return (y - fBm(x, 0, z, 2, 0.3, 0.9));
}
double PerlinNoise::noise(double _x, double _y, double _z) const {
@ -60,31 +60,31 @@ double PerlinNoise::noise(double _x, double _y, double _z) const {
double v = fade(_y);
double w = fade(_z);
int A = p[X] + Y;
int AA = p[A] + Z;
int AB = p[A + 1] + Z;
int B = p[X + 1] + Y;
int BA = p[B] + Z;
int BB = p[B + 1] + Z;
int A = p[X] + Z;
int AA = p[A] + Y;
int AB = p[A + 1] + Y;
int B = p[X + 1] + Z;
int BA = p[B] + Y;
int BB = p[B + 1] + Y;
double res = lerp(
w,
lerp(
v,
lerp(u, grad(p[AA], _x, _y, _z), grad(p[BA], _x-1, _y, _z)),
lerp(u, grad(p[AB], _x, _y-1, _z), grad(p[BB], _x-1, _y-1, _z))
lerp(u, grad(p[AA], _x, _z, _y), grad(p[BA], _x-1, _z, _y)),
lerp(u, grad(p[AB], _x, _z-1, _y), grad(p[BB], _x-1, _z-1, _y))
),
lerp(
v,
lerp(
u,
grad(p[AA+1], _x, _y, _z-1),
grad(p[BA+1], _x-1, _y, _z-1)
grad(p[AA+1], _x, _z, _y-1),
grad(p[BA+1], _x-1, _z, _y-1)
),
lerp(
u,
grad(p[AB+1], _x, _y-1, _z-1),
grad(p[BB+1], _x-1, _y-1, _z-1)
grad(p[AB+1], _x, _z-1, _y-1),
grad(p[BB+1], _x-1, _z-1, _y-1)
)
)
);
@ -92,7 +92,7 @@ double PerlinNoise::noise(double _x, double _y, double _z) const {
}
double PerlinNoise::noise(double _x, double _y) const {
return noise(_x, _y, 0);
return noise(_x, 0, _y);
}
double PerlinNoise::fade(double t) const {
@ -111,6 +111,21 @@ double PerlinNoise::grad(int hash, double x, double y, double z) const {
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
double PerlinNoise::fBm(double x, double y, double z, int octaves, double
lacunarity, double gain) const {
double amplitude = 1.0;
double frequency = 1.0;
double sum = 0.0;
for(int i = 0; i < octaves; ++i)
{
// sum += amplitude * (1-abs(noise(x * frequency, y * frequency, z * frequency)));
sum += amplitude * noise(x * frequency, y * frequency, z * frequency);
amplitude *= gain;
frequency *= lacunarity;
}
return sum;
}
Point PerlinNoise::normal_vector(double x, double y) {
double n_x_y = noise(x, y, 0);
double n_dx_y = noise(x + 0.01, y, 0);

View file

@ -1,6 +1,7 @@
/**
* Perlin Noise implementation for the ground (header file)
**/
#pragma once
#include "Implicit.hpp"
#include <cmath>
#include <random>
@ -15,6 +16,8 @@ class PerlinNoise : public ImplicitSurface {
double operator() (double _x, double _y, double _z) const;
double noise(double x, double y) const;
Point normal_vector(double x, double y);
double fBm(double x, double y, double z, int octaves, double
lacunarity, double gain) const;
virtual Point location_hint() const;
Point location_hint(double x, double z) const;

View file

@ -5,13 +5,16 @@
#include "Ball.hpp"
#include <cstdio>
#include <iostream>
#include "FlatGround.hpp"
using namespace std;
int main() {
int i;
Point center(0,10,0);
Ball ball(center, 0, 0.25, 0, 1, 1);
FlatGround* flat = new FlatGround();
Ball ball(center,flat, 0, 0.25, 0, 1, 1);
for(i=0; i< 10000; i++) {
ball.update_pos(0.001);
cout << ball << "\n";

View file

@ -4,17 +4,21 @@
#include "render/GlutRender.hpp"
#include "Ball.hpp"
#include "FlatGround.hpp"
#include "MarchingCubes.hpp"
#include "periodic_updates.hpp"
int main(int argc, char** argv) {
FlatGround* flat = new FlatGround();
GlutRender& render = GlutRender::get_instance();
render.init(&argc, argv, 640, 480, "Bouncing stuff");
Ball ball(Point(0, 5, 0), 0.75, -.5, -.7, 1, 1);
Ball ball(Point(0, 5, 0), flat, 0.75, -0.5, -0.7, 1, 1);
Cuboid bbox = ball.get_surface()->max_bounding_box();
Cuboid bbox_2(Point(-2, -1, -2), Point(2,1,2));
printf("%.2lf %.2lf %.2lf | %.2lf %.2lf %.2lf\n",
bbox.low(0), bbox.low(1), bbox.low(2),
bbox.high(0), bbox.high(1), bbox.high(2));

View file

@ -6,7 +6,7 @@
#include <iostream>
Spheroid::Spheroid(const Point& _center, double _min_p, double _p, double _q) :
ImplicitSurface(_center), normal_vector(Point(0,0,1)), min_p(_min_p),
ImplicitSurface(_center), min_p(_min_p),
init_p(_p), p(_p), q(_q), stiffness(0)
{
_compute_volume();
@ -22,35 +22,19 @@ void Spheroid::update_radius() {
q = sqrt((3./4.) * V / PI / p);
}
void Spheroid::update_height() {
q = (3./4.) * V / PI / (p*p);
}
void Spheroid::update_center_pos(Point& _center) {
center = _center;
}
void Spheroid::check_horizontal_plan_collision(double height) {
if (((center.y - p) <= height) || (p < init_p)) {
p = fmin(init_p, center.y-height);
void Spheroid::check_ground_collision(const Ground* ground) {
double height = (*ground)(center.x, center.z);
if (((center.y -p) <= height) || (p < init_p)) {
p = fmin(init_p, center.y - height);
update_radius();
}
}
void Spheroid::check_vertical_plan_collision(double& abscissa) {
if (center.x <= abscissa) {
if ((center.x + q) >= abscissa) {
q = abscissa - center.x;
update_height();
}
} else {
if ((center.x - q) <= abscissa) {
q = center.x - abscissa;
update_height();
}
}
}
Cuboid Spheroid::max_bounding_box() const {
double max_radius = sqrt((3./4.) * V / PI / min_p);
@ -60,15 +44,6 @@ Cuboid Spheroid::max_bounding_box() const {
return Cuboid(_bd1, _bd2);
}
void Spheroid::check_perlin_collision(PerlinNoise perlin) {
double height = perlin.noise(center.x, center.z);
if ((center.y - p) <= height) {
p = fmin(init_p, center.z- height );
normal_vector = perlin.normal_vector(center.x, center.z);
update_radius();
}
}
double Spheroid::operator() (double _x, double _y, double _z) const {
return (pow(_x, 2) / pow(q, 2)

View file

@ -8,6 +8,8 @@
#include "Implicit.hpp"
#include "common_structures.hpp"
#include "PerlinNoise.hpp"
#include "FlatGround.hpp"
#include "PerlinGround.hpp"
const double PI = 3.141592653589793;
@ -16,12 +18,9 @@ class Spheroid : public ImplicitSurface {
Spheroid(const Point& _center, double _min_p, double _p, double _q);
void update_center_pos(Point& _center);
void update_radius();
void update_height();
void check_horizontal_plan_collision(double height);
void check_vertical_plan_collision(double& abscissa);
void check_ground_collision(const Ground* ground);
Cuboid max_bounding_box() const;
void check_perlin_collision(PerlinNoise perlin);
Point getNormalVector() const { return normal_vector;}
double operator() (double _x, double _y, double _z) const;
virtual Point location_hint() const;
@ -32,7 +31,6 @@ class Spheroid : public ImplicitSurface {
* V is the volume. Extremely useful to have a constant volume in the
* ball
**/
Point normal_vector;
double min_p, init_p, p, q;
size_t stiffness;
double V;