dbf-udg

view src/mballs.cc @ 8:f0a47f46ee45

lalala
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 18 Feb 2013 06:53:44 +0200
parents e09cbb2e9d4f
children 7056437a361b
line source
1 #include <vector>
2 #include "opengl.h"
3 #include "mballs.h"
4 #include "metasurf.h"
5 #include "vmath/vmath.h"
7 struct MetaBall {
8 Vector3 pos;
9 float orbit;
10 float energy;
11 float phase_offs;
12 };
14 #define VOL_SZ 2
15 #define MBALL_GRID_SZ 50
17 static void update();
18 static float calc_field(float x, float y, float z);
19 static float eval(float x, float y, float z);
20 static void vertex(float x, float y, float z);
21 static void normal(float x, float y, float z);
23 static float grid[MBALL_GRID_SZ][MBALL_GRID_SZ][MBALL_GRID_SZ];
24 static std::vector<MetaBall> balls;
25 static struct metasurface *msurf;
26 static float floor_height = -0.95;
28 bool mball_init()
29 {
30 static const float bbmin = -VOL_SZ / 2.0;
31 static const float bbmax = VOL_SZ / 2.0;
33 if(!(msurf = msurf_create())) {
34 return false;
35 }
36 msurf_threshold(msurf, 10);
37 msurf_resolution(msurf, MBALL_GRID_SZ, MBALL_GRID_SZ, MBALL_GRID_SZ);
38 msurf_bounds(msurf, bbmin, bbmin, bbmin, bbmax, bbmax, bbmax);
39 msurf_eval_func(msurf, eval);
40 msurf_vertex_func(msurf, vertex);
41 //msurf_normal_func(msurf, normal);
43 for(int i=0; i<10; i++) {
44 MetaBall mb;
45 mb.orbit = 0.25 * rand() / (float)RAND_MAX + 0.35;
46 mb.energy = 0.2 * rand() / (float)RAND_MAX + 0.15;
47 mb.phase_offs = rand() / (float)RAND_MAX * M_PI * 2.0;
48 balls.push_back(mb);
49 }
51 return true;
52 }
54 void mball_render()
55 {
56 update();
58 const float blue[] = {0.4, 0.45, 1.0, 1};
59 const float dark_red[] = {0.6, 0.2, 0.1, 1};
60 const float white[] = {1, 1, 1, 1};
61 const float black[] = {0, 0, 0, 1};
63 glMatrixMode(GL_MODELVIEW);
64 glPushMatrix();
65 glScalef(4.0, 4.0, 4.0);
67 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
68 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
69 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0);
71 glBegin(GL_TRIANGLES);
72 msurf_polygonize(msurf);
73 glEnd();
75 // floor
76 glBegin(GL_QUADS);
77 glNormal3f(0, 1, 0);
78 glVertex3f(-5, -1, 5);
79 glVertex3f(5, -1, 5);
80 glVertex3f(5, -1, -5);
81 glVertex3f(-5, -1, -5);
82 glEnd();
84 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dark_red);
85 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
86 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0);
88 // box
89 glPushMatrix();
90 glTranslatef(0, -1.7, 1);
91 glScalef(1.05, 1, 0.05);
92 glutSolidCube(2.0);
93 glPopMatrix();
95 glPushMatrix();
96 glTranslatef(0, -1.7, -1);
97 glScalef(1.05, 1, 0.05);
98 glutSolidCube(2.0);
99 glPopMatrix();
101 glPushMatrix();
102 glTranslatef(1, -1.7, 0);
103 glScalef(0.05, 1, 1);
104 glutSolidCube(2.0);
105 glPopMatrix();
107 glPushMatrix();
108 glTranslatef(-1, -1.7, 0);
109 glScalef(0.05, 1, 1);
110 glutSolidCube(2.0);
111 glPopMatrix();
113 glPopMatrix();
114 }
117 static void update()
118 {
119 unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
120 float sec = msec / 1000.0;
122 for(size_t i=0; i<balls.size(); i++) {
123 float t = sec + balls[i].phase_offs;
124 balls[i].pos.x = cos(t * 1.8) * balls[i].orbit;
125 balls[i].pos.z = sin(t * 1.2) * balls[i].orbit;
126 balls[i].pos.y = (sin(t) + cos(t * 2.0) / 2.0 + sin(t * 3.0) / 3.0) * 0.45;
127 }
129 for(int i=0; i<MBALL_GRID_SZ; i++) {
130 float x = (float)i / (float)MBALL_GRID_SZ * 2.0 - 1.0;
131 for(int j=0; j<MBALL_GRID_SZ; j++) {
132 float y = (float)j / (float)MBALL_GRID_SZ * 2.0 - 1.0;
133 for(int k=0; k<MBALL_GRID_SZ; k++) {
134 float z = (float)k / (float)MBALL_GRID_SZ * 2.0 - 1.0;
135 grid[i][j][k] = calc_field(x, y, z);
136 }
137 }
138 }
139 }
141 static float calc_field(float x, float y, float z)
142 {
143 Vector3 pt(x, y, z);
145 float sum = 0.0f;
146 for(size_t i=0; i<balls.size(); i++) {
147 float dist_sq = (balls[i].pos - pt).length_sq();
148 if(dist_sq > 1e-6) {
149 sum += balls[i].energy / dist_sq;
150 } else {
151 sum += 1000.0;
152 }
153 }
155 // floor
156 float height = y - floor_height;
157 if(height > 1e-6) {
158 sum += 1.0 / height;
159 } else {
160 sum += 1000.0;
161 }
163 return sum;
164 }
166 static inline int clamp(int x, int a, int b)
167 {
168 return x < a ? a : (x > b ? b : x);
169 }
171 static float eval(float x, float y, float z)
172 {
173 int cell_x = clamp((int)((x / VOL_SZ + 0.5) * MBALL_GRID_SZ), 0, MBALL_GRID_SZ - 1);
174 int cell_y = clamp((int)((y / VOL_SZ + 0.5) * MBALL_GRID_SZ), 0, MBALL_GRID_SZ - 1);
175 int cell_z = clamp((int)((z / VOL_SZ + 0.5) * MBALL_GRID_SZ), 0, MBALL_GRID_SZ - 1);
177 return grid[cell_x][cell_y][cell_z];
178 }
180 static void vertex(float x, float y, float z)
181 {
182 float delta = (float)VOL_SZ / (float)MBALL_GRID_SZ;
184 float dfdx = calc_field(x - delta, y, z) - calc_field(x + delta, y, z);
185 float dfdy = calc_field(x, y - delta, z) - calc_field(x, y + delta, z);
186 float dfdz = calc_field(x, y, z - delta) - calc_field(x, y, z + delta);
188 float len = sqrt(dfdx * dfdx + dfdy * dfdy + dfdz * dfdz);
190 glNormal3f(dfdx / len, dfdy / len, dfdz / len);
191 glVertex3f(x, y, z);
192 }
194 static void normal(float x, float y, float z)
195 {
196 glNormal3f(x, y, z);
197 }