Attachment 'gs11.c'
Download 1 // gs11.c
2 // gcc -o gs11 gs11.c -lgd -lpng -lm
3 #define NAME "gs11"
4
5 #define V 10 // tesselation size , 1002 elements
6
7 // NM sets the array sizes - a smarter person would use a malloc()
8 #define NM 580 // max tesselation size, 3,600,002 elements
9 #define XSIZE 480 // Y screen size (0=left, 1023=right)
10 #define YSIZE 540 // Y screen size (0=top, 599=bottom)
11 #define Y0CENT 30 // Y center of small top image
12 #define Y1CENT 100 // Y center of small front image
13 #define YTCENT 240 // Y center of time text
14 #define X0CENT 300 // X center top images
15 #define X1CENT 400 // X center top images
16 #define YBCENT 350 // Y center of big bottom image
17 #define XBCENT 240 // X center of big bottom image
18 #define SIZE 6 // size of spot
19 #define SPACE 160 // scaling of big drawing
20
21 // note - these are applied to the display, not the stored
22 // geodesic sphere display, which is always scaled to unity
23
24 #define XEXP 1.2 // expand array in x (orbital) direction
25 #define YEXP 1.0 // expand array in y (NS) direction
26 #define ZEXP 0.2 // expand array in z (radial) direction
27
28 // turn the array just a bit, so objects in back are visible past those
29 // in front
30 #define XZROTATE 0.01
31
32 #define ASKEW 2.0 // apogee skew
33
34 #define NPICS 240 // number of images in animation
35 #define RATE 10 // images per second
36 #define ESIZE 80 // diameter of earth disk
37 #define ORBSIZE 80 // radius of orbit
38 #define ZFACTR 0.2 // scaling for items in back
39 #define ASCALE 12 // earth orbiting arrow scale
40 #define OSCALE 0.125 // earth orbiting scale
41 #define CMID 155.0 // midrange color in daylight
42 #define CSCALE 100.0 // color scaling to distance
43 #define CDIM 0.25 // dimming factor for eclipse
44
45 #define FNT "DejaVuMonoSans"
46 #define FSZ 20
47
48 #define SPEEDUP (14400.0*RATE/NPICS)
49
50 // --------------------------------------------------------------
51 // How toroidal orbits work.
52 //
53 // An elliptical orbit is faster than a similar circular orbit at
54 // perigee, and slower at apogee. If the delta between circular
55 // and elliptical is ZEXP ( == e R ) then an array element halfway
56 // between perigee and apogee in an elliptical orbit is displaced
57 // 2 * ZEXP ahead of its circular neighbor. We need enough ZEXP
58 // to keep perigee and apogee objects from colliding, and also to
59 // provide a reasonably large surface facing forwards or backwards
60 // in orbit at the 6AM and 6PM positions of the orbit.
61 //
62 // We need enough YEXP (North/South) size to make a reasonable
63 // large disk for radio and solar capture. We need enough XEXP
64 // to make radio disk, and capture the sun at the noon position.
65 //
66 // You can fiddle with the relative values of XEXP, YEXP, and ZEXP
67 // to see how it shapes the array. We probably want something a
68 // little flattened in ZEXP to reduce relative skew.
69 //
70 // This program will arbitrarily draw "right hand" toroidal orbits;
71 // If your thumb is the orbital direction, the orbits will turn
72 // in the direction of your fingers. Viewing from just outside the
73 // orbit, looking at the center of the earth, the orbit will evolve
74 // like so:
75
76 // angle Z (radius) Y(NS) X orbit
77 // 0° -ZEXP inside,perigee 0 0
78 // 90° 0 YEXP top +2*ZEXP skew forward
79 // 180° +ZEXP outside,apogee 0 0
80 // 270° 0 YEXP bot -2*ZEXP skew backward
81
82 // --------------------------------------------------------------
83 // How to draw a geodesic sphere - tesselated icosahedron
84 //
85 // make a big array of normalized array points
86 // for a geodesic sphere radius 1
87 // class 1 icosahedral base
88 // V up to whole bunches, possibly millions of points
89 // number of vertexes is 10*V^2 + 2
90 //
91 // 12 vertices
92 // 20 faces
93 // 30 edges
94 //
95 // Procedure:
96 // (1) define the 12 vertices
97 // (3) define the 30 edges in terms of 2 vertices each (by index)
98 // (2) define the 20 faces in terms of 3 vertices each (by index)
99 //
100 // see http://en.wikipedia.org/wiki/Icosahedron
101 //
102 // -1 +1
103 // axes: x left to right
104 // y down to up
105 // z back to front
106 //
107 // φ = (1 + √5) / 2 is the golden ratio
108 // x y z
109 // 0, 1, 2, 3 (±1, ±φ, 0)
110 // 4, 5, 6, 7 (0, ±1, ±φ)
111 // 8, 9,10,11 (±φ, 0, ±1)
112 //
113 // The radius is sqrt( 1 + φ^2 )
114 // we will normalize that to one, later, and rotate so that
115 // there are vertices top and bottom
116
117 #include <gd.h>
118 #include <math.h>
119 #include <stdio.h>
120 #include <stdlib.h>
121
122 typedef struct { int a, b, c; } Index3 ;
123 typedef struct { int a, b; } Index2 ;
124 typedef struct { double x,y,z; } Point ;
125
126 #define SZ ( 10*(NM+2)*NM ) // max array size (divis by 4)
127
128 Point vertex[SZ] ; // array to vertices of max array
129 double xdis[SZ], ydis[SZ], zdis[SZ], wdis[SZ] ;
130 int col[SZ] ;
131 Index3 colrgb[SZ] ;
132
133 #define RMMKDIR "rm -rf %sdir ; mkdir %sdir"
134 #define PNGFMT "%sdir/a%05d.png"
135 #define PNG2SWF "png2swf -o %s.swf -r %d %sdir/*.png"
136
137 // --------------------------------------------------------------------
138 // this array is used to generate the icosahedron main vertices
139 // 2 is φ , 1 is 1, 0 is 0
140
141 // point 0 is at the left, and 2, 4, 6, 8, and 10 are clockwise around it
142 // point 1 is at the right, and 3, 5, 7, 9, and 11 are clockwise around it
143 // 0 is opposite 1, 2 is opposite 3, 4 is opposite 5, etc.
144
145 static Index3 vertABC[12] = {
146 { 2, 1, 0}, // 0 left point after rotation
147 {-2,-1, 0}, // 1 right point after rotation
148 { 2,-1, 0}, // 2
149 {-2, 1, 0}, // 3
150 { 1, 0, 2}, // 4
151 {-1, 0,-2}, // 5
152 { 0, 2, 1}, // 6
153 { 0,-2,-1}, // 7
154 { 0, 2,-1}, // 8
155 { 0,-2, 1}, // 9
156 { 1, 0,-2}, // 10
157 {-1, 0, 2}, // 11
158 };
159
160 // --------------------------------------------------------------------
161 // this array is used to generate the 30 edges, between the numbered
162 // vertices in vertABC
163
164 static Index2 edge[30] = {
165 { 0, 2 },
166 { 0, 4 },
167 { 0, 6 },
168 { 0, 8 },
169 { 0, 10 },
170 { 1, 3 },
171 { 1, 5 },
172 { 1, 7 },
173 { 1, 9 },
174 { 1, 11 },
175 { 2, 4 },
176 { 2, 7 },
177 { 2, 9 },
178 { 2, 10 },
179 { 3, 5 },
180 { 3, 6 },
181 { 3, 8 },
182 { 3, 11 },
183 { 4, 6 },
184 { 4, 9 },
185 { 4, 11 },
186 { 5, 7 },
187 { 5, 8 },
188 { 5, 10 },
189 { 6, 8 },
190 { 6, 11 },
191 { 7, 9 },
192 { 7, 10 },
193 { 8, 10 },
194 { 9, 11 },
195 };
196
197 // --------------------------------------------------------------------
198 // this array is used to generate the 20 faces, between the numbered
199 // vertices in vertABC
200
201 static Index3 face[20] = {
202 { 0, 2, 4 },
203 { 0, 4, 6 },
204 { 0, 6, 8 },
205 { 0, 8, 10 },
206 { 0, 10, 2 },
207 { 1, 3, 5 },
208 { 1, 5, 7 },
209 { 1, 7, 9 },
210 { 1, 9, 11 },
211 { 1, 11, 3 },
212 { 2, 7, 10 },
213 { 5, 7, 10 },
214 { 5, 8, 10 },
215 { 5, 8, 3 },
216 { 6, 8, 3 },
217 { 6, 11, 3 },
218 { 6, 11, 4 },
219 { 9, 11, 4 },
220 { 9, 2, 4 },
221 { 9, 2, 7 },
222 };
223
224 // --------------------------------------------------------------------
225
226 double psi ;
227 double znorm ;
228
229 int sun1, white, red, green, blue ; // color indexes
230 int dred, gray, trans, lgray, cyan ;
231 int dgray, yellow, magenta, black ;
232 int dcyan ;
233
234 double xsize = (double) XSIZE ; // screen width
235 double ysize = (double) YSIZE ; // screen width
236 double xcenter = (double) ( XSIZE / 2 ) ; // half screen width
237 int ex = (int) (1.5*ORBSIZE) ; // drawn earth center x
238 int ey = (int) (1.3*ORBSIZE) ; // drawn earth center y
239 int re = ESIZE / 2 ; // drawn earth radius
240 int nvert ; // vertices in geosphere
241
242 double pi2 = 6.2831853070795864 ;
243 gdImagePtr im ; // Declare the image
244 FILE *pngout ; // Declare output file
245
246 // =============================================================
247
248 int normalize( Point *a ) {
249 double len = sqrt( a->x*a->x + a->y*a->y + a->z*a->z );
250 if( len == 0.0 ) {
251 fprintf(stderr, "Normalize error%12.3f%12.3f%12.3f\n", a->x, a->y,a->z );
252 return 1 ;
253 }
254 a->x /= len ;
255 a->y /= len ;
256 a->z /= len ;
257 // printf( "N %12.3f%12.3f%12.3f%12.3f\n",a->x, a->y, a->z, len );
258 return 0 ;
259 }
260
261 // -------------------------------------------------------------
262
263 double val( int type ) {
264 switch( type ) {
265 case -2 : return -psi ;
266 case -1 : return -1.0 ;
267 case 0 : return 0.0 ;
268 case 1 : return 1.0 ;
269 case 2 : return psi ;
270 }
271 return 0.0 ;
272 }
273
274 // -------------------------------------------------------------
275
276 void colorstart() {
277 int cp, cq, ix, of ;
278 white =gdImageColorAllocate( im, 255, 255, 255);
279 black =gdImageColorAllocate( im, 0, 0, 0);
280 gray =gdImageColorAllocate( im, 128, 128, 128);
281 dgray =gdImageColorAllocate( im, 96, 96, 96);
282 lgray =gdImageColorAllocate( im, 192, 192, 192);
283 cyan =gdImageColorAllocate( im, 0, 192, 192);
284 dcyan =gdImageColorAllocate( im, 0, 48, 48);
285 red =gdImageColorAllocate( im, 255, 0, 0);
286 dred =gdImageColorAllocate( im, 128, 0, 0);
287 yellow =gdImageColorAllocate( im, 255, 255, 0);
288 green =gdImageColorAllocate( im, 0, 255, 0);
289 blue =gdImageColorAllocate( im, 0, 0, 255);
290 magenta =gdImageColorAllocate( im, 192, 0, 192);
291 trans =gdImageColorAllocate( im, 1, 1, 1);
292
293 for( ix = 0 ; ix < nvert ; ix++ ) {
294 int ir = colrgb[ix].a ;
295 int ig = colrgb[ix].b ;
296 int ib = colrgb[ix].c ;
297 col[ix] = gdImageColorAllocate( im, ir , ig , ib );
298 col[ix+nvert] = gdImageColorAllocate( im, ir/4 , ig/4 , ib/4 );
299 }
300 }
301
302 // draw arrowhead (either degrees or radians ) -----------------------------
303
304 void arrowhead( double xp, double yp, double asize,
305 double deg, double rad, int color ) {
306 double angl = rad+pi2*deg/360.0 ;
307 gdPoint arrow[3] ;
308
309 arrow[0].x = (int)(xp);
310 arrow[0].y = (int)(yp);
311 arrow[1].x = (int)(xp+asize*( -cos(angl)-0.5*sin(angl)));
312 arrow[1].y = (int)(yp+asize*( 0.5*cos(angl)- sin(angl)));
313 arrow[2].x = (int)(xp+asize*( -cos(angl)+0.5*sin(angl)));
314 arrow[2].y = (int)(yp+asize*(-0.5*cos(angl)- sin(angl)));
315 gdImageFilledPolygon( im, arrow, 3, color );
316 }
317
318 // draw arrow -------------------------------------------------------------
319
320 void arrow( double x0, double y0, double x1, double y1, int color ) {
321 double asize = 0.02*(x1-x0) ;
322
323 gdImageLine( im, (int)x0, (int)y0, (int)x1, (int)y1, color ) ;
324 arrowhead( x1, y1, ASCALE, 0.0, 0.0, color ) ;
325 }
326
327 // draw rotating earth and orbiting body and side arrow -------------
328
329 void earth( double ang ) {
330 double x, y ;
331 double xs, ys ;
332 int x0, y0 ;
333 int x1, y1 ;
334 double an0 ;
335 int ie ;
336 int orbit = 2*ORBSIZE ;
337
338 gdImageFilledArc(im, ex, ey, ESIZE, ESIZE, 0, 360, dcyan, gdArc);
339 gdImageFilledArc(im, ex, ey, ESIZE, ESIZE, 90, 270, cyan, gdArc);
340 gdImageArc( im, ex, ey, orbit, orbit, 30, 330, white );
341 gdImageArc( im, ex, ey, orbit, orbit, 330, 30, dgray );
342
343 // draw longitude lines ( 6 = 180/30 degrees )
344 for( ie = 0 ; ie < 6 ; ie ++ ) {
345 an0 = (ang/6.0) + pi2*( (double)ie) / 12.0 ;
346 x0 = ex - (int)( ((double)re) * cos(an0) );
347 x1 = ex + (int)( ((double)re) * cos(an0) );
348 y0 = ey + (int)( ((double)re) * sin(an0) );
349 y1 = ey - (int)( ((double)re) * sin(an0) );
350 gdImageLine( im, x0, y0, x1, y1, black );
351 }
352
353 // draw latitude lines
354 for( ie = 1 ; ie < 3 ; ie++ ) {
355 an0 = pi2*( (double) ie ) / 12.0 ;
356 x0 = (int)( 2.0 * ((double)re) * cos(an0) );
357 gdImageArc( im, ex, ey, x0, x0, 0, 360, black );
358 }
359
360 // draw arrowhead to show side point of view
361 x= -( ORBSIZE + ASCALE ) ;
362 y= 0.0 ;
363 xs = x*cos(ang)+y*sin(ang) + (double) ex ;
364 ys = y*cos(ang)-x*sin(ang) + (double) ey ;
365
366 arrowhead( xs, ys, ASCALE, 0.0, -ang, white );
367 }
368
369 // =============================================================
370
371 int main() {
372 double angle ;
373 int frame ;
374 char pngfilename[64];
375 char command[128];
376
377 double test ; // depth testing
378 int ox, oy ;
379 int s0 ;
380
381 double xu, yu ;
382 int xi, yi ;
383 int icol ;
384 double deg ;
385
386 int i ;
387 double dv = (double) V ;
388
389 psi = 0.5 * ( 1.0 + sqrt(5.0) ) ;
390 znorm = sqrt( psi*psi + 1.0 ) ;
391
392 sprintf( command, RMMKDIR, NAME, NAME );
393 system( command );
394
395 // COMPUTE THE ICOSAHEDRON -------------------------------------------
396 // we will generate the icosahedron, then interpolate the edge points
397 // and face points between them. These will then be normalized to
398 // radius 1
399
400 // compute 12 vertices -------------------------
401
402 for( nvert = 0 ; nvert < 12 ; nvert++ ) {
403 double xtemp = val( vertABC[nvert].a );
404 double ytemp = val( vertABC[nvert].b );
405 double ztemp = val( vertABC[nvert].c );
406
407 // rotate so x value of 0th vertex is max
408 double xr = psi*xtemp + ytemp ;
409 double yr = psi*ytemp - xtemp ;
410 double zr = znorm*ztemp ;
411 double sxz = XZROTATE ;
412 double cxz = sqrt( 1.0-sxz*sxz );
413
414 // rotate x to z (radial) directions, y (NS) remains same
415 vertex[nvert].x = cxz * xr - sxz * zr ;
416 vertex[nvert].y = yr ;
417 vertex[nvert].z = cxz * zr + sxz * xr ;
418 }
419 // nvert is now 12
420
421 // compute 30 edges ---------------------------
422 // using two points on the icosahedron, in the edge table
423
424 for( i = 0 ; i < 30 ; i++ ) {
425 Point va = vertex[ edge[i].a ] ; // find icosahedron points
426 Point vb = vertex[ edge[i].b ] ; // find icosahedron points
427 double da ;
428
429 for( da = 1.0 ; da < dv ; da++ ) {
430 double db = dv-da ;
431 vertex[ nvert ].x = da*va.x + db*vb.x ;
432 vertex[ nvert ].y = da*va.y + db*vb.y ;
433 vertex[ nvert ].z = da*va.z + db*vb.z ;
434 nvert++ ; // add more vertices
435 } }
436
437 // number of new edge points = 30*(V-1)
438 // nvert is now 30*V - 18
439
440 // compute 20 faces ---------------------------
441 // using three points on the icosahedron, in the face table
442
443 for( i = 0 ; i < 20 ; i++ ) {
444 Point va = vertex[ face[i].a ] ; // find icosahedron points
445 Point vb = vertex[ face[i].b ] ; // find icosahedron points
446 Point vc = vertex[ face[i].c ] ; // find icosahedron points
447 double da, db ;
448
449 for( da = 1.0 ; da < dv ; da++ ) {
450 for( db = 1.0 ; db < ( dv-da) ; db++ ) {
451 double dc = dv-(da+db);
452 vertex[ nvert ].x = da*va.x + db*vb.x + dc*vc.x ;
453 vertex[ nvert ].y = da*va.y + db*vb.y + dc*vc.y ;
454 vertex[ nvert ].z = da*va.z + db*vb.z + dc*vc.z ;
455 nvert++ ; // add more vertices
456 } } }
457
458 // number of new face points = 10*V^2 - 30*V + 20
459 // nvert is now 10*V^2 + 2
460
461 // color -----------------------------------------------
462 // first we normalize each vertex point to radius 1. Then
463 // we will choose vertex color based on position in the base array
464
465 for( i = 0 ; i < nvert ; i++ ) {
466 normalize( &vertex[i] );
467 colrgb[i].a = (int) ( CMID + CSCALE*vertex[i].x ) ;
468 colrgb[i].b = (int) ( CMID + CSCALE*vertex[i].y ) ;
469 colrgb[i].c = (int) ( CMID + CSCALE*vertex[i].z ) ;
470 }
471
472 // ICOSAHEDRON COMPUTED --------------------------------------------
473 // graphics loop ---------------------------------------------------
474
475 for( frame = 1 ; frame <= NPICS ; frame++ ) {
476 im = gdImageCreateTrueColor(XSIZE, YSIZE );
477 sprintf( command, PNGFMT, NAME, frame );
478 pngout = fopen( command, "wb");
479
480 angle = (frame+0.001) * pi2 / ((double) NPICS ) ;
481 colorstart() ;
482 earth(angle) ;
483
484 // labels -----------------------------------------------------------
485
486 gdImageStringFT( im, NULL, // imagespace, bounding
487 white, FNT, FSZ, // color, font, fontsize
488 0.0, X1CENT, Y0CENT+FSZ/2, // angle, x, y
489 "Top" ); // the text
490
491 gdImageStringFT( im, NULL, // imagespace, bounding
492 white, FNT, FSZ, // color, font, fontsize
493 0.0, X1CENT-3*FSZ/2, Y1CENT+FSZ/2, // angle, x, y
494 "Front" ); // the text
495
496 gdImageStringFT( im, NULL, // imagespace, bounding
497 white, FNT, 2*FSZ, // color, font, fontsize
498 0.0, X1CENT-3*FSZ, YSIZE-FSZ, // angle, x, y
499 "Side" ); // the text
500
501 // time code -------------------------------------------------------
502
503 double time0 = ( 4.0 * (double) frame ) / ( (double) NPICS ) ;
504 char timestring[64] ;
505
506 int hour = (int) time0 ;
507 int min = (int) ( 0.1 + 60.0*( time0 - (double) hour));
508
509 sprintf( timestring, " %1dh%3dm", hour, min );
510
511 gdImageStringFT( im, NULL, // imagespace, bounding
512 white, FNT, FSZ, // color, font, fontsize
513 0.0, 0, YTCENT, // angle, x, y
514 timestring ); // y, the text
515
516
517 // direction arrows ------------------------------------------------
518 // large side view, small top view, small side view
519
520 gdImageSetThickness( im, 3 );
521
522 arrow( 0, YBCENT, 2*XBCENT, YBCENT, gray ); // large side view
523 arrow( X0CENT-80, Y0CENT, X0CENT+80, Y0CENT, gray ); // top arrow
524
525 // compute element locations in X, Y, Z --------------------------
526 // this is where we skew and distort the array. The Z scaling
527 // becomes the x distance skew. The orbit of each element can be
528 // elliptical in Y (north-south) versus Z (radial), while the X
529 // distance (along the orbit) gets the skew
530
531 double zm = SPACE * ZEXP ; // radial
532 double ym = SPACE * YEXP ;
533 double xm = SPACE * XEXP ;
534 double xt = SPACE * ( 1.0 + ASKEW * ZEXP ) ; // range of x values
535 double as = ASKEW * zm/ym ;
536 double dtest = (257.0/1024.0) ;
537 double test0 = (-1025.0/1024.0);
538 double test1 = ( 1025.0/1024.0);
539 double zfactr = ZFACTR/zm ;
540
541 // offsets from large side view to screen
542 int lsxo = XBCENT ;
543 int lsyo = YBCENT ;
544
545 // compute the points of the rotated, scaled, and skewed array
546 for( i=0 ; i < nvert ; i++ ) {
547 zdis[i] = zm*(cos(angle)*vertex[i].z+sin(angle)*vertex[i].y ) ;
548 ydis[i] = ym*(cos(angle)*vertex[i].y-sin(angle)*vertex[i].z ) ;
549 xdis[i] = xm*vertex[i].x + as*ydis[i] ;
550 }
551
552
553 // layer from back, so that bigger points in front overlap smaller
554 // points in back. This will make a large loop
555 for( test = test0; test < test1 ; test += dtest ) {
556
557 // compute display slices
558 double z0 = test*zm ;
559 double z1 = dtest*zm + z0 ;
560 double y0 = test*ym ;
561 double y1 = dtest*ym + y0 ;
562 double x0 = test*xt ;
563 double x1 = dtest*xt + x0 ;
564
565 /*
566 printf( "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n",
567 test, x0, x1, y0, y1, z0, z1 );
568 */
569
570 // step through all the vertices multiple times
571 for( i=0 ; i < nvert; i++ ) {
572
573 // draw view from top (Z+) --------------------------------------
574
575 if( ( ydis[i] >= y0 ) && ( ydis[i] < y1 ) ) {
576
577 // small top view
578
579 ox = X0CENT + (int) ( 0.25*xdis[i] );
580 oy = Y0CENT + (int) ( 0.25*zdis[i] );
581 gdImageSetPixel( im, ox, oy, col[i] );
582
583 // orbiting tiny top view
584
585 xu = 3.0 -ORBSIZE - OSCALE * zdis[i] ;
586 yu = OSCALE * xdis[i] ;
587
588 xi = ex + (int)( xu*cos(angle)+yu*sin(angle)) ;
589 yi = ey + (int)( yu*cos(angle)-xu*sin(angle)) ;
590
591 if( ( xi < ex )
592 ||( yi < ( ey-re ) )
593 ||( yi > ( ey+re ) ) ) icol = col[ i] ;
594 else icol = col[nvert+i] ; //shadow
595
596 gdImageSetPixel( im, xi, yi, icol );
597 }
598
599 // side views ---------------------------------------------
600
601 if( ( zdis[i] >= z0 ) && ( zdis[i] < z1 ) ) {
602
603 // BIG side view
604 ox = XBCENT + (int) ( xdis[i] );
605 oy = YBCENT + (int) ( -ydis[i] );
606
607 s0 = (int) ( SIZE * (1.00 + zfactr * zdis[i] ) ) ;
608 gdImageFilledArc(im, ox, oy, s0, s0, 0, 360, col[i], gdArc);
609 }
610
611 // small front view - apogee to left, closer ---------------
612
613 if( ( xdis[i] >= x0 ) && ( xdis[i] < x1 ) ) {
614 ox = X0CENT + (int) ( 0.25*zdis[i] );
615 oy = Y1CENT + (int) ( -0.25*ydis[i] );
616 gdImageSetPixel( im, ox, oy, col[i] );
617 }
618 }
619 }
620
621 /* Output the frame in PNG format. */
622 gdImagePngEx( im, pngout, 1 );
623 gdImageDestroy(im);
624 fclose(pngout);
625 }
626
627 sprintf( command, PNG2SWF, NAME, RATE, NAME );
628 system( command );
629 return 0 ;
630 }
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.