home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume16 / sipp2.0 / part04 < prev    next >
Encoding:
Internet Message Format  |  1991-01-02  |  36.8 KB

  1. From: kent@sparky.IMD.Sterling.COM (Kent Landfield)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i008:  sipp 2.0 - a library for 3D graphics, Part04/06
  4. Message-ID: <1991Jan3.065830.5166@sparky.IMD.Sterling.COM>
  5. Date: 3 Jan 91 06:58:30 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 3bb1d602 3fe06482 df70a119 78e70b37
  8.  
  9. Submitted-by: ingwa@isy.liu.se (Inge Wallin)
  10. Posting-number: Volume 16, Issue 8
  11. Archive-name: sipp2.0/part04
  12.  
  13. #!/bin/sh
  14. # This is part 04 of sipp-2.0
  15. # ============= libsipp/sipp.h ==============
  16. if test ! -d 'libsipp'; then
  17.     echo 'x - creating directory libsipp'
  18.     mkdir 'libsipp'
  19. fi
  20. if test -f 'libsipp/sipp.h' -a X"$1" != X"-c"; then
  21.     echo 'x - skipping libsipp/sipp.h (File already exists)'
  22. else
  23. echo 'x - extracting libsipp/sipp.h (Text)'
  24. sed 's/^X//' << 'SHAR_EOF' > 'libsipp/sipp.h' &&
  25. /*
  26. X * sipp.h  
  27. X *
  28. X * Copyright  Jonas Yngvesson
  29. X *            Inge Wallin
  30. X */
  31. X
  32. X
  33. #ifndef _SIPP_H
  34. #define _SIPP_H
  35. X
  36. #ifndef M_PI
  37. #define M_PI 3.14159265358979323846
  38. #endif
  39. X
  40. #ifndef FALSE
  41. typedef unsigned char bool;
  42. #define FALSE  0
  43. #define TRUE   1
  44. #endif 
  45. X
  46. /*
  47. X * Customize for those that don't have memcpy() and friends, but
  48. X * have bcopy() instead.
  49. X */
  50. X
  51. #ifdef NOMEMCPY
  52. #define memcpy(to, from, n) bcopy((from), (to), (n))
  53. #endif
  54. X
  55. X
  56. /*
  57. X * The macro RANDOM() should return a random number
  58. X * in the range [-1, 1].
  59. X */
  60. #define RANDOM()  (2.0 * drand48() - 1.0)
  61. X
  62. X
  63. /*
  64. X * Interface to shader functions.
  65. X */
  66. typedef void Shader();
  67. X
  68. X
  69. /*
  70. X * Colors are handled as an rgb-triple
  71. X * with values between 0 and 1.
  72. X */
  73. typedef struct {
  74. X    double   red;
  75. X    double   grn;
  76. X    double   blu;
  77. } Color;
  78. X
  79. X
  80. /*
  81. X * A transformation matrix is kept as a
  82. X * 4x3 matrix (4x4 is only needed in the last
  83. X * pesprctive transformation.
  84. X * Arrays are not first class objects in C so
  85. X * we surround it with a struct.
  86. X */
  87. typedef struct {
  88. X    double   mat[4][3];
  89. } Transf_mat;
  90. X
  91. X
  92. typedef struct {
  93. X    double x, y, z;
  94. } Vector;
  95. X
  96. X
  97. /*
  98. X * Structure storing the vertices in surfaces. The vertices for a
  99. X * surface are stored in a binary tree sorted first on x, then y and last z.
  100. X */
  101. typedef struct vertex_t {
  102. X    double            x, y, z;    /* vertex position */
  103. X    double            a, b, c;    /* average normal at vertex */
  104. X    double            u, v, w;    /* texture parameters (if any) */
  105. X    struct vertex_t  *big, *sml;  /* pointers to children in the tree */
  106. } Vertex;
  107. X
  108. X
  109. /*
  110. X * Structure to keep a list of vertex references.
  111. X */
  112. typedef struct vertex_ref_t {
  113. X    Vertex       *vertex;
  114. X    struct vertex_ref_t *next;
  115. } Vertex_ref;
  116. X
  117. X
  118. /*
  119. X * Polygon definition. A polygon is defined by a list of
  120. X * references to its vertices (counterclockwize order).
  121. X */
  122. typedef struct polygon_t {
  123. X    Vertex_ref *vertices;     /* vertex list */
  124. X    bool        backface;   /* polygon is backfacing (used at rendering) */
  125. X    struct polygon_t  *next;
  126. } Polygon;
  127. X
  128. X
  129. /*
  130. X * Surface definition. Each surface consists of a vertex tree, 
  131. X * a polygon list, a pointer to a surface description and a pointer
  132. X * to a shader function.
  133. X */
  134. typedef struct surface_t {
  135. X    Vertex           *vertices;          /* vertex tree */
  136. X    Polygon          *polygons;          /* polygon list */
  137. X    void             *surface;           /* surface description */
  138. X    Shader           *shader;            /* shader function */
  139. X    int               ref_count;         /* no of references to this surface */
  140. X    struct surface_t *next;              /* next surface in the list */
  141. } Surface;
  142. X
  143. X
  144. /*
  145. X * Object definition. Object consists of one or more
  146. X * surfaces and/or one or more subojects. Each object
  147. X * has its own transformation matrix that affects itself
  148. X * and all its subobjects.
  149. X */
  150. typedef struct object_t {
  151. X    Surface         *surfaces;       /* List of surfaces */
  152. X    struct object_t *sub_obj;        /* List of subobjects */
  153. X    Transf_mat       transf;         /* Transformation matrix */
  154. X    int              ref_count;      /* No of references to this object */
  155. X    struct object_t *next;           /* Next object in this list */
  156. } Object;
  157. X
  158. X
  159. X
  160. /*
  161. X * Lightsource definition. 
  162. X */
  163. typedef struct lightsource {
  164. X    double              intensity;  /* intensity, same for r, g, b */
  165. X    Vector              dir;        /* direction from origo */  
  166. X    struct lightsource *next;       /* next lightsource in the list */
  167. } Lightsource;
  168. X
  169. X
  170. /*
  171. X * Surface description used by the basic shader. This shader
  172. X * does simple shading of surfaces of a single color.
  173. X */
  174. typedef struct {
  175. X    double  ambient;       /* Fraction of color visible in ambient light */
  176. X    double  specular;      /* Fraction of colour specularly reflected */
  177. X    double  c3;            /* "Shinyness" 0 = shiny,  1 = dull */
  178. X    Color   color;         /* Colour of the surface */
  179. } Surf_desc;
  180. X
  181. X
  182. X
  183. /*
  184. X * This defines all public functions implemented in sipp.
  185. X */
  186. extern void     sipp_init();
  187. extern void     vertex_push();
  188. extern void     vertex_tx_push();
  189. extern void     polygon_push();
  190. extern Surface *surface_create();
  191. extern Surface *surface_basic_create();
  192. extern void     surface_set_shader();
  193. extern void     surface_basic_shader();
  194. extern Object  *object_create();
  195. extern Object  *object_instance();
  196. extern Object  *object_dup();
  197. extern Object  *object_deep_dup();
  198. extern void     object_delete();
  199. extern void     object_add_surface();
  200. extern void     object_add_subobj();
  201. extern void     object_install();
  202. extern void     object_uninstall();
  203. extern void     object_set_transf();
  204. extern void     object_clear_transf();
  205. extern void     object_transform();
  206. extern void     object_rot_x();
  207. extern void     object_rot_y();
  208. extern void     object_rot_z();
  209. extern void     object_rot();
  210. extern void     object_scale();
  211. extern void     object_move();
  212. extern void     lightsource_push();
  213. extern void     view_from();
  214. extern void     view_at();
  215. extern void     view_up();
  216. extern void     view_focal();
  217. extern void     viewpoint();
  218. extern void     render_image();
  219. extern void     basic_shader();
  220. X
  221. #endif /* _SIPP_H */
  222. SHAR_EOF
  223. chmod 0644 libsipp/sipp.h ||
  224. echo 'restore of libsipp/sipp.h failed'
  225. Wc_c="`wc -c < 'libsipp/sipp.h'`"
  226. test 5119 -eq "$Wc_c" ||
  227.     echo 'libsipp/sipp.h: original size 5119, current size' "$Wc_c"
  228. fi
  229. # ============= libsipp/sipptypes.h ==============
  230. if test -f 'libsipp/sipptypes.h' -a X"$1" != X"-c"; then
  231.     echo 'x - skipping libsipp/sipptypes.h (File already exists)'
  232. else
  233. echo 'x - extracting libsipp/sipptypes.h (Text)'
  234. sed 's/^X//' << 'SHAR_EOF' > 'libsipp/sipptypes.h' &&
  235. /*
  236. X * sipptypes.h - typdefs in sipp not needed to be public.
  237. X *
  238. X * (c) Jonas Yngvesson 1989-12-04
  239. X */
  240. X
  241. #ifndef SIPPTYPES_H
  242. #define SIPPTYPES_H
  243. X
  244. X
  245. /*
  246. X * Temporary storage of transformed vertices.
  247. X */
  248. typedef struct view_coord_3d {
  249. X    int                   y;
  250. X    double                x, z;        /* Transformed vertex coordinates */
  251. X    double                nx, ny, nz;  /* average normal */
  252. X    double                u, v, w;     /* texture parameters */
  253. X    struct view_coord_3d *next;        /* next vertex in the list */
  254. } View_coord;
  255. X
  256. X
  257. /*
  258. X * Entry in the edge list used in rendering.
  259. X */
  260. typedef struct edges_3d {
  261. X    int              y, y_stop;   /* Current point and interpolation steps */
  262. X    double           x, xstep;            
  263. X    double           z, zstep;
  264. X    double           nx, nxstep;  /* Current normal and interp. steps */
  265. X    double           ny, nystep;
  266. X    double           nz, nzstep;
  267. X    double           u, ustep;    /* Current texture coordinates and */
  268. X    double           v, vstep;    /* interp. steps                   */
  269. X    double           w, wstep;
  270. X    int              polygon;     /* Uniqe polygon id of the polygon to */
  271. X                                  /* which the edge belongs */
  272. X    Surface         *surface;     /* Surface that the edge belongs to */
  273. X    struct edges_3d *next;        /* Next edge on this scanline */
  274. } Edge;
  275. X
  276. X
  277. /*
  278. X * Y-bucket to keep the edge lists
  279. X */
  280. typedef struct {
  281. X    Edge *first, *last;   /* Firs and last entry in the list */
  282. } Bucket;
  283. X
  284. X
  285. /*
  286. X * Objects installed in the database for rendering are kept
  287. X * in a binary tree, internal to sipp. This database will
  288. X * automatically contain all top level objects, but the user
  289. X * can also force objects in or out of it.
  290. X */
  291. typedef struct inst_obj_t {
  292. X    Object *object;
  293. X    struct inst_obj_t *big;
  294. X    struct inst_obj_t *sml;
  295. } Inst_object;
  296. X
  297. X
  298. #endif /* SIPPTYPES_H */
  299. SHAR_EOF
  300. chmod 0644 libsipp/sipptypes.h ||
  301. echo 'restore of libsipp/sipptypes.h failed'
  302. Wc_c="`wc -c < 'libsipp/sipptypes.h'`"
  303. test 1885 -eq "$Wc_c" ||
  304.     echo 'libsipp/sipptypes.h: original size 1885, current size' "$Wc_c"
  305. fi
  306. # ============= libsipp/torus.c ==============
  307. if test -f 'libsipp/torus.c' -a X"$1" != X"-c"; then
  308.     echo 'x - skipping libsipp/torus.c (File already exists)'
  309. else
  310. echo 'x - extracting libsipp/torus.c (Text)'
  311. sed 's/^X//' << 'SHAR_EOF' > 'libsipp/torus.c' &&
  312. #include <xalloca.h>
  313. #include <math.h>
  314. X
  315. #include <sipp.h>
  316. X
  317. X
  318. static void
  319. arr_rot(arr1, arr2, len, angle)
  320. X    Vector arr1[];
  321. X    Vector arr2[];
  322. X    int    len;
  323. X    double angle;
  324. {
  325. X    int    i;
  326. X    double sa, ca;
  327. X
  328. X    sa = sin(angle);
  329. X    ca = cos(angle);
  330. X    for (i = 0; i < len; i++) {
  331. X        arr2[i].x = arr1[i].x * ca - arr1[i].y * sa;
  332. X        arr2[i].y = arr1[i].x * sa + arr1[i].y * ca;
  333. X        arr2[i].z = arr1[i].z;
  334. X    }
  335. }
  336. X
  337. X
  338. static void
  339. push_band(arr1, arr2, len)
  340. X    Vector arr1[];
  341. X    Vector arr2[];
  342. X    int    len;
  343. {
  344. X    int i, j;
  345. X
  346. X    for (i = 0; i < len; i++) {
  347. X        j = (i + 1) % len;
  348. X        vertex_tx_push(arr1[i].x, arr1[i].y, arr1[i].z, 
  349. X                       arr1[i].x, arr1[i].y, arr1[i].z);
  350. X        vertex_tx_push(arr2[i].x, arr2[i].y, arr2[i].z, 
  351. X                       arr2[i].x, arr2[i].y, arr2[i].z);
  352. X        vertex_tx_push(arr2[j].x, arr2[j].y, arr2[j].z, 
  353. X                       arr2[j].x, arr2[j].y, arr2[j].z);
  354. X        vertex_tx_push(arr1[j].x, arr1[j].y, arr1[j].z, 
  355. X                       arr1[j].x, arr1[j].y, arr1[j].z);
  356. X        polygon_push();
  357. X    }
  358. }
  359. X
  360. X
  361. X
  362. Object *
  363. sipp_torus(bigradius, smallradius, res1, res2, surface, shader)
  364. X    double  bigradius;      /* Radius of the ring */
  365. X    double  smallradius;    /* Radius of the "tube" */
  366. X    int     res1;           /* Number of polygons around the ring */
  367. X    int     res2;           /* Number of polygons around the tube */
  368. X    void   *surface;
  369. X    Shader *shader;
  370. {
  371. X    Object *torus;
  372. X    Vector *arr1;
  373. X    Vector *arr2;
  374. X    Vector *tmp;
  375. X    int     i;
  376. X
  377. X    /* Create two arrays to hold vertices around the tube */
  378. X    arr1 = (Vector *)alloca(res2 * sizeof(Vector));
  379. X    arr2 = (Vector *)alloca(res2 * sizeof(Vector));
  380. X
  381. X    for (i = 0; i < res2; i++) {
  382. X        arr1[i].x = bigradius + smallradius * cos(i * 2.0 * M_PI / res2);
  383. X        arr1[i].y = 0.0;
  384. X        arr1[i].z = smallradius * sin(i * 2.0 * M_PI / res2);
  385. X    }
  386. X
  387. X    /* Sweep out the torus by rotating the two perimeters */
  388. X    /* defined in arr1 and arr2. */
  389. X    for (i = 0; i < res1; i++) {
  390. X        arr_rot(arr1, arr2, res2, 2.0 * M_PI / (double)res1);
  391. X        push_band(arr1, arr2, res2);
  392. X        tmp = arr1;
  393. X        arr1 = arr2;
  394. X        arr2 = tmp;
  395. X    }
  396. X
  397. X    torus = object_create();
  398. X    object_add_surface(torus, surface_create(surface, shader));
  399. X
  400. X    return torus;
  401. }
  402. X
  403. SHAR_EOF
  404. chmod 0644 libsipp/torus.c ||
  405. echo 'restore of libsipp/torus.c failed'
  406. Wc_c="`wc -c < 'libsipp/torus.c'`"
  407. test 2322 -eq "$Wc_c" ||
  408.     echo 'libsipp/torus.c: original size 2322, current size' "$Wc_c"
  409. fi
  410. # ============= libsipp/xalloca.c ==============
  411. if test -f 'libsipp/xalloca.c' -a X"$1" != X"-c"; then
  412.     echo 'x - skipping libsipp/xalloca.c (File already exists)'
  413. else
  414. echo 'x - extracting libsipp/xalloca.c (Text)'
  415. sed 's/^X//' << 'SHAR_EOF' > 'libsipp/xalloca.c' &&
  416. #ifdef HAVE_NO_ALLOCA
  417. X
  418. /*
  419. X    alloca -- (mostly) portable public-domain implementation -- D A Gwyn
  420. X
  421. X    last edit:    86/05/30    rms
  422. X       include config.h, since on VMS it renames some symbols.
  423. X       Use xmalloc instead of malloc.
  424. X
  425. X    This implementation of the PWB library alloca() function,
  426. X    which is used to allocate space off the run-time stack so
  427. X    that it is automatically reclaimed upon procedure exit, 
  428. X    was inspired by discussions with J. Q. Johnson of Cornell.
  429. X
  430. X    It should work under any C implementation that uses an
  431. X    actual procedure stack (as opposed to a linked list of
  432. X    frames).  There are some preprocessor constants that can
  433. X    be defined when compiling for your specific system, for
  434. X    improved efficiency; however, the defaults should be okay.
  435. X
  436. X    The general concept of this implementation is to keep
  437. X    track of all alloca()-allocated blocks, and reclaim any
  438. X    that are found to be deeper in the stack than the current
  439. X    invocation.  This heuristic does not reclaim storage as
  440. X    soon as it becomes invalid, but it will do so eventually.
  441. X
  442. X    As a special case, alloca(0) reclaims storage without
  443. X    allocating any.  It is a good idea to use alloca(0) in
  444. X    your main control loop, etc. to force garbage collection.
  445. */
  446. #ifndef lint
  447. static char    SCCSid[] = "@(#)alloca.c    1.1";    /* for the "what" utility */
  448. #endif
  449. X
  450. #include "xalloca.h"
  451. X
  452. extern void    free();
  453. X
  454. /* ================================================================ */
  455. /*      This is entered from general.h in the GNU shell bash.       */
  456. X
  457. X
  458. #include <stdio.h>
  459. X
  460. /* **************************************************************** */
  461. /*                                    */
  462. /*           Memory Allocation and Deallocation.            */
  463. /*                                    */
  464. /* **************************************************************** */
  465. X
  466. static char *
  467. xmalloc (size)
  468. X     int size;
  469. {
  470. X    char *temp = (char *)malloc (size);
  471. X    
  472. X    if (!temp) {
  473. X        fprintf (stderr, "Out of virtual memory!");
  474. X        exit(1);
  475. X    }
  476. X
  477. X    return (temp);
  478. }
  479. X
  480. X
  481. /* ================================================================ */
  482. X
  483. /*
  484. X    Define STACK_DIRECTION if you know the direction of stack
  485. X    growth for your system; otherwise it will be automatically
  486. X    deduced at run-time.
  487. X
  488. X    STACK_DIRECTION > 0 => grows toward higher addresses
  489. X    STACK_DIRECTION < 0 => grows toward lower addresses
  490. X    STACK_DIRECTION = 0 => direction of growth unknown
  491. */
  492. X
  493. #ifndef STACK_DIRECTION
  494. #define    STACK_DIRECTION    0        /* direction unknown */
  495. #endif
  496. X
  497. #if STACK_DIRECTION != 0
  498. X
  499. #define    STACK_DIR    STACK_DIRECTION    /* known at compile-time */
  500. X
  501. #else    /* STACK_DIRECTION == 0; need run-time code */
  502. X
  503. static int    stack_dir;        /* 1 or -1 once known */
  504. #define    STACK_DIR    stack_dir
  505. X
  506. static void
  507. find_stack_direction (/* void */)
  508. {
  509. X  static char    *addr = NULL;    /* address of first
  510. X                   `dummy', once known */
  511. X  auto char    dummy;        /* to get stack address */
  512. X
  513. X  if (addr == NULL)
  514. X    {                /* initial entry */
  515. X      addr = &dummy;
  516. X
  517. X      find_stack_direction ();    /* recurse once */
  518. X    }
  519. X  else                /* second entry */
  520. X    if (&dummy > addr)
  521. X      stack_dir = 1;        /* stack grew upward */
  522. X    else
  523. X      stack_dir = -1;        /* stack grew downward */
  524. }
  525. X
  526. #endif    /* STACK_DIRECTION == 0 */
  527. X
  528. /*
  529. X    An "alloca header" is used to:
  530. X    (a) chain together all alloca()ed blocks;
  531. X    (b) keep track of stack depth.
  532. X
  533. X    It is very important that sizeof(header) agree with malloc()
  534. X    alignment chunk size.  The following default should work okay.
  535. */
  536. X
  537. #ifndef    ALIGN_SIZE
  538. #define    ALIGN_SIZE    sizeof(double)
  539. #endif
  540. X
  541. typedef union hdr
  542. {
  543. X  char    align[ALIGN_SIZE];    /* to force sizeof(header) */
  544. X  struct
  545. X    {
  546. X      union hdr *next;        /* for chaining headers */
  547. X      char *deep;        /* for stack depth measure */
  548. X    } h;
  549. } header;
  550. X
  551. /*
  552. X    alloca( size ) returns a pointer to at least `size' bytes of
  553. X    storage which will be automatically reclaimed upon exit from
  554. X    the procedure that called alloca().  Originally, this space
  555. X    was supposed to be taken from the current stack frame of the
  556. X    caller, but that method cannot be made to work for some
  557. X    implementations of C, for example under Gould's UTX/32.
  558. */
  559. X
  560. static header *last_alloca_header = NULL; /* -> last alloca header */
  561. X
  562. pointer
  563. alloca (size)            /* returns pointer to storage */
  564. X     unsigned    size;        /* # bytes to allocate */
  565. {
  566. X  auto char    probe;        /* probes stack depth: */
  567. X  register char    *depth = &probe;
  568. X
  569. #if STACK_DIRECTION == 0
  570. X  if (STACK_DIR == 0)        /* unknown growth direction */
  571. X    find_stack_direction ();
  572. #endif
  573. X
  574. X  /* Reclaim garbage, defined as all alloca()ed storage that
  575. X     was allocated from deeper in the stack than currently. */
  576. X  {
  577. X    register header    *hp;    /* traverses linked list */
  578. X
  579. X    for (hp = last_alloca_header; hp != NULL;)
  580. X      if (STACK_DIR > 0 && hp->h.deep > depth
  581. X      || STACK_DIR < 0 && hp->h.deep < depth)
  582. X    {
  583. X      register header    *np = hp->h.next;
  584. X
  585. X      free ((pointer) hp);    /* collect garbage */
  586. X
  587. X      hp = np;        /* -> next header */
  588. X    }
  589. X      else
  590. X    break;            /* rest are not deeper */
  591. X
  592. X    last_alloca_header = hp;    /* -> last valid storage */
  593. X  }
  594. X
  595. X  if (size == 0)
  596. X    return NULL;        /* no allocation required */
  597. X
  598. X  /* Allocate combined header + user data storage. */
  599. X
  600. X  {
  601. X    register pointer    new = xmalloc (sizeof (header) + size);
  602. X    /* address of header */
  603. X
  604. X    ((header *)new)->h.next = last_alloca_header;
  605. X    ((header *)new)->h.deep = depth;
  606. X
  607. X    last_alloca_header = (header *)new;
  608. X
  609. X    /* User storage begins just after header. */
  610. X
  611. X    return (pointer)((char *)new + sizeof(header));
  612. X  }
  613. }
  614. X
  615. #endif  /* HAVE_NO_ALLOCA */
  616. SHAR_EOF
  617. chmod 0644 libsipp/xalloca.c ||
  618. echo 'restore of libsipp/xalloca.c failed'
  619. Wc_c="`wc -c < 'libsipp/xalloca.c'`"
  620. test 5405 -eq "$Wc_c" ||
  621.     echo 'libsipp/xalloca.c: original size 5405, current size' "$Wc_c"
  622. fi
  623. # ============= libsipp/xalloca.h ==============
  624. if test -f 'libsipp/xalloca.h' -a X"$1" != X"-c"; then
  625.     echo 'x - skipping libsipp/xalloca.h (File already exists)'
  626. else
  627. echo 'x - extracting libsipp/xalloca.h (Text)'
  628. sed 's/^X//' << 'SHAR_EOF' > 'libsipp/xalloca.h' &&
  629. #ifdef HAVE_NO_ALLOCA
  630. X
  631. #ifdef X3J11
  632. typedef void    *pointer;        /* generic pointer type */
  633. pointer alloca (unsigned);        /* returns pointer to storage */
  634. #else
  635. typedef char    *pointer;        /* generic pointer type */
  636. pointer alloca ();            /* returns pointer to storage */
  637. #endif /* X3J11 */
  638. X
  639. #else
  640. X
  641. #include <alloca.h>
  642. X
  643. #endif
  644. SHAR_EOF
  645. chmod 0644 libsipp/xalloca.h ||
  646. echo 'restore of libsipp/xalloca.h failed'
  647. Wc_c="`wc -c < 'libsipp/xalloca.h'`"
  648. test 314 -eq "$Wc_c" ||
  649.     echo 'libsipp/xalloca.h: original size 314, current size' "$Wc_c"
  650. fi
  651. # ============= doc/primitives.man ==============
  652. if test ! -d 'doc'; then
  653.     echo 'x - creating directory doc'
  654.     mkdir 'doc'
  655. fi
  656. if test -f 'doc/primitives.man' -a X"$1" != X"-c"; then
  657.     echo 'x - skipping doc/primitives.man (File already exists)'
  658. else
  659. echo 'x - extracting doc/primitives.man (Text)'
  660. sed 's/^X//' << 'SHAR_EOF' > 'doc/primitives.man' &&
  661. .\" Copyright 1990, Jonas Yngvesson, Inge Wallin
  662. .\" This program and documentation may be distributed freely under
  663. .\" the terms of GNU GENERAL PUBLIC LICENSE.
  664. .TH PRIMITIVES 3X "December , 1990" 3X
  665. .SH NAME
  666. primitives - a collection of geometric primitives for \fIsipp\fR.
  667. .SH SYNOPSIS
  668. \fI#include <primitives.h>\fR
  669. .sp
  670. [g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
  671. X
  672. .SH DESCRIPTION
  673. \fIsipp\fR gives the user access to a number of rather low level functions
  674. to create polygons, surfaces and objects. This manual describes a set of
  675. functions that use the low level functions in \fIsipp\fR to create
  676. geometric primitives. Each primitive is a complete \fIsipp\fR object.
  677. .sp
  678. All primitives described here will get texture coordinates equal to the
  679. respective world coordinates.
  680. X
  681. .SH PRIMITIVES
  682. .IP \fIObject\ *sipp_torus(bigradius,\ smallradius,\ res1,\ res2,\ surface,\ shader)\fR
  683. .br
  684. \fIdouble\  bigradius;\fR
  685. .br
  686. \fIdouble\  smallradius;\fR
  687. .br
  688. \fIint\     res1;\fR
  689. .br
  690. \fIint\     res2;\fR
  691. .br
  692. \fIvoid\   *surface;\fR
  693. .br
  694. \fIShader\ *shader;\fR
  695. .sp
  696. \fIsipp_torus()\fR creates a torus centered about the origin and with the
  697. z-axis pointing up through the ring. \fIbigradius\fR is the radius of the
  698. ring and \fIsmallradius\fR is the radius of the "tube" itself. \fIres1\fR
  699. is the number of polygons that will be created radially around the ring
  700. and \fIres2\fR is the number of polygons that will be created around the
  701. tube. \fIsurface\fR is the surface description used by \fIshader()\fR
  702. which is the shading function used when shading the torus.
  703. X
  704. .IP \fIObject\ *sipp_cylinder(radius,\ length,\ resolution,\ surface,\ shader)\fR
  705. .br
  706. \fIdouble\  radius;\fR
  707. .br
  708. \fIdouble\  length;\fR
  709. .br
  710. \fIint\     resolution;\fR
  711. .br
  712. \fIvoid\   *surface;\fR
  713. .br
  714. \fIShader\ *shader;\fR
  715. .sp
  716. \fIsipp_cylinder()\fR creates a cylinder centered about the origin and with the
  717. z-axis along the cylinders main axis. \fIradius\fR and \fIlength\fR
  718. defines the size of the cylinder. \fIresolution\fR
  719. is the number of polygons that will be created radially around the rim.
  720. \fIsurface\fR is the surface description used by \fIshader()\fR
  721. which is the shading function used when shading the cylinder.
  722. X
  723. .IP \fIObject\ *sipp_ellipsoid(x_rad,\ y_rad,\ z_rad,\ resolution,\ surface,\ shader)\fR
  724. .br
  725. \fIdouble\  x_rad;\fR
  726. .br
  727. \fIdouble\  y_rad;\fR
  728. .br
  729. \fIdouble\  z_rad;\fR
  730. .br
  731. \fIint\     resolution;\fR
  732. .br
  733. \fIvoid\   *surface;\fR
  734. .br
  735. \fIShader\ *shader;\fR
  736. .sp
  737. \fIsipp_ellipsoid()\fR creates a ellipsoid centered about the origin.
  738. \fIx_rad\fR, \fIy_rad\fR and \fIz_rad\fR
  739. defines the size of the ellipsoid. \fIresolution\fR
  740. is the number of polygons that will be created around it's "equator".
  741. \fIsurface\fR is the surface description used by \fIshader()\fR
  742. which is the shading function used when shading the ellipsoid.
  743. X
  744. .IP \fIObject\ *sipp_sphere(radius,\ resolution,\ surface,\ shader)\fR
  745. .br
  746. \fIdouble\  radius;\fR
  747. .br
  748. \fIint\     resolution;\fR
  749. .br
  750. \fIvoid\   *surface;\fR
  751. .br
  752. \fIShader\ *shader;\fR
  753. .sp
  754. \fIsipp_sphere()\fR creates a sphere centered about the origin.
  755. \fIradius\fR defines the size of the sphere. \fIresolution\fR
  756. is the number of polygons that will be created around it's "equator".
  757. \fIsurface\fR is the surface description used by \fIshader()\fR
  758. which is the shading function used when shading the sphere.
  759. X
  760. .IP \fIObject\ *sipp_block(x_size,\ y_size,\ z_size,\ surface,\ shader)\fR
  761. .br
  762. \fIdouble\  x_size;\fR
  763. .br
  764. \fIdouble\  y_size;\fR
  765. .br
  766. \fIdouble\  z_size;\fR
  767. .br
  768. \fIvoid\   *surface;\fR
  769. .br
  770. \fIShader\ *shader;\fR
  771. .sp
  772. \fIsipp_block\fR creates a square block with the size defined by \fIx_size\fR,
  773. \fIz_size\fR and \fIz_size\fR. The block is centered about the
  774. origin. \fIsurface\fR is the surface description used by \fIshader()\fR which
  775. is the shading function used when shading the block.
  776. X
  777. .IP \fIObject\ *sipp_cube(side,\ surface,\ shader)\fR
  778. .br
  779. \fIdouble\  side;\fR
  780. .br
  781. \fIvoid\   *surface;\fR
  782. .br
  783. \fIShader\ *shader;\fR
  784. .sp
  785. \fIsipp_cube()\fR creates a cube with the side of length \fIside\fR.  The
  786. cube is centered about the origin. \fIsurface\fR is the surface description
  787. used by \fIshader()\fR which is the shading function used when shading the
  788. cube.
  789. X
  790. .IP \fIObject\ *sipp_bezier(file,\ res,\ surface,\ shader)\fR
  791. .br
  792. \fIFILE\   *file;\fR
  793. .br
  794. \fIint\     res;\fR
  795. .br
  796. \fIvoid\   *surface;\fR
  797. .br
  798. \fIShader\ *shader;\fR
  799. .sp
  800. \fIsipp_bezier()\fR reads a file containing descriptions of a set of bezier
  801. patches or bezier curves. If the file contains descriptions of patches, these
  802. patches will be tesselated into \fIres\fR by \fIres\fR polygons and installed
  803. in a \fIsipp\fR object as one surface. The surface will be shaded by
  804. \fIshader\fR using the surface description \fIsurface\fR.
  805. .sp
  806. If the file contains descriptions of curves, a rotational surface will be
  807. created by rotating these curves about the y-axis. The resulting surface will
  808. be tesselated into polygons and installed in a \fIsipp\fR object as one
  809. surface. The surface will be shaded by \fIshader\fR using the surface
  810. description \fIsurface\fR.
  811. .sp
  812. The format of the description file is rather simple. First a keyword defining
  813. the type of description in the file, \fIbezier_curves:\fR or
  814. \fIbezier_patches:\fR. Then follows a description of the vertices (control
  815. points). First the word \fIvertices:\fR followed by an integer number that
  816. tells how many vertices there are in the description, then the word
  817. \fIvertex_list:\fR followed by the x, y and z coordinates for each vertex. The
  818. number of vertices must be same as the number given above. This is, however,
  819. not checked for. 
  820. .sp
  821. If the file contains curves, the keyword \fIcurves:\fR followed by the number
  822. of bezier curves in the file stand on the next line. After this line, a line
  823. with the single keyword \fIcurve_list:\fR follows. Lastly, the bezier curves
  824. themselves follow as numbers in groups of four by four. Each number is an
  825. index into the vertex list with the first index having number 1.
  826. .sp
  827. If the file contains patches, the format is the same with the following
  828. exceptions: The word \fIpatches:\fR is substituted for \fIcurves:\fR, the word
  829. \fIpatch_list:\fR is substituted for \fIcurve_list:\fR and the indices into
  830. the vertex list are grouped 16 by 16 instead of 4 by 4.
  831. .sp
  832. Comments can be inserted anywhere in a bezier curve/patch description file by
  833. using the hashmark character, #. The comment lasts to the end of the line.
  834. .sp
  835. Example: the body of a standard Newell teapot.
  836. .sp
  837. .nf
  838. # Bezier curves (rotational body) for teapot body.
  839. X
  840. bezier_curves:
  841. X
  842. vertices: 10
  843. vertex_list:
  844. X    3.500000E-01    5.625000E-01    0.000000E+00
  845. X    3.343750E-01    5.953125E-01    0.000000E+00
  846. X    3.593750E-01    5.953125E-01    0.000000E+00
  847. X    3.750000E-01    5.625000E-01    0.000000E+00
  848. X    4.375000E-01    4.312500E-01    0.000000E+00
  849. X    5.000000E-01    3.000000E-01    0.000000E+00
  850. X    5.000000E-01    1.875000E-01    0.000000E+00
  851. X    5.000000E-01    7.500000E-02    0.000000E+00
  852. X    3.750000E-01    1.875000E-02    0.000000E+00
  853. X    3.750000E-01    0.000000E+00    0.000000E+00
  854. X
  855. curves:    3
  856. curve_list:
  857. X
  858. X  1 2 3 4
  859. X
  860. X  4 5 6 7
  861. X
  862. X  7 8 9 10
  863. X
  864. #End of teapot bezier file
  865. .fi
  866. X
  867. .SH SEE ALSO
  868. sipp(3X) - simple polygon processor, a 3d-graphics library
  869. .br
  870. shaders(3X) - a collection of shaders for \fIsipp\fR.
  871. X
  872. .SH AUTHORS
  873. Jonas Yngvesson\    \    (jonas-y@isy.liu.se)
  874. .br
  875. Inge Wallin\        (ingwa@isy.liu.se)
  876. X
  877. .SH BUGS
  878. The format for the bezier patches and curves is prohibitively ugly.
  879. SHAR_EOF
  880. chmod 0644 doc/primitives.man ||
  881. echo 'restore of doc/primitives.man failed'
  882. Wc_c="`wc -c < 'doc/primitives.man'`"
  883. test 7416 -eq "$Wc_c" ||
  884.     echo 'doc/primitives.man: original size 7416, current size' "$Wc_c"
  885. fi
  886. # ============= doc/shaders.man ==============
  887. if test -f 'doc/shaders.man' -a X"$1" != X"-c"; then
  888.     echo 'x - skipping doc/shaders.man (File already exists)'
  889. else
  890. echo 'x - extracting doc/shaders.man (Text)'
  891. sed 's/^X//' << 'SHAR_EOF' > 'doc/shaders.man' &&
  892. .\" Copyright 1990, Jonas Yngvesson, Inge Wallin
  893. .\" This program and documentation may be distributed freely under
  894. .\" the terms of GNU GENERAL PUBLIC LICENSE.
  895. .TH SHADERS 3X "December , 1990" 3X
  896. .SH NAME
  897. shaders - a collection of shaders for \fIsipp\fR.
  898. .SH SYNOPSIS
  899. \fI#include <sipp.h>\fR
  900. .br
  901. \fI#include <shaders.h>\fR
  902. .sp
  903. [g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
  904. X
  905. .SH DESCRIPTION
  906. \fIsipp\fR provides the user with a simple shading model and a shading
  907. function called \fIbasic_shader()\fR. Each shader takes a description of
  908. the surface parameters and the structure used for \fIbasic_shader()\fR
  909. is called \fISurf_desc\fR. See \fIsipp\fR(3X) for more details about
  910. shaders and their parameters.
  911. .sp
  912. This manual describes the parameters for a \fIsipp\fR shading functions and a
  913. set of shaders beside \fIbasic_shader()\fR that are included in the library.
  914. All shaders described here provide some kind of special effect on a surface
  915. and call \fIbasic_shader()\fR to do the actual shading calculations.
  916. X
  917. .SH SIPP SHADING FUNCTIONS
  918. Each surface in a scene has a shading function associated with it.
  919. This function is called for each pixel in the surface as it is
  920. rendered. \fIsipp\fR has an internal basic shading function called
  921. \fIbasic_shader\fR that can be used in most cases. \fIbasic_shader\fR
  922. provides a somewhat modified and simplified version of Blinn's shading
  923. model, taking a \fISurf_desc\fR as a description of the surface. 
  924. .sp
  925. If the user is not satisfied with the builtin shader, he can provide
  926. his own shader and surface description struct. All shaders take
  927. the same parameters and must be defined as follows:
  928. .sp
  929. \fIvoid\ myshader(nx,\ ny,\ nz,\ \ u,\ v,\ w,\ view_vec,\fR
  930. .br
  931. \fI        lights,\ surface,\ color)\fR
  932. .br
  933. \fI    double nx, ny, nz;\fR
  934. .br
  935. \fI    double u, v, w;\fR
  936. .br
  937. \fI    Vector\ view_vec;\fR
  938. .br
  939. \fI    Lightsource *lights;\fR
  940. .br
  941. \fI    void *surface;\fR
  942. .br
  943. \fI    Color\ *color;\fR
  944. .sp
  945. \fInx, ny\fR and \fInz\fR is the \fInon-normalized\fR surface normal at the
  946. point that should be rendered.
  947. .br
  948. \fIu, v\fR and \fIw\fR are the interpolated texture coordinates at the rendered
  949. point. If no texture coordinates have been given at some vertices these
  950. values are undefined and contains garbage at best.
  951. .br
  952. \fIview_vec\fR is a normalized vector, pointing from the rendered
  953. point at the viewpoint.
  954. .br
  955. \fIlights\fR is a pointer to a linked list of lightsource descriptions. See
  956. the function \fIlightsource_push()\fR for a description of the structure of
  957. the links.
  958. .br
  959. \fIsurface\fR is the same \fIsurface\fR-pointer that was sent to the
  960. function \fIsurface_create()\fR. In the case of \fIbasic_shader\fR this is
  961. a pointer to a \fISurf_desc\fR. If the user provides his own shader, he
  962. can also provide his own surface description.
  963. .br
  964. Upon return, the shader should place the calculated rgb colour
  965. components in the areas pointed to by \fIcolor\fR. The rgb components
  966. must be values between 0 and 1.
  967. X
  968. .SH SHADERS AND SURFACE DESCRIPTORS
  969. The following shader functions are provided with the \fIsipp\fR library. 
  970. X
  971. .IP \fImarble_shader()\fR
  972. \fImarble_shader()\fR creates a simulated marble texture on a surface.
  973. It uses two colors, one as the base material and one as the
  974. interspersed material. The interspersed material is put into the
  975. base material in strips that are distorted using \fInoise()\fR and
  976. \fIturbulence()\fR. 
  977. .sp
  978. The surface description for a marble surface is called
  979. \fIMarble_desc\fR and is defined as follows:
  980. .br
  981. \fItypedef struct {\fR
  982. .br
  983. \fI\    double   ambient;\fR
  984. .br
  985. \fI\    double   specular;\fR
  986. .br
  987. \fI\    double   c3;\fR
  988. .br
  989. \fI\    double   scale;\fR
  990. .br
  991. \fI\    Color    base;\fR
  992. .br
  993. \fI\    Color    strip;\fR
  994. .br
  995. \fI} Marble_desc;\fR
  996. .sp
  997. Except for the two colors and the field \fIscale\fR, \fIMarble_desc\fR
  998. looks exactly like a \fISurf_desc\fR and the fields are used in the
  999. same way. 
  1000. .br
  1001. \fIscale\fR is a factor which determines the size of the
  1002. marble pattern depending on the size of the texture coordinate system
  1003. in relation to the world coordinate system. You will have to
  1004. experiment some to get this right.
  1005. .br
  1006. \fIbase\fR is the color of the base material, and \fIstrip\fR is the
  1007. color of the interspersed material.
  1008. X
  1009. .IP \fIgranite_shader()\fR
  1010. \fIgranite_shader()\fR is very similar to \fImarble_shader()\fR in
  1011. that it also
  1012. mixes two colors using \fInoise()\fR and \fIturbulence()\fR. The
  1013. difference is in 
  1014. how the mixing is done. The two colors are mixed whithout treating
  1015. them separately in any way. 
  1016. .sp
  1017. The surface description used in \fIgranite_shader()\fR is called
  1018. \fIGranite_desc\fR and is defined as follows:
  1019. .br
  1020. \fItypedef struct {\fR
  1021. .br
  1022. \fI\    double   ambient;\fR
  1023. .br
  1024. \fI\    double   specular;\fR
  1025. .br
  1026. \fI\    double   c3;\fR
  1027. .br
  1028. \fI\    double   scale;\fR
  1029. .br
  1030. \fI\    Color    col1;\fR
  1031. .br
  1032. \fI\    Color    col2;\fR
  1033. .br
  1034. \fI} Granite_desc;\fR
  1035. .sp
  1036. The fields have the same meaning as in \fIMarble_desc\fR.
  1037. X
  1038. .IP \fIbozo_shader()\fR
  1039. \fIbozo_shader()\fR uses \fInoise()\fR to chose a color from a fixed set.
  1040. The range of possible return value from \fInoise()\fR are divided into parts
  1041. of equal size and each part is assigned a color. The size of the parts
  1042. are dependent on the number of colors.
  1043. .sp
  1044. The surface description is called \fIBozo_desc\fR and is defined as
  1045. follows:
  1046. .br
  1047. \fItypedef struct {\fR
  1048. .br
  1049. \fI\    Color   *colors;\fR
  1050. .br
  1051. \fI\    int      no_of_cols;\fR
  1052. .br
  1053. \fI\    double   ambient;\fR
  1054. .br
  1055. \fI\    double   specular;\fR
  1056. .br
  1057. \fI\    double   c3;\fR
  1058. .br
  1059. \fI\    double   scale;
  1060. .br
  1061. \fI} Bozo_desc;\fR
  1062. .sp
  1063. \fIcolors\fR is a pointer to an array of \fIColor\fR structs and
  1064. \fIno_of_cols\fR defines the number of entries in this array. The other
  1065. fields have the same function as in the prevoiusly described shaders.
  1066. X
  1067. .IP \fImask_shader()\fR
  1068. \fImask_shader()\fR uses another image (ususally a bitmap) as a mask,
  1069. and calls two different shaders depending on the values in this image.
  1070. The mask image can be of any format. The user supplies a pointer
  1071. to the image and a function that tests the value of a certain pixel in it.
  1072. The mapping uses only the \fIu\fR and \fIv\fR texture coordinates.
  1073. .sp
  1074. The surface description is called \fIMask_desc\fR and has the
  1075. following definition:
  1076. .br
  1077. \fItypedef struct {\fR
  1078. .br
  1079. \fI\    Shader *fg_shader;\fR
  1080. .br
  1081. \fI\    void   *fg_surface;\fR
  1082. .br
  1083. \fI\    Shader *bg_shader;\fR
  1084. .br
  1085. \fI\    void   *bg_surface;\fR
  1086. .br
  1087. \fI\    void   *mask;\fR
  1088. .br
  1089. \fI\    bool  (*pixel_test)();\fR
  1090. .br
  1091. \fI\    int x0, y0;\fR
  1092. .br
  1093. \fI\    int xsize, ysize;\fR
  1094. .br
  1095. \fI\    double xscale, yscale;\fR
  1096. .br
  1097. \fI} Mask_desc;\fR
  1098. .sp
  1099. \fIfg_shader\fR is used together with the surface description
  1100. \fIfg_surface\fR when \fIpixel_test\fR (see below) returns TRUE.
  1101. .br
  1102. \fIbg_shader\fR is used together with the surface description
  1103. \fIbg_surface\fR when \fIpixel_test\fR (see below) returns FALSE.
  1104. .br
  1105. \fImask\fR is a pointer to the image. This could be a pointer to a raw array
  1106. of pixels or a complicated struct, the image representation is completely up
  1107. to the user.
  1108. .br
  1109. \fIpixel_test\fR is a function that is called to evaluate pixels in the mask
  1110. image. This function should be declared as follows:
  1111. .br
  1112. \fI\ bool my_pixel_test(image, x, y)\fR
  1113. .br
  1114. \fI\     my_image_struct *image;\fR
  1115. .br
  1116. \fI\     int              x, y;\fR
  1117. .br
  1118. \ \ \fIimage\fR is the same pointer that is stored in the \fIMask_desc\fR.
  1119. .br
  1120. \ \ \fIx\fR and \fIy\fR are the coordinates of the pixel that should be
  1121. tested.
  1122. .br
  1123. \fIx0\fR and \fIy0\fR define where (in mask image coordinates) the
  1124. origo of the texture coordinate system should be placed.
  1125. .br
  1126. \fIxsize\fR and \fIysize\fR is the size of the mask image.
  1127. .br
  1128. \fIxscale\fR and \fIyscale\fR scales the texture coordinate system
  1129. relative the mask image coordinates.
  1130. X
  1131. .IP \fIbumpy_shader()\fR
  1132. \fIbumpy_shader()\fR is a function that perturbates the normal of a
  1133. surface using \fIDnoise()\fR. Any other shader can be used to do the final
  1134. shading calculations. 
  1135. .sp
  1136. The surface description is called \fIBumpy_desc\fR and is defined as
  1137. follows:
  1138. .br
  1139. \fItypedef struct {\fR
  1140. .br
  1141. \fI\    Shader *shader;\fR
  1142. .br
  1143. \fI\    void   *surface;\fR
  1144. .br
  1145. \fI\    double scale;\fR
  1146. .br
  1147. \fI\    bool   bumpflag;\fR
  1148. .br
  1149. \fI\    bool   holeflag;\fR
  1150. .br
  1151. \fI} Bumpy_desc;\fR
  1152. .sp
  1153. \fIshader\fR and \fIsurface\fR define the shader to be used for the
  1154. final shading calculations. 
  1155. .br
  1156. \fIscale\fR has the same meaning as in previous shaders using \fInoise()\fR.
  1157. .br
  1158. \fIbumpflag\fR and \fIholeflag\fR make it possible to flatten out
  1159. half of the bumps. If only \fIbumpflag\fR is TRUE only bumps "standing
  1160. out" from the surface are visible. The rest of the surface will be smooth.
  1161. If, on the other hand, only \fIholeflag\fR is TRUE only bumps going
  1162. "into" the surface will be visible, thus giving the surface an
  1163. eroded look. If both flags are true, the whole surface will get a
  1164. bumpy appearence, rather like an orange.
  1165. X
  1166. .IP \fIplanet_shader()\fR
  1167. \fIplanet_shader()\fR is a somewhat specialized shader that produces a texture
  1168. that resembles a planet surface. The planet is of the Tellus type with a
  1169. mixture of oceans and continents. Some of the surface is covered by
  1170. semi-transparent clouds which enhances the effect greatly. On the other hand,
  1171. no polar caps are provided and this decreses the realism.
  1172. .sp
  1173. The texture is 3-dimensional, so it is possible to create cube planets or even
  1174. planets with cut-out parts that still have surfaces that resemble the earth
  1175. surface. The texture is not scalable, and is designed to be used with texture
  1176. coordinats in the range -1.0 to 1.0, e.g. a unit sphere. Of course the woorld
  1177. coordinats need not have the same order of magnitude.
  1178. .sp
  1179. \fIplanet_shader()\fR uses an ordinary \fISurf_desc\fR in which the
  1180. \fIcolor\fR field is not used.
  1181. X
  1182. .SH SEE ALSO
  1183. sipp(3X) - simple polygon processor, a 3d-graphics library
  1184. .br
  1185. primitives(3X) - a collection of geometric primitives for \fIsipp\fR.
  1186. X
  1187. .SH AUTHORS
  1188. Jonas Yngvesson\    \    (jonas-y@isy.liu.se)
  1189. .br
  1190. Inge Wallin\        (ingwa@isy.liu.se)
  1191. X
  1192. .SH BUGS
  1193. The planet texture should be enhanced with polar caps and it should be
  1194. possible to give parameters to control, among other factors, the ratio of
  1195. ocean/land and the cloudiness.
  1196. SHAR_EOF
  1197. chmod 0644 doc/shaders.man ||
  1198. echo 'restore of doc/shaders.man failed'
  1199. Wc_c="`wc -c < 'doc/shaders.man'`"
  1200. test 10071 -eq "$Wc_c" ||
  1201.     echo 'doc/shaders.man: original size 10071, current size' "$Wc_c"
  1202. fi
  1203. true || echo 'restore of doc/sipp.man failed'
  1204. echo End of part 4, continue with part 5
  1205. exit 0
  1206.  
  1207. -- 
  1208. Inge Wallin               | Thus spake the master programmer:               |
  1209.                           |      "After three days without programming,     |
  1210. ingwa@isy.liu.se          |       life becomes meaningless."                |
  1211.                           | Geoffrey James: The Tao of Programming.         |
  1212.  
  1213.  
  1214. exit 0 # Just in case...
  1215. -- 
  1216. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1217. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1218. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1219. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1220.