initial commit
[liquidmodel] / src / demo.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <cgmath/cgmath.h>
5 #include "demo.h"
6 #include "opengl.h"
7 #include "sanegl.h"
8 #include "sdr.h"
9 #include "assman.h"
10 #include "cmesh.h"
11 #include "music.h"
12 #include "metasurf.h"
13 #include "metaobj.h"
14
15
16 #define BBOX_HXSZ               (BBOX_XSZ / 2.0f)
17 #define BBOX_HYSZ               (BBOX_YSZ / 2.0f)
18 #define BBOX_HZSZ               (BBOX_ZSZ / 2.0f)
19
20 #define VBUF_MAX_TRIS   512
21 #define VBUF_COUNT              (VBUF_MAX_TRIS * 3)
22
23
24 static void set_voxel_res(int sz);
25 static void draw_metaballs(void);
26 static void gen_default_textures(void);
27
28 static unsigned int sdr_foo;
29 static unsigned int tex_logo;
30 static int prev_mx, prev_my;
31
32 static int vox_res, vox_xres, vox_yres, vox_zres;
33 static float vox_xstep, vox_ystep, vox_zstep;
34
35 static struct metasurface *msurf;
36 static struct mobject *mobj;
37
38 static int mousebn[3];
39 static int mousex, mousey;
40 static float cam_theta, cam_phi;
41
42 static unsigned int metavbo[2];
43 static int cur_metavbo;
44
45
46 int demo_init(void)
47 {
48         int i;
49
50         if(init_opengl() == -1) {
51                 return -1;
52         }
53         if(init_assman() == -1) {
54                 return -1;
55         }
56
57         if(init_music() == -1) {
58                 return -1;
59         }
60
61         /* global "debug" shader which just visualizes normals */
62         if(!(sdr_dbg = get_sdrprog("sdr/dbg.v.glsl", "sdr/dbg.p.glsl"))) {
63                 return -1;
64         }
65         cmesh_bind_sdrloc(sdr_dbg);
66
67         gen_default_textures();
68
69         if(!(sdr_foo = get_sdrprog("sdr/foo.v.glsl", "sdr/foo.p.glsl"))) {
70                 return -1;
71         }
72         if(!(tex_logo = get_tex2d("data/ml_logo_old.png"))) {
73                 return -1;
74         }
75         glBindTexture(GL_TEXTURE_2D, tex_logo);
76         glUseProgram(sdr_foo);
77         gl_begin(GL_QUADS);
78         gl_color3f(1, 1, 1);
79         gl_texcoord2f(0, 1);
80         gl_vertex2f(-1, -1);
81         gl_texcoord2f(1, 1);
82         gl_vertex2f(1, -1);
83         gl_texcoord2f(1, 0);
84         gl_vertex2f(1, 1);
85         gl_texcoord2f(0, 0);
86         gl_vertex2f(-1, 1);
87         gl_end();
88         swap_buffers();
89
90         glEnable(GL_CULL_FACE);
91         glEnable(GL_DEPTH_TEST);
92
93
94         vox_res = DEF_VOX_RES;
95         if(!(msurf = msurf_create())) {
96                 return -1;
97         }
98         msurf_set_threshold(msurf, 8);
99         msurf_set_inside(msurf, MSURF_GREATER);
100         msurf_set_bounds(msurf, -BBOX_HXSZ, -BBOX_HYSZ, -BBOX_HZSZ, BBOX_HXSZ, BBOX_HYSZ, BBOX_HZSZ);
101         set_voxel_res(vox_res);
102         msurf_enable(msurf, MSURF_NORMALIZE);
103
104         glGenBuffers(2, metavbo);
105         for(i=0; i<2; i++) {
106                 glBindBuffer(GL_ARRAY_BUFFER, metavbo[i]);
107                 glBufferData(GL_ARRAY_BUFFER, VBUF_COUNT * 6 * sizeof(float), 0, GL_STREAM_DRAW);
108         }
109
110         mobj = malloc(sizeof *mobj);
111         mobj = metaobj_sflake();
112
113         return 0;
114 }
115
116 void demo_cleanup(void)
117 {
118         glDeleteBuffers(2, metavbo);
119
120         destroy_music();
121         destroy_assman();
122
123         glDeleteTextures(1, &deftex_white);
124         glDeleteTextures(1, &deftex_black);
125         glDeleteTextures(1, &deftex_normal);
126 }
127
128 static void set_voxel_res(int sz)
129 {
130         vox_res = sz;
131         vox_xres = vox_res * BBOX_XSZ / BBOX_ZSZ;
132         vox_yres = vox_res * BBOX_YSZ / BBOX_ZSZ;
133         vox_zres = vox_res;
134         vox_xstep = (float)BBOX_XSZ / (float)vox_xres;
135         vox_ystep = (float)BBOX_YSZ / (float)vox_yres;
136         vox_zstep = (float)BBOX_ZSZ / (float)vox_zres;
137
138         if(msurf) {
139                 msurf_set_resolution(msurf, vox_xres, vox_yres, vox_zres);
140         }
141 }
142
143 static void update(float tsec)
144 {
145         int i, j, k;
146         float energy;
147         cgm_vec3 pos;
148         float *vox = msurf_voxels(msurf);
149
150         mobj->update(mobj, tsec);
151
152         for(i=0; i<vox_zres; i++) {
153                 pos.z = -BBOX_HZSZ + i * vox_zstep;
154                 for(j=0; j<vox_yres; j++) {
155                         pos.y = -BBOX_HYSZ + j * vox_ystep;
156                         for(k=0; k<vox_xres; k++) {
157                                 pos.x = -BBOX_HXSZ + k * vox_xstep;
158
159                                 /* initialize with the vertical distance for the pool */
160                                 energy = 5.0 / (pos.y + BBOX_HYSZ);
161                                 /*energy += 5.0 / (pos.x + BBOX_HXSZ);
162                                 energy += 5.0 / (BBOX_HXSZ - pos.x);*/
163
164                                 energy += mobj->eval(mobj, &pos);
165
166                                 *vox++ = energy;
167                         }
168                 }
169         }
170
171         msurf_polygonize(msurf);
172 }
173
174 void demo_display(void)
175 {
176         float tsec;
177
178         time_msec = sys_time - start_time;
179         tsec = (float)time_msec / 1000.0f;
180
181         update(tsec);
182
183         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
184
185         gl_matrix_mode(GL_MODELVIEW);
186         gl_load_identity();
187         gl_translatef(0, 1, -18);
188         gl_rotatef(cam_phi, 1, 0, 0);
189         gl_rotatef(cam_theta, 0, 1, 0);
190
191         gl_push_matrix();
192         gl_translatef(0.5f * BBOX_XSZ / vox_xres, 0, 0.5f * BBOX_ZSZ / vox_zres);
193         draw_metaballs();
194         gl_pop_matrix();
195
196 }
197
198 static void draw_metaballs(void)
199 {
200         int nverts, vcount, szbytes;
201         float *varr, *narr;
202         static int vloc = -1, nloc;
203
204         bind_program(sdr_dbg);
205         gl_apply_xform(sdr_dbg);
206
207         if(vloc == -1) {
208                 if((vloc = glGetAttribLocation(sdr_dbg, "attr_vertex")) == -1) {
209                         return;
210                 }
211                 nloc = glGetAttribLocation(sdr_dbg, "attr_normal");
212         }
213
214         nverts = msurf_vertex_count(msurf);
215         varr = msurf_vertices(msurf);
216         narr = msurf_normals(msurf);
217
218         glEnableVertexAttribArray(vloc);
219         glEnableVertexAttribArray(nloc);
220
221         while(nverts > 0) {
222                 vcount = nverts > VBUF_COUNT ? VBUF_COUNT : nverts;
223                 nverts -= vcount;
224                 szbytes = vcount * 3 * sizeof(float);
225
226                 glBindBuffer(GL_ARRAY_BUFFER, metavbo[cur_metavbo]);
227                 cur_metavbo = (cur_metavbo + 1) & 1;
228                 glBufferSubData(GL_ARRAY_BUFFER, 0, szbytes, varr);
229                 glBufferSubData(GL_ARRAY_BUFFER, szbytes, szbytes, narr);
230                 varr += vcount * 3;
231                 narr += vcount * 3;
232
233                 glVertexAttribPointer(vloc, 3, GL_FLOAT, 0, 0, 0);
234                 glVertexAttribPointer(nloc, 3, GL_FLOAT, 0, 0, (void*)(intptr_t)szbytes);
235
236                 glDrawArrays(GL_TRIANGLES, 0, vcount);
237         }
238
239         glDisableVertexAttribArray(vloc);
240         glDisableVertexAttribArray(nloc);
241 }
242
243 void demo_reshape(int x, int y)
244 {
245         glViewport(0, 0, x, y);
246         win_width = x;
247         win_height = y;
248         win_aspect = (float)x / (float)y;
249
250         gl_matrix_mode(GL_PROJECTION);
251         gl_load_identity();
252         glu_perspective(50.0, win_aspect, 0.5, 500.0);
253 }
254
255 void demo_keyboard(int key, int pressed)
256 {
257         if(!pressed) return;
258 }
259
260 void demo_mouse(int bn, int pressed, int x, int y)
261 {
262         mousebn[bn] = pressed;
263         mousex = x;
264         mousey = y;
265
266         if(bn == 0) {
267                 if(pressed) {
268                         if(y > 3 * win_height / 4) {
269                                 mobj->swstate(mobj, MOBJ_GRABING);
270                         }
271                 } else {
272                         mobj->swstate(mobj, MOBJ_DROPPING);
273                 }
274         }
275 }
276
277 void demo_motion(int x, int y)
278 {
279         float u, v;
280         int dx, dy;
281
282         dx = x - prev_mx;
283         dy = y - prev_my;
284         prev_mx = x;
285         prev_my = y;
286
287         if(!(dx | dy)) {
288                 return;
289         }
290
291         if(mousebn[0]) {
292                 mobj->pos.x += dx * 0.03;
293                 mobj->pos.y -= dy * 0.03;
294         }
295
296         u = (float)x / (float)win_width;
297         v = (float)y / (float)win_height;
298         cam_theta = cgm_lerp(-15, 15, u);
299         cam_phi = cgm_lerp(-10, 25, v);
300 }
301
302 static void gen_default_textures(void)
303 {
304         static const uint32_t col[] = {0xff000000, 0xffffffff, 0xffff7f7f};
305         int i;
306         unsigned int tex[3];
307
308         glGenTextures(3, tex);
309         for(i=0; i<3; i++) {
310                 glBindTexture(GL_TEXTURE_2D, tex[i]);
311                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
312                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
313                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, col + i);
314         }
315
316         deftex_black = tex[0];
317         deftex_white = tex[1];
318         deftex_normal = tex[2];
319 }