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