19 static int init(void);
20 static void destroy(void);
21 static void start(long trans_time);
22 static void draw(void);
24 static void calc_voxel_field(void);
26 static struct screen scr = {
34 static float cam_theta, cam_phi = 25;
35 static float cam_dist = 10;
36 static struct g3d_mesh mmesh;
38 static struct metasurface *msurf;
41 #define VOL_SCALE 10.0f
42 #define VOX_DIST (VOL_SCALE / VOL_SZ)
43 #define VOL_HALF_SCALE (VOL_SCALE * 0.5f)
46 static struct metaball mball[NUM_MBALLS];
50 struct screen *metaballs_screen(void)
57 mball[0].energy = 1.2;
58 mball[1].energy = 0.8;
59 mball[2].energy = 1.0;
61 if(!(msurf = msurf_create())) {
62 fprintf(stderr, "failed to initialize metasurf\n");
65 msurf_set_resolution(msurf, VOL_SZ, VOL_SZ, VOL_SZ);
66 msurf_set_bounds(msurf, -VOL_HALF_SCALE, -VOL_HALF_SCALE, -VOL_HALF_SCALE,
67 VOL_HALF_SCALE, VOL_HALF_SCALE, VOL_HALF_SCALE);
68 msurf_set_threshold(msurf, 1.7);
69 msurf_set_inside(msurf, MSURF_GREATER);
71 mmesh.prim = G3D_TRIANGLES;
74 mmesh.vcount = mmesh.icount = 0;
79 static void destroy(void)
84 static void start(long trans_time)
86 g3d_matrix_mode(G3D_PROJECTION);
88 g3d_perspective(50.0, 1.3333333, 0.5, 100.0);
90 g3d_enable(G3D_CULL_FACE);
91 g3d_enable(G3D_LIGHTING);
92 g3d_enable(G3D_LIGHT0);
94 g3d_polygon_mode(G3D_GOURAUD);
97 static void update(void)
100 float tsec = time_msec / 1000.0f;
101 static float phase[] = {0.0, M_PI / 3.0, M_PI * 0.8};
102 static float speed[] = {0.8, 1.4, 1.0};
103 static float scale[][3] = {{1, 2, 0.8}, {0.5, 1.6, 0.6}, {1.5, 0.7, 0.5}};
104 static float offset[][3] = {{0, 0, 0}, {0.25, 0, 0}, {-0.2, 0.15, 0.2}};
106 mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
108 for(i=0; i<NUM_MBALLS; i++) {
109 float t = (tsec + phase[i]) * speed[i];
112 float x = sin(t + j * M_PI / 2.0);
113 mball[i].pos[j] = offset[i][j] + x * scale[i][j];
118 msurf_polygonize(msurf);
120 mmesh.vcount = msurf_vertex_count(msurf);
121 mmesh.varr = msurf_vertices(msurf);
124 static void draw(void)
130 memset(fb_pixels, 0, FB_WIDTH * FB_HEIGHT * 2);
132 for(i=0; i<120; i++) {
133 for(j=0; j<160; j++) {
134 fb_pixels[(i + 60) * 320 + (j + 80)] = 0x1e7;
137 g3d_viewport(80, 60, 160, 120);
139 g3d_matrix_mode(G3D_MODELVIEW);
141 g3d_translate(0, 0, -cam_dist);
142 g3d_rotate(cam_phi, 1, 0, 0);
143 g3d_rotate(cam_theta, 0, 1, 0);
145 g3d_light_pos(0, -10, 10, 20);
149 g3d_mtl_diffuse(0.6, 0.6, 0.6);
153 g3d_viewport(0, 0, FB_WIDTH, FB_HEIGHT);
155 swap_buffers(fb_pixels);
158 static void calc_voxel_field(void)
163 if(!(voxptr = msurf_voxels(msurf))) {
164 fprintf(stderr, "failed to allocate voxel field\n");
168 for(i=0; i<VOL_SZ; i++) {
169 float z = -VOL_HALF_SCALE + i * VOX_DIST;
171 for(j=0; j<VOL_SZ; j++) {
172 float y = -VOL_HALF_SCALE + j * VOX_DIST;
174 for(k=0; k<VOL_SZ; k++) {
175 float x = -VOL_HALF_SCALE + k * VOX_DIST;
178 for(b=0; b<NUM_MBALLS; b++) {
179 float dx = mball[b].pos[0] - x;
180 float dy = mball[b].pos[1] - y;
181 float dz = mball[b].pos[2] - z;
183 float lensq = dx * dx + dy * dy + dz * dz;
185 val += lensq == 0.0f ? 1024.0f : mball[b].energy / lensq;