[comp.sources.misc] v16i008: sipp 2.0 - a library for 3D graphics, Part04/06

kent@sparky.IMD.Sterling.COM (Kent Landfield) (01/03/91)

Submitted-by: ingwa@isy.liu.se (Inge Wallin)
Posting-number: Volume 16, Issue 8
Archive-name: sipp2.0/part04

#!/bin/sh
# This is part 04 of sipp-2.0
# ============= libsipp/sipp.h ==============
if test ! -d 'libsipp'; then
    echo 'x - creating directory libsipp'
    mkdir 'libsipp'
fi
if test -f 'libsipp/sipp.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/sipp.h (File already exists)'
else
echo 'x - extracting libsipp/sipp.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/sipp.h' &&
/*
X * sipp.h  
X *
X * Copyright  Jonas Yngvesson
X *            Inge Wallin
X */
X
X
#ifndef _SIPP_H
#define _SIPP_H
X
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
X
#ifndef FALSE
typedef unsigned char bool;
#define FALSE  0
#define TRUE   1
#endif 
X
/*
X * Customize for those that don't have memcpy() and friends, but
X * have bcopy() instead.
X */
X
#ifdef NOMEMCPY
#define memcpy(to, from, n) bcopy((from), (to), (n))
#endif
X
X
/*
X * The macro RANDOM() should return a random number
X * in the range [-1, 1].
X */
#define RANDOM()  (2.0 * drand48() - 1.0)
X
X
/*
X * Interface to shader functions.
X */
typedef void Shader();
X
X
/*
X * Colors are handled as an rgb-triple
X * with values between 0 and 1.
X */
typedef struct {
X    double   red;
X    double   grn;
X    double   blu;
} Color;
X
X
/*
X * A transformation matrix is kept as a
X * 4x3 matrix (4x4 is only needed in the last
X * pesprctive transformation.
X * Arrays are not first class objects in C so
X * we surround it with a struct.
X */
typedef struct {
X    double   mat[4][3];
} Transf_mat;
X
X
typedef struct {
X    double x, y, z;
} Vector;
X
X
/*
X * Structure storing the vertices in surfaces. The vertices for a
X * surface are stored in a binary tree sorted first on x, then y and last z.
X */
typedef struct vertex_t {
X    double            x, y, z;    /* vertex position */
X    double            a, b, c;    /* average normal at vertex */
X    double            u, v, w;    /* texture parameters (if any) */
X    struct vertex_t  *big, *sml;  /* pointers to children in the tree */
} Vertex;
X
X
/*
X * Structure to keep a list of vertex references.
X */
typedef struct vertex_ref_t {
X    Vertex       *vertex;
X    struct vertex_ref_t *next;
} Vertex_ref;
X
X
/*
X * Polygon definition. A polygon is defined by a list of
X * references to its vertices (counterclockwize order).
X */
typedef struct polygon_t {
X    Vertex_ref *vertices;     /* vertex list */
X    bool        backface;   /* polygon is backfacing (used at rendering) */
X    struct polygon_t  *next;
} Polygon;
X
X
/*
X * Surface definition. Each surface consists of a vertex tree, 
X * a polygon list, a pointer to a surface description and a pointer
X * to a shader function.
X */
typedef struct surface_t {
X    Vertex           *vertices;          /* vertex tree */
X    Polygon          *polygons;          /* polygon list */
X    void             *surface;           /* surface description */
X    Shader           *shader;            /* shader function */
X    int               ref_count;         /* no of references to this surface */
X    struct surface_t *next;              /* next surface in the list */
} Surface;
X
X
/*
X * Object definition. Object consists of one or more
X * surfaces and/or one or more subojects. Each object
X * has its own transformation matrix that affects itself
X * and all its subobjects.
X */
typedef struct object_t {
X    Surface         *surfaces;       /* List of surfaces */
X    struct object_t *sub_obj;        /* List of subobjects */
X    Transf_mat       transf;         /* Transformation matrix */
X    int              ref_count;      /* No of references to this object */
X    struct object_t *next;           /* Next object in this list */
} Object;
X
X
X
/*
X * Lightsource definition. 
X */
typedef struct lightsource {
X    double              intensity;  /* intensity, same for r, g, b */
X    Vector              dir;        /* direction from origo */  
X    struct lightsource *next;       /* next lightsource in the list */
} Lightsource;
X
X
/*
X * Surface description used by the basic shader. This shader
X * does simple shading of surfaces of a single color.
X */
typedef struct {
X    double  ambient;       /* Fraction of color visible in ambient light */
X    double  specular;      /* Fraction of colour specularly reflected */
X    double  c3;            /* "Shinyness" 0 = shiny,  1 = dull */
X    Color   color;         /* Colour of the surface */
} Surf_desc;
X
X
X
/*
X * This defines all public functions implemented in sipp.
X */
extern void     sipp_init();
extern void     vertex_push();
extern void     vertex_tx_push();
extern void     polygon_push();
extern Surface *surface_create();
extern Surface *surface_basic_create();
extern void     surface_set_shader();
extern void     surface_basic_shader();
extern Object  *object_create();
extern Object  *object_instance();
extern Object  *object_dup();
extern Object  *object_deep_dup();
extern void     object_delete();
extern void     object_add_surface();
extern void     object_add_subobj();
extern void     object_install();
extern void     object_uninstall();
extern void     object_set_transf();
extern void     object_clear_transf();
extern void     object_transform();
extern void     object_rot_x();
extern void     object_rot_y();
extern void     object_rot_z();
extern void     object_rot();
extern void     object_scale();
extern void     object_move();
extern void     lightsource_push();
extern void     view_from();
extern void     view_at();
extern void     view_up();
extern void     view_focal();
extern void     viewpoint();
extern void     render_image();
extern void     basic_shader();
X
#endif /* _SIPP_H */
SHAR_EOF
chmod 0644 libsipp/sipp.h ||
echo 'restore of libsipp/sipp.h failed'
Wc_c="`wc -c < 'libsipp/sipp.h'`"
test 5119 -eq "$Wc_c" ||
	echo 'libsipp/sipp.h: original size 5119, current size' "$Wc_c"
fi
# ============= libsipp/sipptypes.h ==============
if test -f 'libsipp/sipptypes.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/sipptypes.h (File already exists)'
else
echo 'x - extracting libsipp/sipptypes.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/sipptypes.h' &&
/*
X * sipptypes.h - typdefs in sipp not needed to be public.
X *
X * (c) Jonas Yngvesson 1989-12-04
X */
X
#ifndef SIPPTYPES_H
#define SIPPTYPES_H
X
X
/*
X * Temporary storage of transformed vertices.
X */
typedef struct view_coord_3d {
X    int                   y;
X    double                x, z;        /* Transformed vertex coordinates */
X    double                nx, ny, nz;  /* average normal */
X    double                u, v, w;     /* texture parameters */
X    struct view_coord_3d *next;        /* next vertex in the list */
} View_coord;
X
X
/*
X * Entry in the edge list used in rendering.
X */
typedef struct edges_3d {
X    int              y, y_stop;   /* Current point and interpolation steps */
X    double           x, xstep;            
X    double           z, zstep;
X    double           nx, nxstep;  /* Current normal and interp. steps */
X    double           ny, nystep;
X    double           nz, nzstep;
X    double           u, ustep;    /* Current texture coordinates and */
X    double           v, vstep;    /* interp. steps                   */
X    double           w, wstep;
X    int              polygon;     /* Uniqe polygon id of the polygon to */
X                                  /* which the edge belongs */
X    Surface         *surface;     /* Surface that the edge belongs to */
X    struct edges_3d *next;        /* Next edge on this scanline */
} Edge;
X
X
/*
X * Y-bucket to keep the edge lists
X */
typedef struct {
X    Edge *first, *last;   /* Firs and last entry in the list */
} Bucket;
X
X
/*
X * Objects installed in the database for rendering are kept
X * in a binary tree, internal to sipp. This database will
X * automatically contain all top level objects, but the user
X * can also force objects in or out of it.
X */
typedef struct inst_obj_t {
X    Object *object;
X    struct inst_obj_t *big;
X    struct inst_obj_t *sml;
} Inst_object;
X
X
#endif /* SIPPTYPES_H */
SHAR_EOF
chmod 0644 libsipp/sipptypes.h ||
echo 'restore of libsipp/sipptypes.h failed'
Wc_c="`wc -c < 'libsipp/sipptypes.h'`"
test 1885 -eq "$Wc_c" ||
	echo 'libsipp/sipptypes.h: original size 1885, current size' "$Wc_c"
fi
# ============= libsipp/torus.c ==============
if test -f 'libsipp/torus.c' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/torus.c (File already exists)'
else
echo 'x - extracting libsipp/torus.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/torus.c' &&
#include <xalloca.h>
#include <math.h>
X
#include <sipp.h>
X
X
static void
arr_rot(arr1, arr2, len, angle)
X    Vector arr1[];
X    Vector arr2[];
X    int    len;
X    double angle;
{
X    int    i;
X    double sa, ca;
X
X    sa = sin(angle);
X    ca = cos(angle);
X    for (i = 0; i < len; i++) {
X        arr2[i].x = arr1[i].x * ca - arr1[i].y * sa;
X        arr2[i].y = arr1[i].x * sa + arr1[i].y * ca;
X        arr2[i].z = arr1[i].z;
X    }
}
X
X
static void
push_band(arr1, arr2, len)
X    Vector arr1[];
X    Vector arr2[];
X    int    len;
{
X    int i, j;
X
X    for (i = 0; i < len; i++) {
X        j = (i + 1) % len;
X        vertex_tx_push(arr1[i].x, arr1[i].y, arr1[i].z, 
X                       arr1[i].x, arr1[i].y, arr1[i].z);
X        vertex_tx_push(arr2[i].x, arr2[i].y, arr2[i].z, 
X                       arr2[i].x, arr2[i].y, arr2[i].z);
X        vertex_tx_push(arr2[j].x, arr2[j].y, arr2[j].z, 
X                       arr2[j].x, arr2[j].y, arr2[j].z);
X        vertex_tx_push(arr1[j].x, arr1[j].y, arr1[j].z, 
X                       arr1[j].x, arr1[j].y, arr1[j].z);
X        polygon_push();
X    }
}
X
X
X
Object *
sipp_torus(bigradius, smallradius, res1, res2, surface, shader)
X    double  bigradius;      /* Radius of the ring */
X    double  smallradius;    /* Radius of the "tube" */
X    int     res1;           /* Number of polygons around the ring */
X    int     res2;           /* Number of polygons around the tube */
X    void   *surface;
X    Shader *shader;
{
X    Object *torus;
X    Vector *arr1;
X    Vector *arr2;
X    Vector *tmp;
X    int     i;
X
X    /* Create two arrays to hold vertices around the tube */
X    arr1 = (Vector *)alloca(res2 * sizeof(Vector));
X    arr2 = (Vector *)alloca(res2 * sizeof(Vector));
X
X    for (i = 0; i < res2; i++) {
X        arr1[i].x = bigradius + smallradius * cos(i * 2.0 * M_PI / res2);
X        arr1[i].y = 0.0;
X        arr1[i].z = smallradius * sin(i * 2.0 * M_PI / res2);
X    }
X
X    /* Sweep out the torus by rotating the two perimeters */
X    /* defined in arr1 and arr2. */
X    for (i = 0; i < res1; i++) {
X        arr_rot(arr1, arr2, res2, 2.0 * M_PI / (double)res1);
X        push_band(arr1, arr2, res2);
X        tmp = arr1;
X        arr1 = arr2;
X        arr2 = tmp;
X    }
X
X    torus = object_create();
X    object_add_surface(torus, surface_create(surface, shader));
X
X    return torus;
}
X
SHAR_EOF
chmod 0644 libsipp/torus.c ||
echo 'restore of libsipp/torus.c failed'
Wc_c="`wc -c < 'libsipp/torus.c'`"
test 2322 -eq "$Wc_c" ||
	echo 'libsipp/torus.c: original size 2322, current size' "$Wc_c"
fi
# ============= libsipp/xalloca.c ==============
if test -f 'libsipp/xalloca.c' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/xalloca.c (File already exists)'
else
echo 'x - extracting libsipp/xalloca.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/xalloca.c' &&
#ifdef HAVE_NO_ALLOCA
X
/*
X	alloca -- (mostly) portable public-domain implementation -- D A Gwyn
X
X	last edit:	86/05/30	rms
X	   include config.h, since on VMS it renames some symbols.
X	   Use xmalloc instead of malloc.
X
X	This implementation of the PWB library alloca() function,
X	which is used to allocate space off the run-time stack so
X	that it is automatically reclaimed upon procedure exit, 
X	was inspired by discussions with J. Q. Johnson of Cornell.
X
X	It should work under any C implementation that uses an
X	actual procedure stack (as opposed to a linked list of
X	frames).  There are some preprocessor constants that can
X	be defined when compiling for your specific system, for
X	improved efficiency; however, the defaults should be okay.
X
X	The general concept of this implementation is to keep
X	track of all alloca()-allocated blocks, and reclaim any
X	that are found to be deeper in the stack than the current
X	invocation.  This heuristic does not reclaim storage as
X	soon as it becomes invalid, but it will do so eventually.
X
X	As a special case, alloca(0) reclaims storage without
X	allocating any.  It is a good idea to use alloca(0) in
X	your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char	SCCSid[] = "@(#)alloca.c	1.1";	/* for the "what" utility */
#endif
X
#include "xalloca.h"
X
extern void	free();
X
/* ================================================================ */
/*      This is entered from general.h in the GNU shell bash.       */
X
X
#include <stdio.h>
X
/* **************************************************************** */
/*								    */
/*		   Memory Allocation and Deallocation.		    */
/*								    */
/* **************************************************************** */
X
static char *
xmalloc (size)
X     int size;
{
X    char *temp = (char *)malloc (size);
X    
X    if (!temp) {
X        fprintf (stderr, "Out of virtual memory!");
X        exit(1);
X    }
X
X    return (temp);
}
X
X
/* ================================================================ */
X
/*
X	Define STACK_DIRECTION if you know the direction of stack
X	growth for your system; otherwise it will be automatically
X	deduced at run-time.
X
X	STACK_DIRECTION > 0 => grows toward higher addresses
X	STACK_DIRECTION < 0 => grows toward lower addresses
X	STACK_DIRECTION = 0 => direction of growth unknown
*/
X
#ifndef STACK_DIRECTION
#define	STACK_DIRECTION	0		/* direction unknown */
#endif
X
#if STACK_DIRECTION != 0
X
#define	STACK_DIR	STACK_DIRECTION	/* known at compile-time */
X
#else	/* STACK_DIRECTION == 0; need run-time code */
X
static int	stack_dir;		/* 1 or -1 once known */
#define	STACK_DIR	stack_dir
X
static void
find_stack_direction (/* void */)
{
X  static char	*addr = NULL;	/* address of first
X				   `dummy', once known */
X  auto char	dummy;		/* to get stack address */
X
X  if (addr == NULL)
X    {				/* initial entry */
X      addr = &dummy;
X
X      find_stack_direction ();	/* recurse once */
X    }
X  else				/* second entry */
X    if (&dummy > addr)
X      stack_dir = 1;		/* stack grew upward */
X    else
X      stack_dir = -1;		/* stack grew downward */
}
X
#endif	/* STACK_DIRECTION == 0 */
X
/*
X	An "alloca header" is used to:
X	(a) chain together all alloca()ed blocks;
X	(b) keep track of stack depth.
X
X	It is very important that sizeof(header) agree with malloc()
X	alignment chunk size.  The following default should work okay.
*/
X
#ifndef	ALIGN_SIZE
#define	ALIGN_SIZE	sizeof(double)
#endif
X
typedef union hdr
{
X  char	align[ALIGN_SIZE];	/* to force sizeof(header) */
X  struct
X    {
X      union hdr *next;		/* for chaining headers */
X      char *deep;		/* for stack depth measure */
X    } h;
} header;
X
/*
X	alloca( size ) returns a pointer to at least `size' bytes of
X	storage which will be automatically reclaimed upon exit from
X	the procedure that called alloca().  Originally, this space
X	was supposed to be taken from the current stack frame of the
X	caller, but that method cannot be made to work for some
X	implementations of C, for example under Gould's UTX/32.
*/
X
static header *last_alloca_header = NULL; /* -> last alloca header */
X
pointer
alloca (size)			/* returns pointer to storage */
X     unsigned	size;		/* # bytes to allocate */
{
X  auto char	probe;		/* probes stack depth: */
X  register char	*depth = &probe;
X
#if STACK_DIRECTION == 0
X  if (STACK_DIR == 0)		/* unknown growth direction */
X    find_stack_direction ();
#endif
X
X  /* Reclaim garbage, defined as all alloca()ed storage that
X     was allocated from deeper in the stack than currently. */
X  {
X    register header	*hp;	/* traverses linked list */
X
X    for (hp = last_alloca_header; hp != NULL;)
X      if (STACK_DIR > 0 && hp->h.deep > depth
X	  || STACK_DIR < 0 && hp->h.deep < depth)
X	{
X	  register header	*np = hp->h.next;
X
X	  free ((pointer) hp);	/* collect garbage */
X
X	  hp = np;		/* -> next header */
X	}
X      else
X	break;			/* rest are not deeper */
X
X    last_alloca_header = hp;	/* -> last valid storage */
X  }
X
X  if (size == 0)
X    return NULL;		/* no allocation required */
X
X  /* Allocate combined header + user data storage. */
X
X  {
X    register pointer	new = xmalloc (sizeof (header) + size);
X    /* address of header */
X
X    ((header *)new)->h.next = last_alloca_header;
X    ((header *)new)->h.deep = depth;
X
X    last_alloca_header = (header *)new;
X
X    /* User storage begins just after header. */
X
X    return (pointer)((char *)new + sizeof(header));
X  }
}
X
#endif  /* HAVE_NO_ALLOCA */
SHAR_EOF
chmod 0644 libsipp/xalloca.c ||
echo 'restore of libsipp/xalloca.c failed'
Wc_c="`wc -c < 'libsipp/xalloca.c'`"
test 5405 -eq "$Wc_c" ||
	echo 'libsipp/xalloca.c: original size 5405, current size' "$Wc_c"
fi
# ============= libsipp/xalloca.h ==============
if test -f 'libsipp/xalloca.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/xalloca.h (File already exists)'
else
echo 'x - extracting libsipp/xalloca.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/xalloca.h' &&
#ifdef HAVE_NO_ALLOCA
X
#ifdef X3J11
typedef void	*pointer;		/* generic pointer type */
pointer alloca (unsigned);		/* returns pointer to storage */
#else
typedef char	*pointer;		/* generic pointer type */
pointer alloca ();			/* returns pointer to storage */
#endif /* X3J11 */
X
#else
X
#include <alloca.h>
X
#endif
SHAR_EOF
chmod 0644 libsipp/xalloca.h ||
echo 'restore of libsipp/xalloca.h failed'
Wc_c="`wc -c < 'libsipp/xalloca.h'`"
test 314 -eq "$Wc_c" ||
	echo 'libsipp/xalloca.h: original size 314, current size' "$Wc_c"
fi
# ============= doc/primitives.man ==============
if test ! -d 'doc'; then
    echo 'x - creating directory doc'
    mkdir 'doc'
fi
if test -f 'doc/primitives.man' -a X"$1" != X"-c"; then
	echo 'x - skipping doc/primitives.man (File already exists)'
else
echo 'x - extracting doc/primitives.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/primitives.man' &&
.\" Copyright 1990, Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH PRIMITIVES 3X "December , 1990" 3X
.SH NAME
primitives - a collection of geometric primitives for \fIsipp\fR.
.SH SYNOPSIS
\fI#include <primitives.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
X
.SH DESCRIPTION
\fIsipp\fR gives the user access to a number of rather low level functions
to create polygons, surfaces and objects. This manual describes a set of
functions that use the low level functions in \fIsipp\fR to create
geometric primitives. Each primitive is a complete \fIsipp\fR object.
.sp
All primitives described here will get texture coordinates equal to the
respective world coordinates.
X
.SH PRIMITIVES
.IP \fIObject\ *sipp_torus(bigradius,\ smallradius,\ res1,\ res2,\ surface,\ shader)\fR
.br
\fIdouble\  bigradius;\fR
.br
\fIdouble\  smallradius;\fR
.br
\fIint\     res1;\fR
.br
\fIint\     res2;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_torus()\fR creates a torus centered about the origin and with the
z-axis pointing up through the ring. \fIbigradius\fR is the radius of the
ring and \fIsmallradius\fR is the radius of the "tube" itself. \fIres1\fR
is the number of polygons that will be created radially around the ring
and \fIres2\fR is the number of polygons that will be created around the
tube. \fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the torus.
X
.IP \fIObject\ *sipp_cylinder(radius,\ length,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\  radius;\fR
.br
\fIdouble\  length;\fR
.br
\fIint\     resolution;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_cylinder()\fR creates a cylinder centered about the origin and with the
z-axis along the cylinders main axis. \fIradius\fR and \fIlength\fR
defines the size of the cylinder. \fIresolution\fR
is the number of polygons that will be created radially around the rim.
\fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the cylinder.
X
.IP \fIObject\ *sipp_ellipsoid(x_rad,\ y_rad,\ z_rad,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\  x_rad;\fR
.br
\fIdouble\  y_rad;\fR
.br
\fIdouble\  z_rad;\fR
.br
\fIint\     resolution;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_ellipsoid()\fR creates a ellipsoid centered about the origin.
\fIx_rad\fR, \fIy_rad\fR and \fIz_rad\fR
defines the size of the ellipsoid. \fIresolution\fR
is the number of polygons that will be created around it's "equator".
\fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the ellipsoid.
X
.IP \fIObject\ *sipp_sphere(radius,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\  radius;\fR
.br
\fIint\     resolution;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_sphere()\fR creates a sphere centered about the origin.
\fIradius\fR defines the size of the sphere. \fIresolution\fR
is the number of polygons that will be created around it's "equator".
\fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the sphere.
X
.IP \fIObject\ *sipp_block(x_size,\ y_size,\ z_size,\ surface,\ shader)\fR
.br
\fIdouble\  x_size;\fR
.br
\fIdouble\  y_size;\fR
.br
\fIdouble\  z_size;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_block\fR creates a square block with the size defined by \fIx_size\fR,
\fIz_size\fR and \fIz_size\fR. The block is centered about the
origin. \fIsurface\fR is the surface description used by \fIshader()\fR which
is the shading function used when shading the block.
X
.IP \fIObject\ *sipp_cube(side,\ surface,\ shader)\fR
.br
\fIdouble\  side;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_cube()\fR creates a cube with the side of length \fIside\fR.  The
cube is centered about the origin. \fIsurface\fR is the surface description
used by \fIshader()\fR which is the shading function used when shading the
cube.
X
.IP \fIObject\ *sipp_bezier(file,\ res,\ surface,\ shader)\fR
.br
\fIFILE\   *file;\fR
.br
\fIint\     res;\fR
.br
\fIvoid\   *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_bezier()\fR reads a file containing descriptions of a set of bezier
patches or bezier curves. If the file contains descriptions of patches, these
patches will be tesselated into \fIres\fR by \fIres\fR polygons and installed
in a \fIsipp\fR object as one surface. The surface will be shaded by
\fIshader\fR using the surface description \fIsurface\fR.
.sp
If the file contains descriptions of curves, a rotational surface will be
created by rotating these curves about the y-axis. The resulting surface will
be tesselated into polygons and installed in a \fIsipp\fR object as one
surface. The surface will be shaded by \fIshader\fR using the surface
description \fIsurface\fR.
.sp
The format of the description file is rather simple. First a keyword defining
the type of description in the file, \fIbezier_curves:\fR or
\fIbezier_patches:\fR. Then follows a description of the vertices (control
points). First the word \fIvertices:\fR followed by an integer number that
tells how many vertices there are in the description, then the word
\fIvertex_list:\fR followed by the x, y and z coordinates for each vertex. The
number of vertices must be same as the number given above. This is, however,
not checked for. 
.sp
If the file contains curves, the keyword \fIcurves:\fR followed by the number
of bezier curves in the file stand on the next line. After this line, a line
with the single keyword \fIcurve_list:\fR follows. Lastly, the bezier curves
themselves follow as numbers in groups of four by four. Each number is an
index into the vertex list with the first index having number 1.
.sp
If the file contains patches, the format is the same with the following
exceptions: The word \fIpatches:\fR is substituted for \fIcurves:\fR, the word
\fIpatch_list:\fR is substituted for \fIcurve_list:\fR and the indices into
the vertex list are grouped 16 by 16 instead of 4 by 4.
.sp
Comments can be inserted anywhere in a bezier curve/patch description file by
using the hashmark character, #. The comment lasts to the end of the line.
.sp
Example: the body of a standard Newell teapot.
.sp
.nf
# Bezier curves (rotational body) for teapot body.
X
bezier_curves:
X
vertices: 10
vertex_list:
X    3.500000E-01    5.625000E-01    0.000000E+00
X    3.343750E-01    5.953125E-01    0.000000E+00
X    3.593750E-01    5.953125E-01    0.000000E+00
X    3.750000E-01    5.625000E-01    0.000000E+00
X    4.375000E-01    4.312500E-01    0.000000E+00
X    5.000000E-01    3.000000E-01    0.000000E+00
X    5.000000E-01    1.875000E-01    0.000000E+00
X    5.000000E-01    7.500000E-02    0.000000E+00
X    3.750000E-01    1.875000E-02    0.000000E+00
X    3.750000E-01    0.000000E+00    0.000000E+00
X
curves:    3
curve_list:
X
X  1 2 3 4
X
X  4 5 6 7
X
X  7 8 9 10
X
#End of teapot bezier file
.fi
X
.SH SEE ALSO
sipp(3X) - simple polygon processor, a 3d-graphics library
.br
shaders(3X) - a collection of shaders for \fIsipp\fR.
X
.SH AUTHORS
Jonas Yngvesson\	\	(jonas-y@isy.liu.se)
.br
Inge Wallin\		(ingwa@isy.liu.se)
X
.SH BUGS
The format for the bezier patches and curves is prohibitively ugly.
SHAR_EOF
chmod 0644 doc/primitives.man ||
echo 'restore of doc/primitives.man failed'
Wc_c="`wc -c < 'doc/primitives.man'`"
test 7416 -eq "$Wc_c" ||
	echo 'doc/primitives.man: original size 7416, current size' "$Wc_c"
fi
# ============= doc/shaders.man ==============
if test -f 'doc/shaders.man' -a X"$1" != X"-c"; then
	echo 'x - skipping doc/shaders.man (File already exists)'
else
echo 'x - extracting doc/shaders.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/shaders.man' &&
.\" Copyright 1990, Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH SHADERS 3X "December , 1990" 3X
.SH NAME
shaders - a collection of shaders for \fIsipp\fR.
.SH SYNOPSIS
\fI#include <sipp.h>\fR
.br
\fI#include <shaders.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
X
.SH DESCRIPTION
\fIsipp\fR provides the user with a simple shading model and a shading
function called \fIbasic_shader()\fR. Each shader takes a description of
the surface parameters and the structure used for \fIbasic_shader()\fR
is called \fISurf_desc\fR. See \fIsipp\fR(3X) for more details about
shaders and their parameters.
.sp
This manual describes the parameters for a \fIsipp\fR shading functions and a
set of shaders beside \fIbasic_shader()\fR that are included in the library.
All shaders described here provide some kind of special effect on a surface
and call \fIbasic_shader()\fR to do the actual shading calculations.
X
.SH SIPP SHADING FUNCTIONS
Each surface in a scene has a shading function associated with it.
This function is called for each pixel in the surface as it is
rendered. \fIsipp\fR has an internal basic shading function called
\fIbasic_shader\fR that can be used in most cases. \fIbasic_shader\fR
provides a somewhat modified and simplified version of Blinn's shading
model, taking a \fISurf_desc\fR as a description of the surface. 
.sp
If the user is not satisfied with the builtin shader, he can provide
his own shader and surface description struct. All shaders take
the same parameters and must be defined as follows:
.sp
\fIvoid\ myshader(nx,\ ny,\ nz,\ \ u,\ v,\ w,\ view_vec,\fR
.br
\fI		lights,\ surface,\ color)\fR
.br
\fI	double nx, ny, nz;\fR
.br
\fI	double u, v, w;\fR
.br
\fI	Vector\ view_vec;\fR
.br
\fI	Lightsource *lights;\fR
.br
\fI	void *surface;\fR
.br
\fI	Color\ *color;\fR
.sp
\fInx, ny\fR and \fInz\fR is the \fInon-normalized\fR surface normal at the
point that should be rendered.
.br
\fIu, v\fR and \fIw\fR are the interpolated texture coordinates at the rendered
point. If no texture coordinates have been given at some vertices these
values are undefined and contains garbage at best.
.br
\fIview_vec\fR is a normalized vector, pointing from the rendered
point at the viewpoint.
.br
\fIlights\fR is a pointer to a linked list of lightsource descriptions. See
the function \fIlightsource_push()\fR for a description of the structure of
the links.
.br
\fIsurface\fR is the same \fIsurface\fR-pointer that was sent to the
function \fIsurface_create()\fR. In the case of \fIbasic_shader\fR this is
a pointer to a \fISurf_desc\fR. If the user provides his own shader, he
can also provide his own surface description.
.br
Upon return, the shader should place the calculated rgb colour
components in the areas pointed to by \fIcolor\fR. The rgb components
must be values between 0 and 1.
X
.SH SHADERS AND SURFACE DESCRIPTORS
The following shader functions are provided with the \fIsipp\fR library. 
X
.IP \fImarble_shader()\fR
\fImarble_shader()\fR creates a simulated marble texture on a surface.
It uses two colors, one as the base material and one as the
interspersed material. The interspersed material is put into the
base material in strips that are distorted using \fInoise()\fR and
\fIturbulence()\fR. 
.sp
The surface description for a marble surface is called
\fIMarble_desc\fR and is defined as follows:
.br
\fItypedef struct {\fR
.br
\fI\    double   ambient;\fR
.br
\fI\    double   specular;\fR
.br
\fI\    double   c3;\fR
.br
\fI\    double   scale;\fR
.br
\fI\    Color    base;\fR
.br
\fI\    Color    strip;\fR
.br
\fI} Marble_desc;\fR
.sp
Except for the two colors and the field \fIscale\fR, \fIMarble_desc\fR
looks exactly like a \fISurf_desc\fR and the fields are used in the
same way. 
.br
\fIscale\fR is a factor which determines the size of the
marble pattern depending on the size of the texture coordinate system
in relation to the world coordinate system. You will have to
experiment some to get this right.
.br
\fIbase\fR is the color of the base material, and \fIstrip\fR is the
color of the interspersed material.
X
.IP \fIgranite_shader()\fR
\fIgranite_shader()\fR is very similar to \fImarble_shader()\fR in
that it also
mixes two colors using \fInoise()\fR and \fIturbulence()\fR. The
difference is in 
how the mixing is done. The two colors are mixed whithout treating
them separately in any way. 
.sp
The surface description used in \fIgranite_shader()\fR is called
\fIGranite_desc\fR and is defined as follows:
.br
\fItypedef struct {\fR
.br
\fI\    double   ambient;\fR
.br
\fI\    double   specular;\fR
.br
\fI\    double   c3;\fR
.br
\fI\    double   scale;\fR
.br
\fI\    Color    col1;\fR
.br
\fI\    Color    col2;\fR
.br
\fI} Granite_desc;\fR
.sp
The fields have the same meaning as in \fIMarble_desc\fR.
X
.IP \fIbozo_shader()\fR
\fIbozo_shader()\fR uses \fInoise()\fR to chose a color from a fixed set.
The range of possible return value from \fInoise()\fR are divided into parts
of equal size and each part is assigned a color. The size of the parts
are dependent on the number of colors.
.sp
The surface description is called \fIBozo_desc\fR and is defined as
follows:
.br
\fItypedef struct {\fR
.br
\fI\    Color   *colors;\fR
.br
\fI\    int      no_of_cols;\fR
.br
\fI\    double   ambient;\fR
.br
\fI\    double   specular;\fR
.br
\fI\    double   c3;\fR
.br
\fI\    double   scale;
.br
\fI} Bozo_desc;\fR
.sp
\fIcolors\fR is a pointer to an array of \fIColor\fR structs and
\fIno_of_cols\fR defines the number of entries in this array. The other
fields have the same function as in the prevoiusly described shaders.
X
.IP \fImask_shader()\fR
\fImask_shader()\fR uses another image (ususally a bitmap) as a mask,
and calls two different shaders depending on the values in this image.
The mask image can be of any format. The user supplies a pointer
to the image and a function that tests the value of a certain pixel in it.
The mapping uses only the \fIu\fR and \fIv\fR texture coordinates.
.sp
The surface description is called \fIMask_desc\fR and has the
following definition:
.br
\fItypedef struct {\fR
.br
\fI\    Shader *fg_shader;\fR
.br
\fI\    void   *fg_surface;\fR
.br
\fI\    Shader *bg_shader;\fR
.br
\fI\    void   *bg_surface;\fR
.br
\fI\    void   *mask;\fR
.br
\fI\    bool  (*pixel_test)();\fR
.br
\fI\    int x0, y0;\fR
.br
\fI\    int xsize, ysize;\fR
.br
\fI\    double xscale, yscale;\fR
.br
\fI} Mask_desc;\fR
.sp
\fIfg_shader\fR is used together with the surface description
\fIfg_surface\fR when \fIpixel_test\fR (see below) returns TRUE.
.br
\fIbg_shader\fR is used together with the surface description
\fIbg_surface\fR when \fIpixel_test\fR (see below) returns FALSE.
.br
\fImask\fR is a pointer to the image. This could be a pointer to a raw array
of pixels or a complicated struct, the image representation is completely up
to the user.
.br
\fIpixel_test\fR is a function that is called to evaluate pixels in the mask
image. This function should be declared as follows:
.br
\fI\ bool my_pixel_test(image, x, y)\fR
.br
\fI\     my_image_struct *image;\fR
.br
\fI\     int              x, y;\fR
.br
\ \ \fIimage\fR is the same pointer that is stored in the \fIMask_desc\fR.
.br
\ \ \fIx\fR and \fIy\fR are the coordinates of the pixel that should be
tested.
.br
\fIx0\fR and \fIy0\fR define where (in mask image coordinates) the
origo of the texture coordinate system should be placed.
.br
\fIxsize\fR and \fIysize\fR is the size of the mask image.
.br
\fIxscale\fR and \fIyscale\fR scales the texture coordinate system
relative the mask image coordinates.
X
.IP \fIbumpy_shader()\fR
\fIbumpy_shader()\fR is a function that perturbates the normal of a
surface using \fIDnoise()\fR. Any other shader can be used to do the final
shading calculations. 
.sp
The surface description is called \fIBumpy_desc\fR and is defined as
follows:
.br
\fItypedef struct {\fR
.br
\fI\    Shader *shader;\fR
.br
\fI\    void   *surface;\fR
.br
\fI\    double scale;\fR
.br
\fI\    bool   bumpflag;\fR
.br
\fI\    bool   holeflag;\fR
.br
\fI} Bumpy_desc;\fR
.sp
\fIshader\fR and \fIsurface\fR define the shader to be used for the
final shading calculations. 
.br
\fIscale\fR has the same meaning as in previous shaders using \fInoise()\fR.
.br
\fIbumpflag\fR and \fIholeflag\fR make it possible to flatten out
half of the bumps. If only \fIbumpflag\fR is TRUE only bumps "standing
out" from the surface are visible. The rest of the surface will be smooth.
If, on the other hand, only \fIholeflag\fR is TRUE only bumps going
"into" the surface will be visible, thus giving the surface an
eroded look. If both flags are true, the whole surface will get a
bumpy appearence, rather like an orange.
X
.IP \fIplanet_shader()\fR
\fIplanet_shader()\fR is a somewhat specialized shader that produces a texture
that resembles a planet surface. The planet is of the Tellus type with a
mixture of oceans and continents. Some of the surface is covered by
semi-transparent clouds which enhances the effect greatly. On the other hand,
no polar caps are provided and this decreses the realism.
.sp
The texture is 3-dimensional, so it is possible to create cube planets or even
planets with cut-out parts that still have surfaces that resemble the earth
surface. The texture is not scalable, and is designed to be used with texture
coordinats in the range -1.0 to 1.0, e.g. a unit sphere. Of course the woorld
coordinats need not have the same order of magnitude.
.sp
\fIplanet_shader()\fR uses an ordinary \fISurf_desc\fR in which the
\fIcolor\fR field is not used.
X
.SH SEE ALSO
sipp(3X) - simple polygon processor, a 3d-graphics library
.br
primitives(3X) - a collection of geometric primitives for \fIsipp\fR.
X
.SH AUTHORS
Jonas Yngvesson\	\	(jonas-y@isy.liu.se)
.br
Inge Wallin\		(ingwa@isy.liu.se)
X
.SH BUGS
The planet texture should be enhanced with polar caps and it should be
possible to give parameters to control, among other factors, the ratio of
ocean/land and the cloudiness.
SHAR_EOF
chmod 0644 doc/shaders.man ||
echo 'restore of doc/shaders.man failed'
Wc_c="`wc -c < 'doc/shaders.man'`"
test 10071 -eq "$Wc_c" ||
	echo 'doc/shaders.man: original size 10071, current size' "$Wc_c"
fi
true || echo 'restore of doc/sipp.man failed'
echo End of part 4, continue with part 5
exit 0

-- 
Inge Wallin               | Thus spake the master programmer:               |
                          |      "After three days without programming,     |
ingwa@isy.liu.se          |       life becomes meaningless."                |
                          | Geoffrey James: The Tao of Programming.         |


exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.