dbf-udg

annotate src/mballs.cc @ 15:2d1a9b5111f9

added visual studio project
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 20 Feb 2013 06:03:31 +0200
parents 1abbed71e9c9
children
rev   line source
nuclear@12 1 /*
nuclear@13 2 Printblobs - halftoning display hack
nuclear@12 3 Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org>
nuclear@12 4
nuclear@12 5 This program is free software: you can redistribute it and/or modify
nuclear@12 6 it under the terms of the GNU General Public License as published by
nuclear@12 7 the Free Software Foundation, either version 3 of the License, or
nuclear@12 8 (at your option) any later version.
nuclear@12 9
nuclear@12 10 This program is distributed in the hope that it will be useful,
nuclear@12 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@12 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@12 13 GNU General Public License for more details.
nuclear@12 14
nuclear@12 15 You should have received a copy of the GNU General Public License
nuclear@12 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@12 17 */
nuclear@5 18 #include <vector>
nuclear@12 19 #include <math.h>
nuclear@5 20 #include "opengl.h"
nuclear@5 21 #include "mballs.h"
nuclear@5 22 #include "metasurf.h"
nuclear@9 23 #include "dsys.h"
nuclear@11 24 #include "udg.h"
nuclear@5 25
nuclear@5 26 struct MetaBall {
nuclear@12 27 float pos[3];
nuclear@5 28 float orbit;
nuclear@5 29 float energy;
nuclear@5 30 float phase_offs;
nuclear@5 31 };
nuclear@5 32
nuclear@5 33 #define VOL_SZ 2
nuclear@5 34 #define MBALL_GRID_SZ 50
nuclear@5 35
nuclear@9 36 static void update(float sec);
nuclear@5 37 static float calc_field(float x, float y, float z);
nuclear@5 38 static float eval(float x, float y, float z);
nuclear@5 39 static void vertex(float x, float y, float z);
nuclear@5 40 static void normal(float x, float y, float z);
nuclear@5 41
nuclear@5 42 static float grid[MBALL_GRID_SZ][MBALL_GRID_SZ][MBALL_GRID_SZ];
nuclear@5 43 static std::vector<MetaBall> balls;
nuclear@5 44 static struct metasurface *msurf;
nuclear@8 45 static float floor_height = -0.95;
nuclear@5 46
nuclear@11 47 static struct dsys_event *evrise;
nuclear@11 48
nuclear@5 49 bool mball_init()
nuclear@5 50 {
nuclear@5 51 static const float bbmin = -VOL_SZ / 2.0;
nuclear@5 52 static const float bbmax = VOL_SZ / 2.0;
nuclear@5 53
nuclear@5 54 if(!(msurf = msurf_create())) {
nuclear@5 55 return false;
nuclear@5 56 }
nuclear@5 57 msurf_threshold(msurf, 10);
nuclear@5 58 msurf_resolution(msurf, MBALL_GRID_SZ, MBALL_GRID_SZ, MBALL_GRID_SZ);
nuclear@5 59 msurf_bounds(msurf, bbmin, bbmin, bbmin, bbmax, bbmax, bbmax);
nuclear@5 60 msurf_eval_func(msurf, eval);
nuclear@5 61 msurf_vertex_func(msurf, vertex);
nuclear@5 62 //msurf_normal_func(msurf, normal);
nuclear@5 63
nuclear@5 64 for(int i=0; i<10; i++) {
nuclear@5 65 MetaBall mb;
nuclear@5 66 mb.orbit = 0.25 * rand() / (float)RAND_MAX + 0.35;
nuclear@9 67 mb.energy = 0.1 * rand() / (float)RAND_MAX + 0.15;
nuclear@5 68 mb.phase_offs = rand() / (float)RAND_MAX * M_PI * 2.0;
nuclear@5 69 balls.push_back(mb);
nuclear@5 70 }
nuclear@5 71
nuclear@11 72 evrise = dsys_event(demo, "mball_rise");
nuclear@11 73 dsys_set_event_eval(evrise, dsys_eval_sigmoid);
nuclear@11 74
nuclear@5 75 return true;
nuclear@5 76 }
nuclear@5 77
nuclear@9 78 void mball_render(float sec)
nuclear@5 79 {
nuclear@9 80 update(sec);
nuclear@5 81
nuclear@8 82 const float blue[] = {0.4, 0.45, 1.0, 1};
nuclear@8 83 const float dark_red[] = {0.6, 0.2, 0.1, 1};
nuclear@8 84 const float white[] = {1, 1, 1, 1};
nuclear@8 85 const float black[] = {0, 0, 0, 1};
nuclear@8 86
nuclear@5 87 glMatrixMode(GL_MODELVIEW);
nuclear@5 88 glPushMatrix();
nuclear@5 89 glScalef(4.0, 4.0, 4.0);
nuclear@5 90
nuclear@8 91 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
nuclear@8 92 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
nuclear@8 93 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0);
nuclear@8 94
nuclear@5 95 glBegin(GL_TRIANGLES);
nuclear@5 96 msurf_polygonize(msurf);
nuclear@5 97 glEnd();
nuclear@5 98
nuclear@8 99 // floor
nuclear@8 100 glBegin(GL_QUADS);
nuclear@8 101 glNormal3f(0, 1, 0);
nuclear@8 102 glVertex3f(-5, -1, 5);
nuclear@8 103 glVertex3f(5, -1, 5);
nuclear@8 104 glVertex3f(5, -1, -5);
nuclear@8 105 glVertex3f(-5, -1, -5);
nuclear@8 106 glEnd();
nuclear@8 107
nuclear@8 108 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, dark_red);
nuclear@8 109 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);
nuclear@8 110 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0);
nuclear@8 111
nuclear@8 112 // box
nuclear@8 113 glPushMatrix();
nuclear@8 114 glTranslatef(0, -1.7, 1);
nuclear@8 115 glScalef(1.05, 1, 0.05);
nuclear@8 116 glutSolidCube(2.0);
nuclear@8 117 glPopMatrix();
nuclear@8 118
nuclear@8 119 glPushMatrix();
nuclear@8 120 glTranslatef(0, -1.7, -1);
nuclear@8 121 glScalef(1.05, 1, 0.05);
nuclear@8 122 glutSolidCube(2.0);
nuclear@8 123 glPopMatrix();
nuclear@8 124
nuclear@8 125 glPushMatrix();
nuclear@8 126 glTranslatef(1, -1.7, 0);
nuclear@8 127 glScalef(0.05, 1, 1);
nuclear@8 128 glutSolidCube(2.0);
nuclear@8 129 glPopMatrix();
nuclear@8 130
nuclear@8 131 glPushMatrix();
nuclear@8 132 glTranslatef(-1, -1.7, 0);
nuclear@8 133 glScalef(0.05, 1, 1);
nuclear@8 134 glutSolidCube(2.0);
nuclear@8 135 glPopMatrix();
nuclear@8 136
nuclear@5 137 glPopMatrix();
nuclear@5 138 }
nuclear@5 139
nuclear@5 140
nuclear@9 141 static void update(float sec)
nuclear@5 142 {
nuclear@11 143 float trise = dsys_event_value(evrise);
nuclear@11 144
nuclear@5 145 for(size_t i=0; i<balls.size(); i++) {
nuclear@5 146 float t = sec + balls[i].phase_offs;
nuclear@12 147 balls[i].pos[0] = cos(t * 1.8) * balls[i].orbit;
nuclear@12 148 balls[i].pos[2] = sin(t * 1.2) * balls[i].orbit;
nuclear@12 149 balls[i].pos[1] = (sin(t) + cos(t * 2.0) / 2.0 + sin(t * 3.0) / 3.0) * 0.45 - (2.0 - trise * 2.0);
nuclear@5 150 }
nuclear@5 151
nuclear@5 152 for(int i=0; i<MBALL_GRID_SZ; i++) {
nuclear@5 153 float x = (float)i / (float)MBALL_GRID_SZ * 2.0 - 1.0;
nuclear@5 154 for(int j=0; j<MBALL_GRID_SZ; j++) {
nuclear@5 155 float y = (float)j / (float)MBALL_GRID_SZ * 2.0 - 1.0;
nuclear@5 156 for(int k=0; k<MBALL_GRID_SZ; k++) {
nuclear@5 157 float z = (float)k / (float)MBALL_GRID_SZ * 2.0 - 1.0;
nuclear@5 158 grid[i][j][k] = calc_field(x, y, z);
nuclear@5 159 }
nuclear@5 160 }
nuclear@5 161 }
nuclear@5 162 }
nuclear@5 163
nuclear@5 164 static float calc_field(float x, float y, float z)
nuclear@5 165 {
nuclear@5 166 float sum = 0.0f;
nuclear@5 167 for(size_t i=0; i<balls.size(); i++) {
nuclear@12 168 float dx = balls[i].pos[0] - x;
nuclear@12 169 float dy = balls[i].pos[1] - y;
nuclear@12 170 float dz = balls[i].pos[2] - z;
nuclear@12 171 float dist_sq = dx * dx + dy * dy + dz * dz;
nuclear@5 172 if(dist_sq > 1e-6) {
nuclear@5 173 sum += balls[i].energy / dist_sq;
nuclear@5 174 } else {
nuclear@5 175 sum += 1000.0;
nuclear@5 176 }
nuclear@5 177 }
nuclear@8 178
nuclear@8 179 // floor
nuclear@8 180 float height = y - floor_height;
nuclear@8 181 if(height > 1e-6) {
nuclear@8 182 sum += 1.0 / height;
nuclear@8 183 } else {
nuclear@8 184 sum += 1000.0;
nuclear@8 185 }
nuclear@8 186
nuclear@5 187 return sum;
nuclear@5 188 }
nuclear@5 189
nuclear@5 190 static inline int clamp(int x, int a, int b)
nuclear@5 191 {
nuclear@5 192 return x < a ? a : (x > b ? b : x);
nuclear@5 193 }
nuclear@5 194
nuclear@5 195 static float eval(float x, float y, float z)
nuclear@5 196 {
nuclear@5 197 int cell_x = clamp((int)((x / VOL_SZ + 0.5) * MBALL_GRID_SZ), 0, MBALL_GRID_SZ - 1);
nuclear@5 198 int cell_y = clamp((int)((y / VOL_SZ + 0.5) * MBALL_GRID_SZ), 0, MBALL_GRID_SZ - 1);
nuclear@5 199 int cell_z = clamp((int)((z / VOL_SZ + 0.5) * MBALL_GRID_SZ), 0, MBALL_GRID_SZ - 1);
nuclear@5 200
nuclear@5 201 return grid[cell_x][cell_y][cell_z];
nuclear@5 202 }
nuclear@5 203
nuclear@5 204 static void vertex(float x, float y, float z)
nuclear@5 205 {
nuclear@5 206 float delta = (float)VOL_SZ / (float)MBALL_GRID_SZ;
nuclear@5 207
nuclear@5 208 float dfdx = calc_field(x - delta, y, z) - calc_field(x + delta, y, z);
nuclear@5 209 float dfdy = calc_field(x, y - delta, z) - calc_field(x, y + delta, z);
nuclear@5 210 float dfdz = calc_field(x, y, z - delta) - calc_field(x, y, z + delta);
nuclear@5 211
nuclear@5 212 float len = sqrt(dfdx * dfdx + dfdy * dfdy + dfdz * dfdz);
nuclear@5 213
nuclear@5 214 glNormal3f(dfdx / len, dfdy / len, dfdz / len);
nuclear@5 215 glVertex3f(x, y, z);
nuclear@5 216 }
nuclear@5 217
nuclear@5 218 static void normal(float x, float y, float z)
nuclear@5 219 {
nuclear@5 220 glNormal3f(x, y, z);
nuclear@5 221 }