crude metaballs
[metatoy] / src / game.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <math.h>
4 #include "game.h"
5 #include "colormgr.h"
6 #include "3dgfx.h"
7 #include "mesh.h"
8 #include "metasurf.h"
9 #include "util.h"
10
11 #define BBOX_SIZE               10.0f
12 #define BBOX_HSZ                (BBOX_SIZE / 2.0f)
13 #define VOX_RES                 30
14 #define VOX_STEP                (BBOX_SIZE / (float)VOX_RES)
15
16 #define VBUF_MAX_TRIS   256
17 #define VBUF_SIZE               (VBUF_MAX_TRIS * 3)
18
19 struct mball {
20         float energy;
21         float x, y, z;
22 };
23
24 static struct g3d_mesh mesh;
25 static struct g3d_vertex *vbuf;
26 static struct metasurface *msurf;
27 static struct mball *balls;
28 static int num_balls;
29
30 static void update(float tsec);
31 static void draw_metaballs(void);
32
33 int game_init(void)
34 {
35         int i;
36
37         init_colormgr();
38
39         g3d_init();
40         g3d_framebuffer(320, 200, framebuf);
41         g3d_viewport(0, 0, 320, 200);
42
43         g3d_clear_color(0, 0, 0);
44
45         g3d_matrix_mode(G3D_PROJECTION);
46         g3d_load_identity();
47         g3d_perspective(50.0f, 1.33333, 0.5, 500.0);
48
49         g3d_enable(G3D_CULL_FACE);
50         g3d_enable(G3D_DEPTH_TEST);
51         g3d_enable(G3D_LIGHTING);
52         g3d_enable(G3D_LIGHT0);
53
54         g3d_polygon_mode(G3D_GOURAUD);
55
56         gen_torus_mesh(&mesh, 2.0, 0.7, 24, 12);
57
58         if(!(msurf = msurf_create())) {
59                 return -1;
60         }
61         msurf_set_threshold(msurf, 8);
62         msurf_set_inside(msurf, MSURF_GREATER);
63         msurf_set_bounds(msurf, -BBOX_HSZ, -BBOX_HSZ, -BBOX_HSZ, BBOX_HSZ, BBOX_HSZ, BBOX_HSZ);
64         msurf_set_resolution(msurf, VOX_RES, VOX_RES, VOX_RES);
65         msurf_enable(msurf, MSURF_NORMALIZE);
66
67         vbuf = malloc_nf(VBUF_SIZE * sizeof *vbuf);
68
69         num_balls = 1;
70         balls = calloc_nf(num_balls, sizeof *balls);
71
72         for(i=0; i<num_balls; i++) {
73                 balls[i].energy = 20;
74         }
75         return 0;
76 }
77
78 void game_shutdown(void)
79 {
80 }
81
82 static void update(float tsec)
83 {
84         int i, j, k, n;
85         float x, y, z, dx, dy, dz, dsq, energy;
86         float *vox = msurf_voxels(msurf);
87
88         for(i=0; i<num_balls; i++) {
89                 balls[i].y = sin(tsec) * 5.0f;
90         }
91
92         for(i=0; i<VOX_RES; i++) {
93                 z = -BBOX_HSZ + i * VOX_STEP;
94                 for(j=0; j<VOX_RES; j++) {
95                         y = -BBOX_HSZ + j * VOX_STEP;
96                         for(k=0; k<VOX_RES; k++) {
97                                 x = -BBOX_HSZ + k * VOX_STEP;
98
99                                 /* initialize with the vertical distance for the pool */
100                                 energy = BBOX_HSZ * 0.8 - y;
101
102                                 /* add the contribution of the balls */
103                                 for(n=0; n<num_balls; n++) {
104                                         dx = x - balls[n].x;
105                                         dy = y - balls[n].y;
106                                         dz = z - balls[n].z;
107                                         dsq = dx * dx + dy * dy + dz * dz;
108
109                                         energy += balls[n].energy / dsq;
110                                 }
111                                 *vox++ = energy;
112                         }
113                 }
114         }
115
116         msurf_polygonize(msurf);
117 }
118
119 void game_draw(void)
120 {
121         unsigned long msec = game_getmsec();
122         float tsec = (float)msec / 1000.0f;
123
124         update(tsec);
125
126         g3d_clear(G3D_COLOR_BUFFER_BIT | G3D_DEPTH_BUFFER_BIT);
127
128         g3d_matrix_mode(G3D_MODELVIEW);
129         g3d_load_identity();
130         g3d_translate(0, 0, -15);
131         /*g3d_rotate(tsec * 50.0f, 1, 0, 0);
132         g3d_rotate(tsec * 30.0f, 0, 0, 1);
133
134         draw_mesh(&mesh);*/
135         draw_metaballs();
136
137         game_swap_buffers();
138 }
139
140 static void draw_metaballs(void)
141 {
142         int i, nverts, vbuf_count;
143         float *varr, *narr;
144         struct g3d_vertex *vbptr;
145         static int nfrm;
146
147         nverts = msurf_vertex_count(msurf);
148         varr = msurf_vertices(msurf);
149         narr = msurf_normals(msurf);
150
151         vbptr = vbuf;
152         for(i=0; i<nverts; i++) {
153                 vbuf_count = vbptr - vbuf;
154                 if(vbuf_count >= VBUF_SIZE) {
155                         g3d_draw(G3D_TRIANGLES, vbuf, vbuf_count);
156                         vbptr = vbuf;
157                 }
158                 vbptr->x = varr[0];
159                 vbptr->y = varr[1];
160                 vbptr->z = varr[2];
161                 vbptr->w = 1.0f;
162                 vbptr->nx = narr[0];
163                 vbptr->ny = narr[1];
164                 vbptr->nz = narr[2];
165                 vbptr->w = 1.0f;
166                 vbptr->l = 255;
167                 vbptr++;
168                 varr += 3;
169                 narr += 3;
170         }
171
172         if(vbptr > vbuf) {
173                 g3d_draw(G3D_TRIANGLES, vbuf, vbptr - vbuf);
174         }
175
176         nfrm++;
177 }
178
179 void game_keyboard(int key, int press)
180 {
181         if(key == 27) game_quit();
182 }
183
184 void game_mouse(int bn, int press, int x, int y)
185 {
186 }
187
188 void game_motion(int x, int y)
189 {
190 }