dbf-udg

annotate src/mballs.cc @ 11:5f99c4c7a9fe

now it looks pretty much ok
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 20 Feb 2013 04:55:03 +0200
parents 7056437a361b
children 1abbed71e9c9
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 }