summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--balls.cpp87
-rw-r--r--balls.h12
-rw-r--r--collision.cpp (renamed from collision.c)9
-rw-r--r--geometry.cpp11
-rw-r--r--rand.cpp15
6 files changed, 127 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index b4e8116..ed96b3c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ CC = g++
CFLAGS = -Wall -pedantic
LDFLAGS = -ltbb -lglut -lGLU -lGL
-balls: balls.o collision.o geometry.o
+balls: balls.o collision.o geometry.o rand.o
${CC} -o $@ $^ ${LDFLAGS}
@echo done
diff --git a/balls.cpp b/balls.cpp
index c14a1dc..0f870ff 100644
--- a/balls.cpp
+++ b/balls.cpp
@@ -1,4 +1,4 @@
-#include <stdlib.h>
+#include <iostream>
#include <GL/glut.h>
#include <oneapi/tbb.h>
@@ -6,6 +6,14 @@
using namespace std;
+#define VMAX_INIT 0.15
+ /* max initial velocity [m/s] */
+#define RMIN 0.05
+#define RMAX 0.10
+ /* min/max radius [m] */
+#define DENSITY 1500.0
+ /* density of ball [kg/m^3] */
+
enum {
WIDTH = 800,
HEIGHT = 600,
@@ -17,6 +25,8 @@ enum {
FPS = 60,
MS_PER_S = 1000,
FRAME_TIME_MS = MS_PER_S / FPS,
+
+ NBALLS_DEFAULT = 3,
};
void keyboard(unsigned char key, int x, int y);
@@ -24,10 +34,15 @@ void display(void);
void drawBg(void);
void drawCircle(double radius, Point p);
void reshape(int w, int h);
+vector<Ball> makeBalls(unsigned int n);
+vector<Point> noOverlapCircles(unsigned int n);
+double mass(double radius);
+double volumeSphere(double radius);
void animate(int v);
const static Rectangle bounds = {{-1.5, -1.0}, {1.5, 1.0}};
-static Ball ball = {{0.25, 0.25}, {0.25, 0.25}, 0.200, 0.25};
+
+static vector<Ball> balls;
int
main(int argc, char *argv[]) {
@@ -39,6 +54,9 @@ main(int argc, char *argv[]) {
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
+
+ balls = makeBalls(NBALLS_DEFAULT);
+
glutTimerFunc(FRAME_TIME_MS, animate, 0);
glutMainLoop();
@@ -57,7 +75,8 @@ display(void) {
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
drawBg();
- drawCircle(ball.r, ball.p);
+ for (Ball b : balls)
+ drawCircle(b.r, b.p);
glutSwapBuffers();
}
@@ -105,11 +124,67 @@ reshape(int w, int h) {
glMatrixMode(GL_MODELVIEW);
}
+vector<Ball>
+makeBalls(unsigned int n) {
+ vector<Ball> balls(n);
+ vector<Point> ps = noOverlapCircles(n);
+ unsigned int i;
+
+ srand(time(0));
+ for (i = 0; i < n; i++) {
+ cout << "Creating ball " << i << "\n";
+ balls[i].p = ps[i];
+
+ balls[i].v.x = randDouble(-VMAX_INIT, VMAX_INIT);
+ balls[i].v.y = randDouble(-VMAX_INIT, VMAX_INIT);
+
+ balls[i].r = randDouble(RMIN, RMAX);
+
+ balls[i].m = mass(balls[i].r);
+ }
+ return balls;
+}
+
+vector<Point>
+noOverlapCircles(unsigned int n) {
+ vector<Point> ps(n);
+ Rectangle r;
+ unsigned int i, j;
+
+ srand(time(0));
+ r = insetRect(bounds, RMAX);
+ for (i = 0; i < n; i++) {
+ cout << "Create non-overlapping circle " << i << "\n";
+ ps[i] = randPtInRect(r);
+ for (j = 0; j < i; j++) /* TODO: parallel reduce */
+ if (isCollision(ps[j], RMAX, ps[i], RMAX))
+ break;
+ if (j < i) { /* overlapping */
+ i--;
+ continue;
+ }
+ }
+ return ps;
+}
+
+/* mass [kg] of ball as function of radius [m] */
+double
+mass(double radius) {
+ return volumeSphere(radius) * DENSITY;
+}
+
+/* volume [m^3] of sphere as function of radius [m] */
+double
+volumeSphere(double radius) {
+ return 4.0 * M_PI * radius*radius*radius / 3.0;
+}
+
void
animate(int v) {
- ball.p = ptAddVec(ball.p, ball.v);
-
- collideWall(&ball, bounds);
+ for (Ball& ball : balls) {
+ ball.p = ptAddVec(ball.p, ball.v);
+ collideWall(&ball, bounds);
+ }
display();
glutTimerFunc(FRAME_TIME_MS, animate, 0);
diff --git a/balls.h b/balls.h
index 3205959..b69eea4 100644
--- a/balls.h
+++ b/balls.h
@@ -1,3 +1,5 @@
+#include <stdlib.h>
+
typedef struct {
double x, y;
} Point;
@@ -13,11 +15,17 @@ typedef struct {
typedef struct {
Point p; /* position [m] */
Vector v; /* velocity [m/s] */
- double m; /* mass [kg] */
double r; /* radius [m] */
+ double m; /* mass [kg] */
} Ball;
Point ptAddVec(Point p, Vector v);
+Point Pt(double x, double y);
Rectangle insetRect(Rectangle r, double n);
+Point randPtInRect(Rectangle r);
+
+int isCollision(Point p1, double r1, Point p2, double r2);
+void collideWall(Ball *b, Rectangle wall);
-void collideWall(Ball *b, Rectangle wall); \ No newline at end of file
+int randInt(int lo, int hi);
+double randDouble(double lo, double hi);
diff --git a/collision.c b/collision.cpp
index 17889a4..1ffe957 100644
--- a/collision.c
+++ b/collision.cpp
@@ -4,6 +4,15 @@ static double clamp(double v, double lo, double hi);
static double min(double a, double b);
static double max(double a, double b);
+int
+isCollision(Point p1, double r1, Point p2, double r2) {
+ double dx, dy;
+
+ dx = p1.x - p2.x;
+ dy = p1.y - p2.y;
+ return (dx*dx + dy*dy) <= (r1+r2)*(r1+r2);
+}
+
void
collideWall(Ball *b, Rectangle wall) {
wall = insetRect(wall, b->r);
diff --git a/geometry.cpp b/geometry.cpp
index ae2c8ae..2bdad8c 100644
--- a/geometry.cpp
+++ b/geometry.cpp
@@ -7,6 +7,12 @@ ptAddVec(Point p, Vector v) {
return p;
}
+Point
+Pt(double x, double y) {
+ Point p = {x, y};
+ return p;
+}
+
Rectangle
insetRect(Rectangle r, double n) {
r.min.x += n;
@@ -15,3 +21,8 @@ insetRect(Rectangle r, double n) {
r.max.y -= n;
return r;
}
+
+Point
+randPtInRect(Rectangle r) {
+ return Pt(randDouble(r.min.x, r.max.x), randDouble(r.min.y, r.max.y));
+}
diff --git a/rand.cpp b/rand.cpp
new file mode 100644
index 0000000..6ffe897
--- /dev/null
+++ b/rand.cpp
@@ -0,0 +1,15 @@
+#include "balls.h"
+
+int
+randInt(int lo, int hi) {
+ return (rand() % (hi-lo)) + lo;
+}
+
+double
+randDouble(double lo, double hi) {
+ double r, diff;
+
+ r = (double) rand() / (double) RAND_MAX;
+ diff = hi - lo;
+ return lo + r*diff;
+}