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

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

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

#!/bin/sh
# This is part 05 of sipp-2.0
# ============= doc/sipp.man ==============
if test ! -d 'doc'; then
    echo 'x - creating directory doc'
    mkdir 'doc'
fi
if test -f 'doc/sipp.man' -a X"$1" != X"-c"; then
	echo 'x - skipping doc/sipp.man (File already exists)'
else
echo 'x - extracting doc/sipp.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/sipp.man' &&
.\" Copyright 1990, Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH SIPP 3X "December , 1990" 3X
.SH NAME
sipp - simple polygon processor, a 3d-graphics library
.SH SYNOPSIS
\fI#include <sipp.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
.SH DESCRIPTION
\fIsipp\fR is a library for creating 3-dimensional scenes and rendering them
using a scan-line z-buffer algorithm. A scene is built up of objects
which can be transformed with rotation, translation and scaling. The
objects form hierarchies where each object can have arbitrarily many
subobjects and subsurfaces. A surface is a number of connected
polygons which are rendered with Phong interpolation of the surface
normals.
.sp
The library has an internal database for the objects that is to be
rendered. Objects can be installed in, and removed from, this database
at any time.
.sp
The library also provides 3-dimensional texture mapping with automatic
interpolation of texture coordinates. Simple anti-aliasing is performed
through double oversampling. A scene can be illuminated by an
arbitrary number of light sources. A basic shading algorithm is
provided with the library, but the user can also use his own shading
algorithms for each surface to produce special effects. Images are
produced in the Portable Pixmap format (ppm) for which many utilities
exist.
X
.SH USAGE
Before any other function in \fIsipp\fR is used, the function
\fIsipp_init()\fR must always be called. This call initiates the
internal database and other global variables. The rest of this section
describes the ideas behind \fIsipp\fR and outlines its usage. See the
section 
.B FUNCTIONS
for details.
.sp
All objects in \fIsipp\fR are built up of polygons with 3 or more
vertices. The polygons can either be concave or convex, but all
vertices must lie in the same plane. No test is done to assertain
this, however. A number of polygons can form a, possibly non-planar,
surface that is rendered using Phong interpolation of the surface
normals. Surfaces are grouped together into objects which can also
have other objects as subobjects. Each object or subobject can be
transformed using the standard transformations: rotation, scaling and
translation. All transformations are done with respect to the parent
object if the object is a subobject and the world if the object is a
top level object.
.sp
When an object is defined, copies can be made of it and it can be
installed into the internal database for rendering. The installation
doesn't affect the object in any way, i.e. it can still be transformed
and copied. This is useful if more pictures than one is to be created,
e.g. in an animation.
.sp
\fIsipp\fR uses a number of stacks to create a scene. First,
\fIvertices\fR of a polygon are pushed onto a \fIvertex stack\fR. When
all vertices in a polygon are pushed, a \fIpolygon\fR is created from
them and is pushed onto a \fIpolygon stack\fR. When a number of
polygons have been pushed, a call to a function in \fIsipp\fR combine
them into a \fIsurface\fR and returns a pointer to the surface. This
surface can then be inserted into an \fIobject\fR together with other
surfaces.  Objects can be transformed, used as subobjects in other
objects and inserted into the scene database.
.sp
To create a polygon, two functions are used: \fIvertex_push()\fR and
\fIpolygon_push()\fR. Variants of these functions exist, but these are
the simple forms that are the easiest to use. A call to
\fIvertex_push()\fR is done for each vertex in the polygons, going
counter clockwise around the edge. The order in which the vertices are
pushed is important, because this determines the front and the back
face of the polygon. When all polygons are pushed onto the vertex
stack, \fIpolygon_push()\fR is called. This call creates a polygon
structure out of the pushed vertices, deletes them from the vertex
stack, and pushes the newly created polygon onto the polygon stack.
.sp
When all polygons in a surface is on the polygon stack,
\fIsurface_create()\fR (or one of it's variants) will create a surface
out of them and empty the polygon stack for a new surface definition.
\fIsurface_create()\fR returns a pointer to the created surface.
.sp
An object is created with the function \fIobject_create()\fR. This
function returns a pointer to an empty object, i.e. it contains no
surfaces or subobjects. Surfaces and subobjects are added to an object
with the functions \fIobject_add_surface()\fR and \fIobject_add
subobj()\fR. When all surfaces and subobjects are added to the object
it can be installed in the rendering database, or removed from it,
with the functions \fIobject_install()\fR and \fIobject_uninstall()\fR
respectively.
X
.SH DATA TYPES
The \fIsipp\fR library defines a number of data types in the file
\fIsipp.h\fR. These data types are:
.IP \fIbool\fR
.br
\fIbool\fR can be used as a boolean type, with values \fITRUE\fR of
\fIFALSE\fR. These constants are also defined in \fIsipp.h\fR.
X
.IP \fIColor\fR
\fIColor\fR is a struct with three members, \fIred\fR, \fIgrn\fR and
\fIblu\fR.  Each member of the struct is a double that should be in
the range [0,1].
X
.IP \fIVector\fR
A \fIVector\fR is a struct with three members, \fIx\fR, \fIy\fR and
\fIz\fR which are all doubles.
X
.IP \fITransf_mat\fR
\fITransf_mat\fR is a standard 4 x 4 homogenous transformation matrix.
Actually it is stored as a 4 x 3 matrix to save memory, since the
rightmost column is only needed in the viewing calculation.
.sp
The members of a \fITransf_mat\fR should never be accessed directly, but
rather through the abstract functions described in the \fBFUNCTIONS\fR
section. 
X
.IP \fISurface\fR\ and\ \fIObject\fR
\fISurface\fR and \fIObject\fR are both opaque types used by \fIsipp\fR. The
actual definition of them is not important to the user.
X
.IP \fISurf_desc\fR
A \fISurf_desc\fR is a surface description, used by the built-in shader to
determine properties about a surface. The definition of \fISurf_desc\fR is as
follows: 
.br
\fItypedef\ struct {\fR
.br
\fI    double\  ambient;\fR\       /* Fraction of color visible in ambient light */
.br
\fI    double\  specular;\fR\      /* Fraction of colour specularly reflected */
.br
\fI    double\  c3;\fR\            /* "Shininess" 0 = shiny,  1 = dull */
.br
\fI    Color\   color;\fR\         /* Colour of the surface */
.br
\fI}\ Surf_desc;\fR
X
.IP \fILightsource\fR
All lightsources in the scene are kept in a linked list where the
nodes are defined like this:
.sp
.I typedef struct lightsource {
.br
\fI\    double intensity;\fR
.br
\fI\    Vector dir;\fR
.br
\fI\    struct lightsource *next;\fR
.br
.I } Lightsource;
.sp
A pointer to the head of this list is sent to the shader.
X
.SH 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 FUNCTIONS
X
.IP \fIvoid\ sipp_init()\fR
Initializes the whole library and emptys the internal database. This
function must be called before any other function in the library.
X
.IP \fIvoid\ vertex_push(x,\ y,\ z)\fR
.br
\fIdouble\ x,\ y,\ z;\fR
.sp
Push a vertex onto the internal vertex stack.
.br
Note: Vertices must be pushed on the vertex stack
\fIcounterclockwize\fR when looking at the "front" face of the
polygon. Otherwize the front of the surface will be defined in the
wrong direction.
X
.IP \fIvoid\ vertex_tx_push(x,\ y,\ z,\ u,\ v,\ w)\fR
.br
\fIdouble\ x,\ y,\ z;\fR
.br
\fIdouble\ u,\ v,\ w;\fR
.sp
Push a vertex and it's texture coordinates onto the vertex stack. Three texture
coordinates are provided to make it possible to use both 2d and solid texture.
The texture coordinates are interpolated between vertices on the same object
and are \fInot\fR affected by transformations of the object. The interpolated
coordinates will be sent to the shader. The coordinates can of course be used
to hold any attribute that one whishes to interpolate between vertices and
then use in the shader.
X
.IP \fIvoid\ polygon_push()\fR
Create a polygon from the vertices on the vertex stack and push it
onto the polygon stack. The vertex stack is empty and ready for a new
polygon definition after this operation.
.br
If a vertex in the polygon is already defined in a previous polygon
that belongs to the same surface, the same vertex will be referenced,
i.e. vertices shared between polygons are only stored once, but they
must be repeated when defining the polygons.
X
.IP \fISurface\ *surface_create(surf_desc,\ shader)\fR
.br
\fIvoid\ *surf_desc;\fR
.br
\fIShader\ *shader;\fR
.sp
Create a surface from the polygons on the polygon stack. A pointer
to the newly-created surface is returned. The polygon stack is empty
afterwards. \fIshader\fR is a pointer to the shader function that
will be called when a point on this surface is to be rendered. See the
section \fBSHADER FUNCTIONS\fR for a declaration of the shader function.
\fIsurf_desc\fR is a pointer to a static structure that contains the
surface properties of the surface. The exact representation of this
structure can be chosen freely by the user depending on the
implementation of his shader. If the internal shader,
\fIbasic_shader\fR is used, this struct is of type \fISurf_desc\fR.
X
.IP \fISurface\ *surface_basic_create(ambient,\ red,\ grn,\ blu,\ specular,\ c3)\fR
.br
\fIdouble\ ambient;\fR
.br
\fIdouble\ red,\ grn,\ blu;\fR
.br
\fIdouble\ specular;\fR
.br
\fIdouble\ c3;\fR
.sp
Create a surface from the polygons on the polygon stack.  A pointer to
the newly-created surface is returned.  The surface will be shaded
with the internal shader, \fIbasic_shader\fR, using the parameters as
values in a \fISurf_desc\fR struct.
X
.IP \fIvoid\ surface_set_shader(surface,\ surf_desc,\ shader)\fR
.br
\fISurface\ *surface;\fR
.br
\fIvoid\    *surf_desc;\fR
.br
\fIShader\  *shader;\fR
.sp
Set the surface \fIsurface\fR to be shaded with the shading function
\fIshader\fR. The shading information used by the shader is pointed at
by \fIsurf_desc\fR.
X
.IP \fIvoid\ surface_basic_shader(surface,\ ambient,\ red,\ grn,\ blu,\ specular,\ c3)\fR
.br
\fISurface\ *surface;\fR
.br
\fIdouble\  ambient;\fR
.br
\fIdouble\  red,\ grn,\ blu;\fR
.br
\fIdouble\  specular;\fR
.br
\fIdouble\  c3;\fR
.sp
Set \fIsurface\fR to be shaded by the internal shader and let
\fIambient\fR, \fIred\fR, \fIgrn\fR, \fIblu\fR, \fIspecular\fR and
\fIc3\fR be the values stored in the \fISurf_desc\fR struct for this
surface. 
X
.IP \fIObject\ *object_create()\fR
Create an empty object, i.e. an object with no surfaces or subobjects
in it. The transformation matrix in the new object will be a identity
matrix initially.
X
.IP \fIObject\ *object_instance(obj)\fR
.br
\fIObject\ *obj;\fR
.sp
Create a new instance of a previously defined object. The lists of
surfaces and subobjects in \fIobj\fR are not copied, but a new
reference with its own transformation matrix is created. The matrix is
set to the identity matrix. If \fIobj\fR is changed, i.e. if one of its
subobjects or surfaces are transformed, one is deleted or added, the
change will also be seen in the copy.
X
.IP \fIObject\ *object_dup(obj)\fR
.br
\fIObject\ *obj;\fR
.sp
Copy recursively an object and its subobjects. The
surfaces in the object tree are not copied, only new references to them
are made.
X
.IP \fIObject\ *object_deep_dup(obj)\fR
.br
\fIObject\ *obj;\fR
.sp
Copy the entire tree for the object \fIobj\fR, including subobjects
and all surfaces, polygons and vertices. This is a costly operation if
the object is complex.
X
.IP \fIvoid\ object_delete(obj)\fR
.br
\fIObject\ *obj;\fR
.sp
Delete the object \fIobj\fR, i.e. the memory used by \fIobj\fR and
all its subobjects and surfaces is recursively freed. \fIsipp\fR keeps
track of internal references so objects and surfaces referenced
from somewhere else in \fIsipp\fR will not be deleted, i.e. no dangeling
references are created in the data structures.
X
.IP \fIvoid\ object_install(obj)\fR
.br
\fIObject\ *obj;\fR
.sp
Install the object \fIobj\fR into the rendering database. This
function must be called on all objects that are to be visible in the
rendered image.
X
.IP \fIvoid\ object_uninstall(obj)\fR
.br
\fIObject\ *obj;\fR
.sp
Remove the object \fIobj\fR from the rendering database. If \fIobj\fR
is not in the database to begin with, nothing happens.
X
.IP \fIvoid\ object_add_surface(obj,\ surf)\fR
.br
\fIObject\  *obj;\fR
.br
\fISurface\ *surf;\fR
.sp
Add the surface \fIsurf\fR to the object \fIobj\fR.
X
.IP \fIvoid\ object_add_subobj(obj,\ subobj)\fR
.br
\fIObject\ *obj;\fR
.br
\fIObject\ *subobj;\fR
.sp
Add the subobject \fIsubobj\fR to the object \fIobj\fR.
X
.IP \fIvoid\ object_set_transf(obj,\ matrix)\fR
.br
\fIObject\     *obj;\fR
.br
\fITransf_mat\ *matrix;\fR
.sp
Set the transformation matrix of the object \fIobj\fR to \fImatrix\fR.
.br
X
.IP \fIvoid\ object_clear_transf(obj)\fR
.br
\fIObject\     *obj;\fR
.sp
Set the transformation matrix of the object \fIobj\fR to the unit matrix.
.br
X
.IP \fIvoid\ object_transform(obj,\ matrix)\fR
.br
\fIObject\     *obj;\fR
.br
\fITransf_mat\ *matrix;\fR
.sp
Post multiply the matrix \fImatrix\fR into the transformation matrix
of the object \fIobj\fR.
X
.br
X
.IP \fIvoid\ object_rot_x(obj,\ ang)\fR
.br
\fIObject\  *obj;\fR
.br
\fIdouble\  ang;\fR
.sp
Rotate the object \fIobj\fR the angle \fIang\fR about the X axis.
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ object_rot_y(obj,\ ang)\fR
.br
\fIObject\  *obj;\fR
.br
\fIdouble\  ang;\fR
.sp
Rotate the object \fIobj\fR the angle \fIang\fR about the Y axis.
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ object_rot_z(obj,\ ang)\fR
.br
\fIObject\  *obj;\fR
.br
\fIdouble\  ang;\fR
.sp
Rotate the object \fIobj\fR the angle \fIang\fR about the Z axis.
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ object_rot(obj,\ point,\ vec,\ ang)\fR
.br
\fIObject\ *obj;\fR
.br
\fIVector\ *point;\fR
.br
\fIVector\ *vec;\fR
.br
\fIdouble\ ang;\fR
.sp
Rotate the object \fIobj\fR the angle \fIang\fR about the line
given by the point \fIpoint\fR and the vector \fIvec\fR starting in
that point. \fIang\fR is expressed in radians.
.br
X
.IP \fIvoid\ object_scale(obj,\ xscale,\ yscale,\ zscale)\fR
.br
\fIObject\ *obj;\fR
.br
\fIdouble\ xscale,\ yscale,\ zscale;\fR
.sp
Scale the object \fIobj\fR with the scaling factors \fIxscale,\
yscale\fR and \fIzscale\fR in the main directions respectively.
X
.IP \fIvoid\ object_move(obj,\ dx,\ dy,\ dz)\fR
.br
\fIObject\ *obj;\fR
.br
\fIdouble\ dx,\ dy,\ dz;\fR
.sp
Move (translate) the object \fIobj\ dx,\ dy\fR and \fIdz\fR in the
three main directions, respectively.
X
.IP \fIvoid\ lightsource_push(x,\ y,\ z,\ intensity)\fR
.br
\fIdouble\ x,\ y,\ z;\fR
.br
\fIdouble\ intensity;\fR
.sp
Create a new lightsource in the scene. All lightsources is considered
to be at an infinit distance and to emit white light. \fIx,\ y,\ z\fR
defines a vector pointing to the lightsource. \fIintensity\fR is a
double between 0 and 1 that defines the intensity of the light coming
from the lightsource.
X
.IP \fIvoid\ view_from(x,\ y,\ z)\fR
.br
.I double x, y, z;
.sp
Define the position of the viewpoint.
X
.IP \fIvoid\ view_at(x,\ y,\ z)\fR
.br
.I double x, y, z;
.sp
Define the viewing direction as going from the viewpoint to the point
.I x, y, z.
X
.IP \fIvoid\ view_up(x,\ y,\ z)\fR
.br
.I double x, y, z;
.sp
Define the up vector. The only constraint on this vector is that it
must not be parallel to the vector going from the viewpoint to the
viewed point.  If this function is not called, the default up vector
is the world Y axis.
X
.IP \fIvoid\ view_focal(ratio)\fR
.br
.I double ratio;
.sp
Define the focal ratio of the "camera". This is the ratio between the
distance from the viewpoint to the screen and half the screen height.
.sp 5
X					screen
.br
X					|
.br
X					| d
.br
.lc \ 
X	viewpoint|
.br
.lc -
X	*|
.br
.lc \ 
X			s|
.br
X					|
.br
X					|
.sp 2
.nf
X        focal_ratio = d / s
.fi
.sp
Another way of describing the value is acrtan(v/2) where v is the opening
angle of the view.
.br
Note: The same focal ratio is used both horizontally and vertically.
If the picture is rendered with different resolution in x and y, the ratio
is assumed to be related to the \fIsmallest\fR of the two.
X
.IP \fIviewpoint(x,\ y,\ z,\ to_x,\ to_y,\ to_z,\ up_x,\ up_y,\ up_z,\ focal_ratio)\fR
.br
This function is used to set all viewpoint related values in one call. All
arguments are doubles.
.br
.I x, y, z
is the position of the viewpoint as in \fIview_from()\fR.
.br
.I to_x, to_y, to_z
defines the viewing direction as in \fIview_at()\fR.
.br
.I up_x, up_y, up_z
defines the up vector as in \fIview_up()\fR.
.br
.I focal_ratio
defines (guess what) the focal ratio as in \fIview_focal()\fR.
X
.IP \fIvoid\ render_image(xsize,\ ysize,\ outfile)\fR
.br
\fIint\    xsize, ysize;\fR
.br
\fIFILE\ *outfile;\fR
.sp
This function does the actual rendering of the scene. The image is
created with size (\fIxsize\fR X \fIysize\fR). \fIoutfile\fR is an
open file pointer to which the image will be written.  It can just as
well be a pipe of course.
X
.IP \fIvoid\ basic_shader(nx,\ ny,\ nz,\ \ u,\ v,\ w,\ view_vec,fR
.br
\fI             	lights,\ surface,\ color)\fR
.br
\fIdouble nx, ny, nz;\fR
.br
\fIdouble u, v, w;\fR
.br
\fIVector\ view_vec;\fR
.br
\fILightsource *lights;\fR
.br
\fISurf_desc *surface;\fR
.br
\fI
Color\ *color;\fR
.sp
This is the basic shader function that is provided with the library.
See the section about \fBSHADING FUNCTIONS\fR for more details.
X
.SH SEE ALSO
shaders(3X) - a number of shaders for \fIsipp\fR.
.br
primitives(3X) - a number of geometric primitives for \fIsipp\fR.
X
.SH AUTHORS
Jonas Yngvesson\	\	(jonas-y@isy.liu.se)
.br
Inge Wallin\		(ingwa@isy.liu.se)
.SH BUGS
Antialiasing is rather crude. Aliasing effects is still quite obvious. It
also ought to be possible to turn off antialiasing in order to get a faster
"preview".
.sp
The viewing vector which is sent to the shader is
actually only an approximation which assumes the viewpoint being at infinite
distance. 
.sp
No information is sent to the shader about how big interpolation steps
are in the texture coordinate system. This makes it impossible to use
any filtering techniqe for texture mapping, e.g. summed area tables.
.sp
There is no way to delete a subobject from an object.
SHAR_EOF
chmod 0644 doc/sipp.man ||
echo 'restore of doc/sipp.man failed'
Wc_c="`wc -c < 'doc/sipp.man'`"
test 20064 -eq "$Wc_c" ||
	echo 'doc/sipp.man: original size 20064, current size' "$Wc_c"
fi
# ============= demo/Makefile ==============
if test ! -d 'demo'; then
    echo 'x - creating directory demo'
    mkdir 'demo'
fi
if test -f 'demo/Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/Makefile (File already exists)'
else
echo 'x - extracting demo/Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/Makefile' &&
#
# Makefile for the misc demos of sipp version 2.0.
#
X
# These values are used if not overruled from the command line
CC = cc
CFLAGS = -O -I../libsipp
X
X
SRCS = torustest.c cylindertest.c ellipsoid.c blocktest.c chain.c \
X	teapot.c structure.c planettest.c isy90.c
PROGRAMS = torustest cylindertest ellipsoid blocktest chain \
X	teapot structure planettest isy90
X
X
all:
X	@echo "If you want to make only the pretty images, type 'make pretty'."
X	@echo "If you want to make only the test images, type   'make tests'."
X	@echo "If you want to make all images, type             'make images'."
X	@echo
X	@echo "If you want to make the programs, but not the images,"
X	@echo "type 'make programs'."
X	@echo
X
X
# ================================================================
X
X
programs: ../libsipp/libsipp.a $(PROGRAMS)
X
../libsipp/libsipp.a:
X	cd ..; $(MAKE) library
X
X
# ================================================================
X
X
teapot: teapot.o ../libsipp/libsipp.a
X	$(CC) -o teapot teapot.o ../libsipp/libsipp.a -lm
X	
chain: chain.o ../libsipp/libsipp.a
X	$(CC) -o chain chain.o ../libsipp/libsipp.a -lm
X
structure: structure.o ../libsipp/libsipp.a
X	$(CC) -o structure structure.o ../libsipp/libsipp.a -lm
X
planettest: planettest.o ../libsipp/libsipp.a
X	$(CC) -o planettest planettest.o ../libsipp/libsipp.a -lm
X
isy90: isy90.o ../libsipp/libsipp.a
X	$(CC) -o isy90 isy90.o ../libsipp/libsipp.a -lm
X
ellipsoid:    ellipsoid.o ../libsipp/libsipp.a
X	$(CC) -o ellipsoid ellipsoid.o ../libsipp/libsipp.a -lm
X
torustest: torustest.o ../libsipp/libsipp.a
X	$(CC) -o torustest torustest.o ../libsipp/libsipp.a -lm
X
cylindertest: cylindertest.o ../libsipp/libsipp.a
X	$(CC) -o cylindertest cylindertest.o ../libsipp/libsipp.a -lm
X
blocktest: blocktest.o ../libsipp/libsipp.a
X	$(CC) -o blocktest blocktest.o ../libsipp/libsipp.a -lm
X
X
# ================================================================
X
X
clean:
X	$(RM) *~ .*~ *.o $(PROGRAMS) *.ppm
X
tags:
X	etags $(SRCS)
X
X
# ================================================================
X
PRETTY = chain.ppm teapot.ppm structure.ppm planet.ppm isy90.ppm
TESTS = torus.ppm cylinder.ppm ellipsoid.ppm block.ppm
IMAGES = $(PRETTY) $(TESTS)
X
images: $(IMAGES)
pretty: $(PRETTY)
tests:  $(TESTS)
X
chain.ppm: chain
X	chain 
teapot.ppm: teapot
X	teapot 
structure.ppm: structure
X	structure
planet.ppm: planettest
X	planettest
isy90.ppm: isy90
X	isy90
torus.ppm: torustest
X	torustest
cylinder.ppm: cylindertest
X	cylindertest
ellipsoid.ppm: ellipsoid
X	ellipsoid
block.ppm: blocktest
X	blocktest
SHAR_EOF
chmod 0644 demo/Makefile ||
echo 'restore of demo/Makefile failed'
Wc_c="`wc -c < 'demo/Makefile'`"
test 2518 -eq "$Wc_c" ||
	echo 'demo/Makefile: original size 2518, current size' "$Wc_c"
fi
# ============= demo/README ==============
if test -f 'demo/README' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/README (File already exists)'
else
echo 'x - extracting demo/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/README' &&
This directory contains test programs and demonstration programs for
the sipp library version 2.0. The images here can be divided into two
categories: the mere test images (boring) and the demonstrations
images (impressive).
X
Test image              Created by      Explanation
---------------------------------------------------
torus.ppm               torustest       A plain violet torus
cylinder.ppm            cylindertest    A violet, rather fat, cylinder
ellipsoid.ppm           ellipsoid       A violet course ellipsoid.
X                                        Note how the surface of the
X                                        ellipsoid appears smooth in
X                                        spite of the low number of
X                                        polygons in it.
block.ppm               blocktest       An orange square block.
X
X
Demo image              Created by      Explanation
---------------------------------------------------
chain.ppm               chain           A 3-D chain of torii.
teapot.ppm              teapot          The standard classic Newell
X                                        teapot. 
structure.ppm           structure       A geometric structure,
X                                        demonstrating bumpy
X                                        appearance of a surface
planet.ppm              planettest      A planet with fractal coasts
X                                        and clouds.
isy90.ppm               isy90           The cover of the 1990
X                                        Activity Report at the Dept.
X                                        of EE at Linkoping University.  
X                                        Demonstrates a simulated
X                                        granite texture.
SHAR_EOF
chmod 0644 demo/README ||
echo 'restore of demo/README failed'
Wc_c="`wc -c < 'demo/README'`"
test 1771 -eq "$Wc_c" ||
	echo 'demo/README: original size 1771, current size' "$Wc_c"
fi
# ============= demo/TAGS ==============
if test -f 'demo/TAGS' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/TAGS (File already exists)'
else
echo 'x - extracting demo/TAGS (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/TAGS' &&
X
torustest.c,13
main(13,130
X
cylindertest.c,13
main(12,112
X
ellipsoidtest.c,13
main(12,112
X
blocktest.c,11
main(9,88
X
chain.c,13
main(13,130
X
teapot.c,11
main(8,81
X
d15.c,55
ellips_plate(47,931
main(126,3268
pixel_test(33,752
X
structure.c,37
#define SIGNBIT(12,151
main(29,383
X
planettest.c,13
main(12,130
SHAR_EOF
chmod 0644 demo/TAGS ||
echo 'restore of demo/TAGS failed'
Wc_c="`wc -c < 'demo/TAGS'`"
test 327 -eq "$Wc_c" ||
	echo 'demo/TAGS: original size 327, current size' "$Wc_c"
fi
# ============= demo/blocktest.c ==============
if test -f 'demo/blocktest.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/blocktest.c (File already exists)'
else
echo 'x - extracting demo/blocktest.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/blocktest.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
X
X
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    FILE    *fp ;
X    Surf_desc surf;
X    int      side;
X
X
X    if (argc != 2) {
X        side = 256;
X    } else {
X        side = atoi(argv[1]);
X    }
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 0.9);
X    lightsource_push(-1.0, -1.0, 0.5, 0.4);
X
X    surf.ambient = 0.5;
X    surf.color.red = 0.8;
X    surf.color.grn = 0.5;
X    surf.color.blu = 0.2;
X    surf.specular = 0.6;
X    surf.c3 = 0.2;
X    
X    object_install(sipp_block(1.0, 2.0, 3.0, &surf, basic_shader)); 
X
X    viewpoint(7.0, 3.0, 5.0,  0.0, 0.0, 0.0,  0.0, 0.0, 1.0,  0.4);
X
X    printf("Rendering, wait...");
X    fflush(stdout);
X
X    fp = fopen("block.ppm", "w");
X    render_image(side, side, fp);
X    printf("Done.\n");
}
X
SHAR_EOF
chmod 0644 demo/blocktest.c ||
echo 'restore of demo/blocktest.c failed'
Wc_c="`wc -c < 'demo/blocktest.c'`"
test 830 -eq "$Wc_c" ||
	echo 'demo/blocktest.c: original size 830, current size' "$Wc_c"
fi
# ============= demo/chain.c ==============
if test -f 'demo/chain.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/chain.c (File already exists)'
else
echo 'x - extracting demo/chain.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/chain.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
X
X
X
#define SMALLRES 15
#define BIGRES   40
X
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    Object  *torus;
X    Object  *torus_pair;
X    Object  *chain;
X    FILE    *fp ;
X    Surf_desc surf;
X    int      side;
X
X
X    if (argc != 2) {
X        side = 256;
X    } else {
X        side = atoi(argv[1]);
X    }
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 0.9);
X    lightsource_push(-1.0, -1.0, 0.5, 0.4);
X
X    surf.ambient = 0.5;
X    surf.color.red = 0.8;
X    surf.color.grn = 0.6;
X    surf.color.blu = 0.3;
X    surf.specular = 0.6;
X    surf.c3 = 0.2;
X    
X    torus = sipp_torus(1.0, 0.23, BIGRES, SMALLRES, &surf, basic_shader);
X    torus_pair = object_create();
X    object_add_subobj(torus_pair, torus);
X    torus = object_instance(torus);
X    object_move(torus, 0.0, -1.375, 0.0);
X    object_rot_y(torus, M_PI / 2.0);
X    object_add_subobj(torus_pair, torus);
X    
X    chain = object_create();
X    object_move(torus_pair, -1.375, 1.375, 0.0);
X    object_add_subobj(chain, torus_pair);
X    torus_pair = object_instance(torus_pair);
X    object_rot_z(torus_pair, M_PI / 2.0);
X    object_move(torus_pair, -1.375, -1.375, 0.0);
X    object_add_subobj(chain, torus_pair);
X    torus_pair = object_instance(torus_pair);
X    object_rot_z(torus_pair, M_PI);
X    object_move(torus_pair, 1.375, -1.375, 0.0);
X    object_add_subobj(chain, torus_pair);
X    torus_pair = object_instance(torus_pair);
X    object_rot_z(torus_pair, 3.0 * M_PI / 2.0);
X    object_move(torus_pair, 1.375, 1.375, 0.0);
X    object_add_subobj(chain, torus_pair);
X    
X    object_install(chain);
X
X    view_from(5.0, -2.0, 15.0);
X    view_at(0.5, 0.0, 0.0);
X    view_up(0.0, 0.0, 1.0);
X    view_focal(0.25);
X
X    printf("Rendering, wait...");
X    fflush(stdout);
X
X    fp = fopen("chain.ppm", "w");
X    render_image(side, side, fp);
X    printf("Done.\n");
}
SHAR_EOF
chmod 0644 demo/chain.c ||
echo 'restore of demo/chain.c failed'
Wc_c="`wc -c < 'demo/chain.c'`"
test 1910 -eq "$Wc_c" ||
	echo 'demo/chain.c: original size 1910, current size' "$Wc_c"
fi
# ============= demo/cylindertest.c ==============
if test -f 'demo/cylindertest.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/cylindertest.c (File already exists)'
else
echo 'x - extracting demo/cylindertest.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/cylindertest.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
X
X
X
#define RESOLUTION 40
X
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    FILE    *fp ;
X    Surf_desc surf;
X    int      side;
X
X
X    if (argc != 2) {
X        side = 256;
X    } else {
X        side = atoi(argv[1]);
X    }
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 0.9);
X    lightsource_push(-1.0, -1.0, 0.5, 0.4);
X
X    surf.ambient = 0.5;
X    surf.color.red = 0.6;
X    surf.color.grn = 0.3;
X    surf.color.blu = 0.5;
X    surf.specular = 0.6;
X    surf.c3 = 0.2;
X    
X    object_install(sipp_cylinder(1.0, 1.0, RESOLUTION, &surf, basic_shader)); 
X
X    viewpoint(3.0, 0.0, 2.0,  0.0, 0.0, 0.0,  0.0, 0.0, 1.0,  0.4);
X
X    printf("Rendering, wait...");
X    fflush(stdout);
X
X    fp = fopen("cylinder.ppm", "w");
X    render_image(side, side, fp);
X    printf("Done.\n");
}
SHAR_EOF
chmod 0644 demo/cylindertest.c ||
echo 'restore of demo/cylindertest.c failed'
Wc_c="`wc -c < 'demo/cylindertest.c'`"
test 866 -eq "$Wc_c" ||
	echo 'demo/cylindertest.c: original size 866, current size' "$Wc_c"
fi
# ============= demo/ellipsoid.c ==============
if test -f 'demo/ellipsoid.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/ellipsoid.c (File already exists)'
else
echo 'x - extracting demo/ellipsoid.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/ellipsoid.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
X
X
X
#define RESOLUTION 15
X
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    FILE    *fp ;
X    Surf_desc surf;
X    int      side;
X
X
X    if (argc != 2) {
X        side = 256;
X    } else {
X        side = atoi(argv[1]);
X    }
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 0.9);
X    lightsource_push(-1.0, -1.0, 0.5, 0.4);
X
X    surf.ambient = 0.5;
X    surf.color.red = 0.6;
X    surf.color.grn = 0.3;
X    surf.color.blu = 0.5;
X    surf.specular = 0.6;
X    surf.c3 = 0.2;
X    
X    object_install(sipp_ellipsoid(1.0, 2.0, 3.0, RESOLUTION,
X                                  &surf, basic_shader)); 
X
X    viewpoint(10.0, 0.0, 0.0,  0.0, 0.0, 0.0,  0.0, 0.0, 1.0,  0.4);
X
X    printf("Rendering, wait...");
X    fflush(stdout);
X
X    fp = fopen("ellipsoid.ppm", "w");
X    render_image(side, side, fp);
X    printf("Done.\n");
}
SHAR_EOF
chmod 0644 demo/ellipsoid.c ||
echo 'restore of demo/ellipsoid.c failed'
Wc_c="`wc -c < 'demo/ellipsoid.c'`"
test 908 -eq "$Wc_c" ||
	echo 'demo/ellipsoid.c: original size 908, current size' "$Wc_c"
fi
# ============= demo/isy90.c ==============
if test -f 'demo/isy90.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/isy90.c (File already exists)'
else
echo 'x - extracting demo/isy90.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/isy90.c' &&
#include <math.h>
#include <stdio.h>
X
#include <sipp.h>
#include <shaders.h>
#include <primitives.h>
X
X
#define BEZ_RES        9
#define CYL_RES        40
#define LID_ROT        1.5
#define BLOCK_SIZE     1.2
#define NCYL           10
#define CYL_LEN        5.0
#define SMALL_CYL_RAD  ((BLOCK_SIZE * M_PI) / (NCYL * 2))
#define BIG_CYL_RAD    (0.5 * BLOCK_SIZE - 1.1 * SMALL_CYL_RAD)
X
X
Marble_desc teapot_surf = {
X    0.4, 
X    0.5,
X    0.05,
X    8.0, 
X    {0.90, 0.80, 0.65}, 
X    {0.30, 0.08, 0.08}
};
X
Granite_desc column_surf = {
X    0.4,
X    0.1,
X    0.4,
X    20.0,
X    {0.647, 0.565, 0.5},
X    {0.15, 0.12, 0.10}
};
X
X
main(argc, argv)
X    int argc;
X    char **argv;
{
X    Object  *column;
X    Object  *teapot;
X    Object  *handle;
X    Object  *spout;
X    Object  *body;
X    Object  *lid;
X    Object  *tmp;
X    FILE    *infile;
X    int      siz;
X    FILE    *image;
X    int      i;
X
X    if (argc > 1) {
X        siz = atoi(argv[1]);
X    } else {
X        siz = 256;
X    }
X
X    sipp_init();
X
X    infile = fopen("tpt_handle.bez", "r");
X    handle = sipp_bezier(infile, BEZ_RES, &teapot_surf, marble_shader);
X    fclose(infile);
X
X    infile = fopen("tpt_spout.bez", "r");
X    spout = sipp_bezier(infile, BEZ_RES, &teapot_surf, marble_shader);
X    fclose(infile);
X
X    infile = fopen("tpt_body.bez", "r");
X    body = sipp_bezier(infile, BEZ_RES, &teapot_surf, marble_shader);
X    fclose(infile);
X
X    infile = fopen("tpt_lid.bez", "r");
X    lid = sipp_bezier(infile, BEZ_RES, &teapot_surf, marble_shader);
X    fclose(infile);
X
X    object_rot_y(lid, LID_ROT);
X
X    teapot = object_create();
X    object_add_subobj(teapot, body);
X    object_add_subobj(teapot, lid);
X    object_add_subobj(teapot, handle);
X    object_add_subobj(teapot, spout);
X
X    object_install(teapot);
X
X    column = object_create();
X    tmp = sipp_block(BLOCK_SIZE, BLOCK_SIZE / 4.0, BLOCK_SIZE,
X                     &column_surf, granite_shader);
X    object_move(tmp, 0.0, -BLOCK_SIZE / 8.0, 0.0);
X    object_add_subobj(column, tmp);
X
X    for (i = 0; i < NCYL; i++) {
X        if (i == 0) {
X            tmp = sipp_cylinder(SMALL_CYL_RAD, CYL_LEN, CYL_RES,
X                                &column_surf, granite_shader); 
X        } else {
X            tmp = object_instance(tmp);
X        }
X        object_rot_x(tmp, M_PI / 2.0);
X        object_move(tmp, BIG_CYL_RAD * cos(i * 2.0 * M_PI / NCYL), 
X                    -0.5 * (CYL_LEN + BLOCK_SIZE / 4.0), 
X                    BIG_CYL_RAD * sin(i * 2.0 * M_PI / NCYL));
X        object_add_subobj(column, tmp);
X    }
X
X    object_install(column);
X        
X    
X    lightsource_push(1.0, 1.0, 0.5, 0.85);
X    lightsource_push(-1.0, 0.5, 0.5, 0.25);
X    view_from(2.0, 1.5, 4.0);
X    view_at(0.0, 0.1, 0.0);
X    view_up(0.0, 1.0, 0.0);
X    view_focal(0.2);
X    image = fopen("isy90.ppm", "w");
X    render_image(siz, siz, image);
}
SHAR_EOF
chmod 0644 demo/isy90.c ||
echo 'restore of demo/isy90.c failed'
Wc_c="`wc -c < 'demo/isy90.c'`"
test 2837 -eq "$Wc_c" ||
	echo 'demo/isy90.c: original size 2837, current size' "$Wc_c"
fi
# ============= demo/planettest.c ==============
if test -f 'demo/planettest.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/planettest.c (File already exists)'
else
echo 'x - extracting demo/planettest.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/planettest.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
#include <shaders.h>
X
X
X
#define SUBDIVS  20
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    Surf_desc   planet_surface;
X    Object     *planet;
X    FILE       *outfile;
X    int         size;
X
X    if (argc == 2) {
X        size = atoi(argv[1]);
X    } else {
X        size = 256;
X    }
X    
X    planet_surface.ambient = 0.4;
X    planet_surface.specular = 0.0;
X    planet_surface.c3 = 0.5;
X    planet_surface.color.red = 1.0;
X    planet_surface.color.grn = 0.0;
X    planet_surface.color.blu = 0.0;
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 1.0);
X
X    object_install(sipp_sphere(1.0, SUBDIVS, &planet_surface, planet_shader)); 
X
X    viewpoint(0.0, 2.0, 0.0,  0.0, 0.0, 0.0,  0.0, 0.0, 1.0,  0.75);
X
X    outfile = fopen("planet.ppm", "w");
X    render_image(size, size, outfile);
}
X
SHAR_EOF
chmod 0644 demo/planettest.c ||
echo 'restore of demo/planettest.c failed'
Wc_c="`wc -c < 'demo/planettest.c'`"
test 878 -eq "$Wc_c" ||
	echo 'demo/planettest.c: original size 878, current size' "$Wc_c"
fi
# ============= demo/structure.c ==============
if test -f 'demo/structure.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/structure.c (File already exists)'
else
echo 'x - extracting demo/structure.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/structure.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
#include <shaders.h>
X
X
#define SPHERERES 40
#define CYLRES    40
X
#define SIGNBIT(bit, i)   (((i >> bit) & 1) ? -1.0 : 1.0)
X
Surf_desc surf = {
X    0.4,
X    0.7, 
X    0.1, 
X    {0.8, 0.6, 0.3}
X    };
X    
Bumpy_desc bumpy_surf = {
X    basic_shader, 
X    &surf, 
X    14.0, 
X    FALSE, 
X    TRUE
};
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    Object  *sphere;
X    Object  *cyl;
X    Object  *structure;
X    FILE    *fp ;
X    Surf_desc cyl_surf;
X    int      size;
X    int      i;
X
X
X    if (argc != 2) {
X        size = 256;
X    } else {
X        size = atoi(argv[1]);
X    }
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 0.9);
X    lightsource_push(-1.0, -1.0, 0.5, 0.4);
X
X    cyl_surf.ambient = 0.5;
X    cyl_surf.color.red = 0.5;
X    cyl_surf.color.grn = 0.6;
X    cyl_surf.color.blu = 0.8;
X    cyl_surf.specular = 0.4;
X    cyl_surf.c3 = 0.3;
X    
X    structure = object_create();
X
X    sphere = sipp_sphere(1.0, SPHERERES, &bumpy_surf, bumpy_shader);
X    for (i = 0; i < 8; i++) {
X        if (i) {
X            sphere = object_instance(sphere);
X        }
X        object_move(sphere, 2.0 * SIGNBIT(2, i), 2.0 * SIGNBIT(1, i), 
X                    2.0 * SIGNBIT(0, i));
X        object_add_subobj(structure, sphere);
X    }
X
X    cyl = sipp_cylinder(0.25, 4.0, CYLRES, &cyl_surf, basic_shader);
X    for (i = 0; i < 4; i++) {
X        if (i) {
X            cyl = object_instance(cyl);
X        }
X        object_move(cyl, 2.0 * SIGNBIT(1, i), 2.0 * SIGNBIT(0, i), 0.0);
X        object_add_subobj(structure, cyl);
X    }
X    for (i = 0; i < 4; i++) {
X        cyl = object_instance(cyl);
X        object_rot_x(cyl, M_PI / 2.0);
X        object_move(cyl, 2.0 * SIGNBIT(1, i), 0.0, 2.0 * SIGNBIT(0, i));
X        object_add_subobj(structure, cyl);
X    }
X    for (i = 0; i < 4; i++) {
X        cyl = object_instance(cyl);
X        object_rot_y(cyl, M_PI / 2.0);
X        object_move(cyl, 0.0, 2.0 * SIGNBIT(1, i), 2.0 * SIGNBIT(0, i));
X        object_add_subobj(structure, cyl);
X    }
X    
X    object_install(structure);
X
X    view_from(10.0, -5.0, 15.0);
X    view_at(0.0, 0.0, 0.0);
X    view_up(0.0, 0.0, 1.0);
X    view_focal(0.25);
X
X    printf("Rendering, wait...");
X    fflush(stdout);
X
X    fp = fopen("structure.ppm", "w");
X    render_image(size, size, fp);
X    printf("Done.\n");
}
X
SHAR_EOF
chmod 0644 demo/structure.c ||
echo 'restore of demo/structure.c failed'
Wc_c="`wc -c < 'demo/structure.c'`"
test 2360 -eq "$Wc_c" ||
	echo 'demo/structure.c: original size 2360, current size' "$Wc_c"
fi
# ============= demo/teapot.c ==============
if test -f 'demo/teapot.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/teapot.c (File already exists)'
else
echo 'x - extracting demo/teapot.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/teapot.c' &&
#include <stdio.h>
X
#include <sipp.h>
#include <primitives.h>
X
X
#define RESOLUTION 9
X
Surf_desc teapot_surf = {
X    0.4, 
X    0.5,
X    0.1, 
X    {0.9, 0.6, 0.6}
};
X
X
main(argc, argv)
X    int argc;
X    char **argv;
{
X    Object  *teapot;
X    Object  *handle;
X    Object  *spout;
X    Object  *body;
X    Object  *lid;
X    FILE    *infile;
X    int      siz;
X    FILE    *image;
X
X    if (argc > 1) {
X        siz = atoi(argv[1]);
X    } else {
X        siz = 256;
X    }
X
X    sipp_init();
X
X    infile = fopen("tpt_handle.bez", "r");
X    handle = sipp_bezier(infile, RESOLUTION, &teapot_surf, basic_shader);
X    fclose(infile);
X
X    infile = fopen("tpt_spout.bez", "r");
X    spout = sipp_bezier(infile, RESOLUTION, &teapot_surf, basic_shader);
X    fclose(infile);
X
X    infile = fopen("tpt_body.bez", "r");
X    body = sipp_bezier(infile, RESOLUTION, &teapot_surf, basic_shader);
X    fclose(infile);
X
X    infile = fopen("tpt_lid.bez", "r");
X    lid = sipp_bezier(infile, RESOLUTION, &teapot_surf, basic_shader);
X    fclose(infile);
X
X    teapot = object_create();
X    object_add_subobj(teapot, body);
X    object_add_subobj(teapot, lid);
X    object_add_subobj(teapot, handle);
X    object_add_subobj(teapot, spout);
X
X    object_install(teapot);
X
X    lightsource_push(1.0, 1.0, 1.0, 1.0);
/*    lightsource_push(-1.0, 1.0, -1.0, 1.0);*/
X    view_from(0.75, 1.5, 3.5);
X    view_at(0.0, 0.4, 0.0);
X    view_up(0.0, 1.0, 0.0);
X    view_focal(0.25);
X    image = fopen("teapot.ppm", "w");
X    render_image(siz, siz, image);
}
SHAR_EOF
chmod 0644 demo/teapot.c ||
echo 'restore of demo/teapot.c failed'
Wc_c="`wc -c < 'demo/teapot.c'`"
test 1505 -eq "$Wc_c" ||
	echo 'demo/teapot.c: original size 1505, current size' "$Wc_c"
fi
# ============= demo/torustest.c ==============
if test -f 'demo/torustest.c' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/torustest.c (File already exists)'
else
echo 'x - extracting demo/torustest.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/torustest.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <primitives.h>
X
X
X
#define SMALLRES 15
#define BIGRES   40
X
X
main(argc, argv)
X    int    argc;
X    char **argv;
{
X    FILE    *fp ;
X    Surf_desc surf;
X    int      side;
X
X
X    if (argc != 2) {
X        side = 256;
X    } else {
X        side = atoi(argv[1]);
X    }
X
X    sipp_init();
X
X    lightsource_push(1.0, 1.0, 1.0, 0.9);
X    lightsource_push(-1.0, -1.0, 0.5, 0.4);
X
X    surf.ambient = 0.5;
X    surf.color.red = 0.6;
X    surf.color.grn = 0.3;
X    surf.color.blu = 0.5;
X    surf.specular = 0.6;
X    surf.c3 = 0.2;
X    
X    object_install(sipp_torus(1.0, 0.4, BIGRES, SMALLRES, &surf,
X                              basic_shader)); 
X
X    viewpoint(2.0, 0.0, 7.0,  0.5, 0.0, 0.0,  0.0, 0.0, 1.0,  0.4);
X
X    printf("Rendering, wait...");
X    fflush(stdout);
X
X    fp = fopen("torus.ppm", "w");
X    render_image(side, side, fp);
X    printf("Done.\n");
}
SHAR_EOF
chmod 0644 demo/torustest.c ||
echo 'restore of demo/torustest.c failed'
Wc_c="`wc -c < 'demo/torustest.c'`"
test 914 -eq "$Wc_c" ||
	echo 'demo/torustest.c: original size 914, current size' "$Wc_c"
fi
# ============= demo/tpt_body.bez ==============
if test -f 'demo/tpt_body.bez' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/tpt_body.bez (File already exists)'
else
echo 'x - extracting demo/tpt_body.bez (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/tpt_body.bez' &&
# 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
SHAR_EOF
chmod 0644 demo/tpt_body.bez ||
echo 'restore of demo/tpt_body.bez failed'
Wc_c="`wc -c < 'demo/tpt_body.bez'`"
test 644 -eq "$Wc_c" ||
	echo 'demo/tpt_body.bez: original size 644, current size' "$Wc_c"
fi
# ============= demo/tpt_handle.bez ==============
if test -f 'demo/tpt_handle.bez' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/tpt_handle.bez (File already exists)'
else
echo 'x - extracting demo/tpt_handle.bez (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/tpt_handle.bez' &&
# Bezier patches defining the teapot handle.
X
bezier_patches:
X
X
vertices: 42
vertex_list:
X
X   -3.750000E-01    5.250000E-01    0.000000E+00
X   -6.250000E-01    5.250000E-01    0.000000E+00
X   -7.500000E-01    5.250000E-01    0.000000E+00
X   -7.500000E-01    4.125000E-01    0.000000E+00
X   -7.500000E-01    3.000000E-01    0.000000E+00
X   -6.625000E-01    1.968750E-01    0.000000E+00
X   -4.750000E-01    1.125000E-01    0.000000E+00
X   -3.750000E-01    5.250000E-01   -7.500000E-02
X   -6.250000E-01    5.250000E-01   -7.500000E-02
X   -7.500000E-01    5.250000E-01   -7.500000E-02
X   -7.500000E-01    4.125000E-01   -7.500000E-02
X   -7.500000E-01    3.000000E-01   -7.500000E-02
X   -6.625000E-01    1.968750E-01   -7.500000E-02
X   -4.750000E-01    1.125000E-01   -7.500000E-02
X   -4.000000E-01    4.687500E-01   -7.500000E-02
X   -5.750000E-01    4.687500E-01   -7.500000E-02
X   -6.750000E-01    4.687500E-01   -7.500000E-02
X   -6.750000E-01    4.125000E-01   -7.500000E-02
X   -6.750000E-01    3.562500E-01   -7.500000E-02
X   -6.250000E-01    2.437500E-01   -7.500000E-02
X   -5.000000E-01    1.875000E-01   -7.500000E-02
X   -4.000000E-01    4.687500E-01    0.000000E+00
X   -5.750000E-01    4.687500E-01    0.000000E+00
X   -6.750000E-01    4.687500E-01    0.000000E+00
X   -6.750000E-01    4.125000E-01    0.000000E+00
X   -6.750000E-01    3.562500E-01    0.000000E+00
X   -6.250000E-01    2.437500E-01    0.000000E+00
X   -5.000000E-01    1.875000E-01    0.000000E+00
X   -4.000000E-01    4.687500E-01    7.500000E-02
X   -5.750000E-01    4.687500E-01    7.500000E-02
X   -6.750000E-01    4.687500E-01    7.500000E-02
X   -6.750000E-01    4.125000E-01    7.500000E-02
X   -6.750000E-01    3.562500E-01    7.500000E-02
X   -6.250000E-01    2.437500E-01    7.500000E-02
X   -5.000000E-01    1.875000E-01    7.500000E-02
X   -3.750000E-01    5.250000E-01    7.500000E-02
X   -6.250000E-01    5.250000E-01    7.500000E-02
X   -7.500000E-01    5.250000E-01    7.500000E-02
X   -7.500000E-01    4.125000E-01    7.500000E-02
X   -7.500000E-01    3.000000E-01    7.500000E-02
X   -6.625000E-01    1.968750E-01    7.500000E-02
X   -4.750000E-01    1.125000E-01    7.500000E-02
X
patches:   4
patch_list:
X
X 1  2  3  4
36 37 38 39
29 30 31 32
22 23 24 25
X
22 23 24 25
15 16 17 18
X 8  9 10 11
X 1  2  3  4
X
X 4  5  6  7
39 40 41 42
32 33 34 35
25 26 27 28
X
X 7  6  5  4
14 13 12 11
21 20 19 18
28 27 26 25
SHAR_EOF
chmod 0644 demo/tpt_handle.bez ||
echo 'restore of demo/tpt_handle.bez failed'
Wc_c="`wc -c < 'demo/tpt_handle.bez'`"
test 2371 -eq "$Wc_c" ||
	echo 'demo/tpt_handle.bez: original size 2371, current size' "$Wc_c"
fi
# ============= demo/tpt_lid.bez ==============
if test -f 'demo/tpt_lid.bez' -a X"$1" != X"-c"; then
	echo 'x - skipping demo/tpt_lid.bez (File already exists)'
else
echo 'x - extracting demo/tpt_lid.bez (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/tpt_lid.bez' &&
# Bezier curves (rotational body) for teapot lid.
X
bezier_curves:
X
vertices: 7
vertex_list:
X
X    0.000000e+00    7.500000e-01    0.000000e+00
X    2.000000E-01    7.500000E-01    0.000000E+00
X    0.000000E+00    6.750000E-01    0.000000E+00
X    5.000000E-02    6.375000E-01    0.000000E+00
X    1.000000E-01    6.000000E-01    0.000000E+00
X    3.250000E-01    6.000000E-01    0.000000E+00
X    3.375000E-01    5.625000E-01    0.000000E+00
X
curves:   2
curve_list:
X
X 1 2 3 4
X
X 4 5 6 7
SHAR_EOF
chmod 0644 demo/tpt_lid.bez ||
echo 'restore of demo/tpt_lid.bez failed'
Wc_c="`wc -c < 'demo/tpt_lid.bez'`"
test 481 -eq "$Wc_c" ||
	echo 'demo/tpt_lid.bez: original size 481, current size' "$Wc_c"
fi
true || echo 'restore of demo/tpt_spout.bez failed'
echo End of part 5, continue with part 6
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.