transitions for both shapes
[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 #include "cgmath/cgmath.h"
11 #include "metaobj.h"
12
13
14 #define BBOX_HXSZ               (BBOX_XSZ / 2.0f)
15 #define BBOX_HYSZ               (BBOX_YSZ / 2.0f)
16 #define BBOX_HZSZ               (BBOX_ZSZ / 2.0f)
17 #define VOX_XRES                (VOX_RES * BBOX_XSZ / BBOX_ZSZ)
18 #define VOX_YRES                (VOX_RES * BBOX_YSZ / BBOX_ZSZ)
19 #define VOX_ZRES                VOX_RES
20 #define VOX_XSTEP               (BBOX_XSZ / (float)VOX_XRES)
21 #define VOX_YSTEP               (BBOX_YSZ / (float)VOX_YRES)
22 #define VOX_ZSTEP               (BBOX_ZSZ / (float)VOX_ZRES)
23
24 #define VBUF_MAX_TRIS   256
25 #define VBUF_SIZE               (VBUF_MAX_TRIS * 3)
26
27 unsigned long time_msec;
28
29 static struct g3d_vertex *vbuf;
30 static struct metasurface *msurf;
31 static struct mobject **mobjects, *mobj;
32
33 #define NUM_OBJ         2
34 static int num_mobj, cur_obj;
35
36 static int mousebn[3];
37 static int mousex, mousey;
38 static float cam_theta, cam_phi;
39
40 extern unsigned char textures_img[];
41 extern unsigned char textures_cmap[];
42 extern unsigned char textures_slut[];
43
44
45 static void update(float tsec);
46 static void draw_metaballs(void);
47
48
49 int game_init(void)
50 {
51         init_colormgr();
52         load_colormap(0, 256, textures_cmap, textures_slut);
53
54         g3d_init();
55         g3d_framebuffer(FB_WIDTH, FB_HEIGHT, framebuf);
56         g3d_viewport(0, 0, FB_WIDTH, FB_HEIGHT);
57
58         g3d_clear_color(0);
59
60         g3d_matrix_mode(G3D_PROJECTION);
61         g3d_load_identity();
62         g3d_perspective(60.0f, 1.33333, 0.5, 500.0);
63
64         g3d_enable(G3D_CULL_FACE);
65         g3d_enable(G3D_DEPTH_TEST);
66         g3d_enable(G3D_LIGHTING);
67         g3d_enable(G3D_LIGHT0);
68         g3d_light_ambient(0.2);
69
70         g3d_polygon_mode(G3D_GOURAUD);
71
72         if(!(msurf = msurf_create())) {
73                 return -1;
74         }
75         msurf_set_threshold(msurf, 8);
76         msurf_set_inside(msurf, MSURF_GREATER);
77         msurf_set_bounds(msurf, -BBOX_HXSZ, -BBOX_HYSZ, -BBOX_HZSZ, BBOX_HXSZ, BBOX_HYSZ, BBOX_HZSZ);
78         msurf_set_resolution(msurf, VOX_XRES, VOX_YRES, VOX_ZRES);
79         msurf_enable(msurf, MSURF_NORMALIZE);
80
81         vbuf = malloc_nf(VBUF_SIZE * sizeof *vbuf);
82
83         num_mobj = NUM_OBJ;
84         mobjects = malloc(num_mobj * sizeof *mobj);
85         mobjects[0] = metaobj_sflake();
86         mobjects[1] = metaobj_sgi();
87         cur_obj = 0;
88         mobj = mobjects[cur_obj];
89         return 0;
90 }
91
92 void game_shutdown(void)
93 {
94 }
95
96 static void update(float tsec)
97 {
98         int i, j, k;
99         float energy;
100         cgm_vec3 pos;
101         float *vox = msurf_voxels(msurf);
102
103         mobjects[cur_obj]->update(mobjects[cur_obj], tsec);
104
105         for(i=0; i<VOX_ZRES; i++) {
106                 pos.z = -BBOX_HZSZ + i * VOX_ZSTEP;
107                 for(j=0; j<VOX_YRES; j++) {
108                         pos.y = -BBOX_HYSZ + j * VOX_YSTEP;
109                         for(k=0; k<VOX_XRES; k++) {
110                                 pos.x = -BBOX_HXSZ + k * VOX_XSTEP;
111
112                                 /* initialize with the vertical distance for the pool */
113                                 energy = 5.0 / (pos.y + BBOX_HYSZ);
114                                 /*energy += 5.0 / (pos.x + BBOX_HXSZ);
115                                 energy += 5.0 / (BBOX_HXSZ - pos.x);*/
116
117                                 energy += mobj->eval(mobj, &pos);
118
119                                 *vox++ = energy;
120                         }
121                 }
122         }
123
124         msurf_polygonize(msurf);
125 }
126
127 void game_draw(void)
128 {
129         float tsec;
130
131         time_msec = game_getmsec();
132         tsec = (float)time_msec / 1000.0f;
133
134         update(tsec);
135
136         g3d_clear(G3D_COLOR_BUFFER_BIT | G3D_DEPTH_BUFFER_BIT);
137
138         g3d_matrix_mode(G3D_MODELVIEW);
139         g3d_load_identity();
140         g3d_translate(0, 1, -14);
141         g3d_rotate(cam_phi, 1, 0, 0);
142         g3d_rotate(cam_theta, 0, 1, 0);
143
144         g3d_disable(G3D_LIGHTING);
145         g3d_enable(G3D_TEXTURE_2D);
146         g3d_enable(G3D_TEXTURE_GEN);
147         g3d_set_texture(32, 32, textures_img);
148         draw_metaballs();
149         g3d_disable(G3D_TEXTURE_GEN);
150         g3d_enable(G3D_LIGHTING);
151
152         game_swap_buffers();
153 }
154
155 static void draw_metaballs(void)
156 {
157         int i, nverts, vbuf_count;
158         float *varr, *narr;
159         struct g3d_vertex *vbptr;
160
161         nverts = msurf_vertex_count(msurf);
162         varr = msurf_vertices(msurf);
163         narr = msurf_normals(msurf);
164
165         vbptr = vbuf;
166         for(i=0; i<nverts; i++) {
167                 vbuf_count = vbptr - vbuf;
168                 if(vbuf_count >= VBUF_SIZE) {
169                         g3d_draw(G3D_TRIANGLES, vbuf, vbuf_count);
170                         vbptr = vbuf;
171                 }
172                 vbptr->x = varr[0];
173                 vbptr->y = varr[1];
174                 vbptr->z = varr[2];
175                 vbptr->w = 1.0f;
176                 vbptr->nx = narr[0];
177                 vbptr->ny = narr[1];
178                 vbptr->nz = narr[2];
179                 vbptr->w = 1.0f;
180                 vbptr->l = 255;
181                 vbptr++;
182                 varr += 3;
183                 narr += 3;
184         }
185
186         if(vbptr > vbuf) {
187                 g3d_draw(G3D_TRIANGLES, vbuf, vbptr - vbuf);
188         }
189 }
190
191 void game_keyboard(int key, int press)
192 {
193         if(key == 27) game_quit();
194 }
195
196 void game_mouse(int bn, int press, int x, int y)
197 {
198         mousebn[bn] = press;
199         mousex = x;
200         mousey = y;
201
202         if(bn == 0) {
203                 if(press) {
204                         if(y > 3 * FB_HEIGHT / 4) {
205                                 mobj->swstate(mobj, MOBJ_GRABING);
206                         }
207                 } else {
208                         mobj->swstate(mobj, MOBJ_DROPPING);
209                 }
210         }
211 }
212
213 void game_motion(int x, int y)
214 {
215         int dx = x - mousex;
216         int dy = y - mousey;
217         mousex = x;
218         mousey = y;
219
220         if((dx | dy) == 0) return;
221
222         if(mousebn[0]) {
223                 mobj->pos.x += dx * 0.1;
224                 mobj->pos.y -= dy * 0.1;
225         }
226         if(mousebn[2]) {
227                 cam_theta += (float)dx * (0.6f * 1.333333333f);
228                 cam_phi += (float)dy * 0.6f;
229                 if(cam_phi < -90) cam_phi = -90;
230                 if(cam_phi > 90) cam_phi = 90;
231         }
232 }