Compare commits

...

21 commits

Author SHA1 Message Date
Théophile Bastian 8051f4203f Allow the camera to follow the ball
But when the ground is not textured, this looks just as if the ball was
not moving… :(
2018-02-14 13:23:27 +01:00
Théophile Bastian baaa5e4057 Control pause and speed with keyboard
Keys: space for toggle pause, < and > for speed control, 0 to reset
speed
2018-02-14 13:22:31 +01:00
Théophile Bastian 8bd230c010 Remove lag: lower resolution for ground 2018-02-14 13:21:49 +01:00
Théophile Bastian eaa730f5dc Integrate Perlin noise switch
Also make Perlin noise ground wider and less ugly
2018-02-14 13:16:01 +01:00
Rémi Oudin b208cc237e Perlin Ground integrated 2018-02-14 12:47:45 +01:00
Théophile Bastian 3bf61a7409 Enhance slightly the scene (floor + background) 2018-02-14 11:43:49 +01:00
Théophile Bastian 3e3ec57bb5 Add a color attribute to meshes and surfaces 2018-02-14 11:41:55 +01:00
Rémi Oudin 818aaf01a9 Finished rebase 2018-02-14 11:41:24 +01:00
Rémi Oudin d8dafd3823 Better parameters 2018-02-14 10:50:03 +01:00
Rémi Oudin d23f05de14 Woops, wrong variables 2018-02-14 10:34:54 +01:00
Rémi Oudin 2afd89dbf3 Fractional Brownian Motion 2018-02-13 23:38:24 +01:00
Rémi Oudin 6823552ee7 Error after rebase 2018-02-13 22:56:44 +01:00
Rémi Oudin 041a1236c0 missing interface in header file 2018-02-13 22:55:12 +01:00
Rémi Oudin f6f789cc2e Utility function 2018-02-13 22:55:12 +01:00
Rémi Oudin 14f3b8afdf Display Perlin ground 2018-02-13 22:54:41 +01:00
Rémi Oudin 75fc077007 No more glitch. 2018-02-13 22:54:41 +01:00
Rémi Oudin aafbd8ec9c Add a get_surface method to perlin ground 2018-02-13 22:54:41 +01:00
Rémi Oudin 083bc3c654 Many many changes 2018-02-13 22:54:41 +01:00
Rémi Oudin 538930bd71 Bug fix (y and z axis) + pragma 2018-02-13 22:51:51 +01:00
Rémi Oudin 15ee31c30e Integration of the grounds 2018-02-13 22:51:51 +01:00
Rémi Oudin d484a18da5 Add some structure for the ground. 2018-02-13 22:49:30 +01:00
25 changed files with 370 additions and 89 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,25 @@ 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;
surface.update_center_pos(Center);
surface.check_horizontal_plan_collision(0.0);
surface.check_ground_collision(ground);
}
void Ball::_compute_T_n() {
@ -61,21 +63,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();
@ -84,7 +88,15 @@ void Ball::update_pos(double dt) {
_compute_v_x(normal);
_compute_v_z(normal);
min_height = fmin(radius, min_height + 0.2 * (radius - min_height));
std::cout << "U:" << U << "\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;
};

45
GroundFlatMesh.cpp Normal file
View file

@ -0,0 +1,45 @@
#include "GroundFlatMesh.hpp"
#include <vector>
const int GroundFlatMesh::MIN_I = -40;
const int GroundFlatMesh::MAX_I = 100;
const int GroundFlatMesh::MIN_J = -40;
const int GroundFlatMesh::MAX_J = 100;
GroundFlatMesh::GroundFlatMesh(const Point& center, double decay_speed)
: center(center), decay_speed(decay_speed)
{
std::vector<std::vector<size_t> > vertice_at(MAX_I - MIN_I + 1,
std::vector<size_t>(MAX_J - MIN_J + 1));
for(int i=MIN_I; i < MAX_I + 1; ++i) {
for(int j=MIN_J; j < MAX_J + 1; ++j) {
vertice_at[i - MIN_I][j - MIN_J] =
output.add_vertice(
tile_position(i, j),
Point(0., 1., 0.));
}
}
for(int i=MIN_I; i < MAX_I; ++i) {
for(int j=MIN_J; j < MAX_J; ++j) {
output.add_face(Face(
vertice_at[i - MIN_I][j - MIN_J],
vertice_at[i - MIN_I][j + 1 - MIN_J],
vertice_at[i + 1 - MIN_I][j + 1 - MIN_J]));
output.add_face(Face(
vertice_at[i - MIN_I][j - MIN_J],
vertice_at[i + 1 - MIN_I][j + 1 - MIN_J],
vertice_at[i + 1- MIN_I][j - MIN_J]));
}
}
}
double GroundFlatMesh::ith_dist(int i) const {
return ((i < 0) ? -1 : 1) * decay_speed * i * i;
}
Point GroundFlatMesh::tile_position(int i, int j) const {
return Point(ith_dist(i), 0., ith_dist(j));
}

20
GroundFlatMesh.hpp Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include "Mesh.hpp"
class GroundFlatMesh {
public:
GroundFlatMesh(const Point& center, double decay_speed);
Mesh* get_mesh() { return &output; }
private: //meth
double ith_dist(int i) const;
Point tile_position(int i, int j) const;
private:
static const int MIN_I, MAX_I, MIN_J, MAX_J;
Mesh output;
const Point& center;
double decay_speed;
};

View file

@ -8,11 +8,16 @@ class ImplicitSurface {
double operator()(const Point& pt) const;
Point getCenter() const { return center;}
const Color& get_color() const { return color; }
void set_color(const Color& _color) { color = _color; }
virtual Point location_hint() const = 0;
/// Compute the normal vector to the isosurface at `pt`
Point normal_at(const Point& pt) const;
protected:
Point center;
Color color;
ImplicitSurface(Point _center) : center(_center) {}
};

View file

@ -11,11 +11,15 @@ OBJS=Implicit.o \
Mesh.o \
spheroid.o \
Ball.o \
Ground.o \
FlatGround.o \
PerlinGround.o \
PerlinNoise.o \
util/ObjParser.o \
MarchingCubes.o \
_gen/marching_cubes_data.o \
periodic_updates.o \
GroundFlatMesh.o \
tests/TestImplicitSphere.o \
render/GlutRender.o

View file

@ -5,6 +5,8 @@
#include "GL/gl.h"
#include "GL/gl.h"
MarchingCubes::MarchingCubes(
const ImplicitSurface& surface,
const Cuboid& box,
@ -22,6 +24,8 @@ MarchingCubes& MarchingCubes::add_hint(const Point& hint) {
Mesh MarchingCubes::operator()() {
Mesh output;
output.set_color(surface.get_color());
perf_counter = 0;
if(hints.empty())
@ -29,7 +33,9 @@ Mesh MarchingCubes::operator()() {
else
with_hints(output);
printf("Explored cubes: %ld\n", perf_counter);
#ifdef MC_SHOW_PERF
fprintf(stderr, "Explored cubes: %ld\n", perf_counter);
#endif // MC_SHOW_PERF
output.translate(surface.getCenter());

View file

@ -41,6 +41,9 @@ class Mesh {
/// Gets the various faces
const std::vector<Face>& get_faces() const;
const Color& get_color() const { return color; }
void set_color(const Color& _color) { color = _color; }
private: //struct
struct NormalVect {
NormalVect(const Point& vect, bool manual=false)
@ -63,4 +66,5 @@ class Mesh {
std::vector<std::vector<size_t> > faces_with_vert;
Point center;
Color color;
};

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

@ -152,6 +152,20 @@ class Cuboid {
Point lowBound, highBound;
};
struct Color {
Color() : r(0), g(0), b(0) {}
Color(double r, double g, double b) : r(r), g(g), b(b) {}
double r, g, b;
double operator[](int i) const {
switch(i % 3) {
case 0: return r;
case 1: return g;
case 2: return b;
}
return 0; // won't happen
}
};
namespace std {
template<> struct hash<Face>
{

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

@ -2,25 +2,60 @@
* bouncing implicit-surface defined sphere.
**/
#include <cstring>
#include "render/GlutRender.hpp"
#include "Ball.hpp"
#include "FlatGround.hpp"
#include "MarchingCubes.hpp"
#include "GroundFlatMesh.hpp"
#include "periodic_updates.hpp"
int main(int argc, char** argv) {
bool perlin = false;
for(int pos=1; pos < argc; ++pos) {
if(strcmp(argv[pos], "-perlin") == 0)
perlin = true;
}
// Last minute switch, this code is ugly, please close your eyes until
// stated otherwise.
PerlinGround perlin_ground;
FlatGround flat_ground;
GroundFlatMesh ground_mesh(Point(0., 0., 0.), 0.05);
Ground* ball_ground = nullptr;
if(perlin)
ball_ground = &perlin_ground;
else
ball_ground = &flat_ground;
// You can open your eyes, now.
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), ball_ground, 0.55, -.5, -.7, 1, 1);
ball.get_surface()->set_color(Color(1., 0., 0.));
Cuboid bbox = ball.get_surface()->max_bounding_box();
Cuboid bbox_2(Point(-20, -3, -20), Point(20,3,20));
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));
render.add_surface(ball.get_surface(), bbox);
if(perlin) {
perlin_ground.get_surface()->set_color(Color(0.13, 0.82, 0.21));
render.add_surface(perlin_ground.get_surface(), bbox_2, 1.2);
}
else {
ground_mesh.get_mesh()->set_color(Color(0.13, 0.82, 0.21));
render.add_mesh(ground_mesh.get_mesh());
}
//render.follow_implicit_position(ball.get_surface());
render.set_idle_func(periodic_update);
render.add_kb_handler(periodic_kb_handler);
init_periodic_static(&ball);
render.run();

View file

@ -8,6 +8,9 @@ static Ball* _ball = nullptr;
static std::chrono::time_point<std::chrono::steady_clock>
_last_time, _init_clocks;
static bool is_paused = false;
static double speed_factor = 1.;
void init_periodic_static(Ball* ball) {
_last_time = std::chrono::steady_clock::now();
_init_clocks = std::chrono::steady_clock::now();
@ -23,9 +26,32 @@ double ellapsed_double(
}
void periodic_update() {
if(is_paused)
return;
printf("%lf\n", speed_factor);
auto now = std::chrono::steady_clock::now();
_ball->update_pos(ellapsed_double(_last_time, now));
_ball->update_pos(speed_factor * ellapsed_double(_last_time, now));
_last_time = now;
glutPostRedisplay();
}
void periodic_kb_handler(unsigned char key, int, int) {
if(key == ' ') {
if(is_paused)
_last_time = std::chrono::steady_clock::now();
is_paused = !is_paused;
}
else if(key == '<') {
speed_factor -= .1;
if(speed_factor <= 0.05)
speed_factor = .1;
}
else if(key == '>') {
speed_factor += .1;
}
else if(key == '0') {
speed_factor = 1.;
}
}

View file

@ -4,3 +4,5 @@
void init_periodic_static(Ball* ball);
void periodic_update();
void periodic_kb_handler(unsigned char key, int, int);

View file

@ -12,7 +12,7 @@ GlutRender& GlutRender::get_instance() {
return instance;
}
GlutRender::GlutRender() {
GlutRender::GlutRender() : followed_implicit(nullptr) {
std::default_random_engine rand_engine(time(NULL));
std::uniform_real_distribution<double> distribution;
rand_color = std::bind(distribution, rand_engine);
@ -29,12 +29,13 @@ void GlutRender::init(int* argc, char** argv,
// ==== Callbacks ====
glutDisplayFunc(display_handle);
glutReshapeFunc(reshape_handle);
glutKeyboardFunc(kb_evt_handle);
// ==== Lighting ====
GLfloat light0_pos[] = {10., 15., 10.};
GLfloat light0_pos[] = {30., 35., 20., 0.};
GLfloat light0_ambient[] = {0., 0., 0., 1.};
GLfloat light0_diffuse[] = {1., 1., .65, 1.};
GLfloat light0_specular[] = {5., 5., .33, 1.};
GLfloat light0_diffuse[] = {1., 1., .85, 1.};
GLfloat light0_specular[] = {5., 5., .43, 1.};
glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
@ -47,15 +48,16 @@ void GlutRender::init(int* argc, char** argv,
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH); // Enable smooth shading
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
GLfloat material_specular[] = {1., 1., 1., 1.};
GLfloat material_emission[] = {0., 0., 0., 1.};
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material_emission);
glEnable(GL_COLOR_MATERIAL);
// ==== Misc ====
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Background color
//glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Background color
glClearColor(0.15f, 0.08f, 0.5f, 1.0f); // Background color
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
@ -73,12 +75,14 @@ void GlutRender::remove_mesh(Mesh* mesh) {
meshes.erase(mesh);
}
void GlutRender::add_surface(ImplicitSurface* surf, const Cuboid& box) {
surfaces.insert(SurfaceDetails(surf, box));
void GlutRender::add_surface(ImplicitSurface* surf, const Cuboid& box,
double resolution)
{
surfaces.insert(SurfaceDetails(surf, box, resolution));
}
void GlutRender::remove_surface(ImplicitSurface* surf) {
surfaces.erase(SurfaceDetails(surf, Cuboid::empty()));
surfaces.erase(SurfaceDetails(surf, Cuboid::empty(), 0.1));
}
void GlutRender::run() {
@ -89,6 +93,14 @@ void GlutRender::set_idle_func(void (*func)(void)) {
glutIdleFunc(func);
}
void GlutRender::add_kb_handler(GlutRender::kb_handler_t handler) {
kb_handlers.push_back(handler);
}
void GlutRender::follow_implicit_position(const ImplicitSurface* surf) {
followed_implicit = surf;
}
void GlutRender::reshape(int wid, int hei) {
if (hei == 0)
hei = 1;
@ -149,8 +161,15 @@ void GlutRender::display_mesh(Mesh& mesh) const {
#endif // DEBUG_DISPLAY_WIREFRAME
const Color& color = mesh.get_color();
GLfloat material_specular[] = {
(float)color[0],
(float)color[1],
(float)color[2],
1.};
glBegin(GL_TRIANGLES);
glColor3f(1., 1., 1.);
glColor3f(color[0], color[1], color[2]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);
for(const Face& face: mesh.get_faces()) {
Point p0 = face.pt(0, points) + mesh_center,
p1 = face.pt(1, points) + mesh_center,
@ -172,17 +191,27 @@ void GlutRender::display() {
// Camera position and orientation
glLoadIdentity();
//glTranslatef(1., 2., -10.);
gluLookAt(0, 2.5, -10,
0, 2.5, 0,
0, 1, 0);
Point look_from(0, 2.5, -10);
if(followed_implicit != nullptr) {
const Point& look_at = followed_implicit->getCenter();
gluLookAt(look_from.x, look_from.y, look_from.z,
look_at.x, look_from.y, look_at.z,
0, 1, 0);
}
else {
gluLookAt(look_from.x, look_from.y, look_from.z,
0, 2.5, 0,
0, 1, 0);
}
for(Mesh* mesh: meshes) {
display_mesh(*mesh);
}
for(const SurfaceDetails& surface: surfaces) {
Mesh mesh = MarchingCubes(*surface.surface, surface.box)
Mesh mesh = MarchingCubes(*surface.surface, surface.box,
surface.resolution)
.add_hint(surface.surface->location_hint())
();
display_mesh(mesh);
@ -191,9 +220,18 @@ void GlutRender::display() {
glutSwapBuffers();
}
void GlutRender::on_kb_evt(unsigned char key, int x, int y) {
for(auto& handler: kb_handlers) {
handler(key, x, y);
}
}
void GlutRender::reshape_handle(int wid, int hei) {
get_instance().reshape(wid, hei);
}
void GlutRender::display_handle() {
get_instance().display();
}
void GlutRender::kb_evt_handle(unsigned char key, int x, int y) {
get_instance().on_kb_evt(key, x, y);
}

View file

@ -5,9 +5,12 @@
#include "../Mesh.hpp"
#include "../Implicit.hpp"
#include <set>
#include <functional>
class GlutRender {
public:
typedef std::function<void(unsigned char, int, int)> kb_handler_t;
static GlutRender& get_instance();
GlutRender(GlutRender const&) = delete;
@ -18,19 +21,26 @@ class GlutRender {
void cleanup();
void add_mesh(Mesh* mesh);
void remove_mesh(Mesh* mesh);
void add_surface(ImplicitSurface* surf, const Cuboid& box);
void add_surface(ImplicitSurface* surf, const Cuboid& box,
double resolution=0.1);
void remove_surface(ImplicitSurface* surf);
void run();
void set_idle_func(void (*func)(void));
void add_kb_handler(kb_handler_t handler);
void follow_implicit_position(const ImplicitSurface* surf);
private:
struct SurfaceDetails {
SurfaceDetails(ImplicitSurface* surf, const Cuboid& box):
surface(surf), box(box) {}
SurfaceDetails(ImplicitSurface* surf, const Cuboid& box,
double resolution):
surface(surf), box(box), resolution(resolution) {}
ImplicitSurface* surface;
Cuboid box;
double resolution;
bool operator<(const SurfaceDetails& oth) const {
return surface < oth.surface;
@ -46,13 +56,20 @@ class GlutRender {
protected:
void reshape(int wid, int hei);
void display();
void on_kb_evt(unsigned char key, int x, int y);
static void reshape_handle(int wid, int hei);
static void display_handle();
static void kb_evt_handle(unsigned char key, int x, int y);
private: //attr
std::function<double()> rand_color;
std::set<Mesh*> meshes;
std::set<SurfaceDetails> surfaces;
std::vector<kb_handler_t> kb_handlers;
const ImplicitSurface* followed_implicit;
};

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;