5e9f213cd9b972a41dad8e9438313574a37ac5fa
[laserbrain_demo] / src / blob_exhibit.cc
1 #include "blob_exhibit.h"
2 #include "blobs/metasurf.h"
3 #include "app.h"
4
5 struct Metaball {
6         Vec3 pos;
7         float energy;
8         Vec3 path_scale, path_offset;
9         float phase_offset, speed;
10 };
11 #define NUM_MBALLS      8
12
13 static Metaball def_mball_data[] = {
14         {Vec3(0, 0, 0), 2.18038,  Vec3(1.09157, 1.69766, 1),   Vec3(0.622818, 0.905624, 0), 1.24125, 0.835223},
15         {Vec3(0, 0, 0), 2.03646,  Vec3(0.916662, 1.2161, 1),   Vec3(0.118734, 0.283516, 0), 2.29201, 1.0134},
16         {Vec3(0, 0, 0), 2.40446,  Vec3(1.87429, 1.57595, 1),   Vec3(0.298566, -0.788474, 0), 3.8137, 0.516301},
17         {Vec3(0, 0, 0), 0.985774, Vec3(0.705847, 0.735019, 1), Vec3(0.669189, -0.217922, 0), 0.815497, 0.608809},
18         {Vec3(0, 0, 0), 2.49785,  Vec3(0.827385, 1.75867, 1),  Vec3(0.0284513, 0.247808, 0), 1.86002, 1.13755},
19         {Vec3(0, 0, 0), 1.54857,  Vec3(1.24037, 0.938775, 1),  Vec3(1.04011, 0.596987, 0), 3.30964, 1.26991},
20         {Vec3(0, 0, 0), 1.30046,  Vec3(1.83729, 1.02869, 1),   Vec3(-0.476708, 0.676994, 0), 5.77441, 0.569755},
21         {Vec3(0, 0, 0), 2.39865,  Vec3(1.28899, 0.788321, 1),  Vec3(-0.910677, 0.359099, 0), 5.5935, 0.848893}
22 };
23
24 struct BlobPriv {
25         metasurface *msurf;
26         Metaball mballs[NUM_MBALLS];
27         Texture *tex;
28 };
29
30 static void vertex(struct metasurface *ms, float x, float y, float z);
31 static float eval(struct metasurface *ms, float x, float y, float z);
32
33
34 BlobExhibit::BlobExhibit()
35 {
36         priv = new BlobPriv;
37         for(int i=0; i<NUM_MBALLS; i++) {
38                 priv->mballs[i] = def_mball_data[i];
39         }
40 }
41
42 BlobExhibit::~BlobExhibit()
43 {
44         destroy();
45         delete priv;
46 }
47
48 bool BlobExhibit::init()
49 {
50         if(!(priv->msurf = msurf_create())) {
51                 return false;
52         }
53         msurf_set_user_data(priv->msurf, priv);
54         msurf_set_threshold(priv->msurf, 8);
55         msurf_set_inside(priv->msurf, MSURF_GREATER);
56         msurf_set_bounds(priv->msurf, -3.5, 3.5, -3.5, 3.5, -3.5, 3.5);
57         msurf_eval_func(priv->msurf, eval);
58         msurf_vertex_func(priv->msurf, vertex);
59
60         priv->tex = texman.get_texture("data/sphmap.jpg");
61         return true;
62 }
63
64 void BlobExhibit::destroy()
65 {
66         if(priv->msurf) {
67                 msurf_free(priv->msurf);
68                 priv->msurf = 0;
69         }
70 }
71
72 void BlobExhibit::update(float dt)
73 {
74         double sec = time_msec / 1000.0;
75
76         for(int i=0; i<NUM_MBALLS; i++) {
77                 float t = fmod(sec * priv->mballs[i].speed + priv->mballs[i].phase_offset, M_PI * 2.0);
78                 priv->mballs[i].pos.x = cos(t) * priv->mballs[i].path_scale.x + priv->mballs[i].path_offset.x;
79                 priv->mballs[i].pos.y = sin(t) * priv->mballs[i].path_scale.y + priv->mballs[i].path_offset.y;
80                 priv->mballs[i].pos.z = -cos(t) * priv->mballs[i].path_scale.z + priv->mballs[i].path_offset.z;
81         }
82 }
83
84 void BlobExhibit::draw() const
85 {
86         pre_draw();
87
88         glPushAttrib(GL_ENABLE_BIT);
89
90         glUseProgram(0);
91
92         glDisable(GL_LIGHTING);
93         glEnable(GL_TEXTURE_2D);
94         priv->tex->bind();
95
96         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
97         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
98         glEnable(GL_TEXTURE_GEN_S);
99         glEnable(GL_TEXTURE_GEN_T);
100
101         glMatrixMode(GL_TEXTURE);
102         glLoadIdentity();
103         glScalef(1, -1, 1);
104
105         glFrontFace(GL_CW);
106         glBegin(GL_TRIANGLES);
107         glColor3f(1, 1, 1);
108         msurf_polygonize(priv->msurf);
109         glEnd();
110         glFrontFace(GL_CCW);
111
112         glLoadIdentity();
113         glMatrixMode(GL_MODELVIEW);
114
115         glPopAttrib();
116
117         post_draw();
118 }
119
120 static void vertex(struct metasurface *ms, float x, float y, float z)
121 {
122         static const float delta = 0.01;
123
124         float val = eval(ms, x, y, z);
125         float dfdx = eval(ms, x + delta, y, z) - val;
126         float dfdy = eval(ms, x, y + delta, z) - val;
127         float dfdz = eval(ms, x, y, z + delta) - val;
128
129         glNormal3f(dfdx, dfdy, dfdz);
130         glVertex3f(x, y, z);
131 }
132
133 static float eval(struct metasurface *ms, float x, float y, float z)
134 {
135         float sum = 0.0f;
136         BlobPriv *priv = (BlobPriv*)msurf_get_user_data(ms);
137
138         for(int i=0; i<NUM_MBALLS; i++) {
139                 float dx = x - priv->mballs[i].pos.x;
140                 float dy = y - priv->mballs[i].pos.y;
141                 float dz = z - priv->mballs[i].pos.z;
142                 float dsq = dx * dx + dy * dy + dz * dz;
143
144                 sum += priv->mballs[i].energy / dsq;
145         }
146         return sum;
147 }