home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume21
/
sipp
/
part07
< prev
next >
Wrap
Text File
|
1991-07-23
|
50KB
|
1,615 lines
Newsgroups: comp.sources.misc
From: Jonas Yngvesson <jonas-y@isy.liu.se>
Subject: v21i032: sipp - A 3D rendering library v2.1, Part07/08
Message-ID: <1991Jul23.181801.28000@sparky.IMD.Sterling.COM>
X-Md4-Signature: db212cb96d3ef57e8b2fec27ce5c0a5d
Date: Tue, 23 Jul 1991 18:18:01 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: Jonas Yngvesson <jonas-y@isy.liu.se>
Posting-number: Volume 21, Issue 32
Archive-name: sipp/part07
Supersedes: sipp2.0: Volume 16, Issue 5-10
Environment: UNIX
#!/bin/sh
# This is part 07 of sipp-2.1
# ============= 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 Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH SIPP 3X "July , 1991" 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 ]
X
.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 using either Phong, Gouraud or
Flat shading. An image can also be rendered as a line drawing of the
polygon edges without any shading at all.
.sp
The library has an internal database for the objects to be rendered.
Objects can be installed in, and removed from, this database at any
time.
.sp
The library also provides support for texture mapping with
automatic interpolation of texture coordinates. Simple anti-aliasing can be
performed with 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.
.sp
Images can be rendered directly onto a file in the Portable Pixmap
format (ppm) (or, for line images, Portable Bitmap, pbm) or into a
pixmap (bitmap) in core. The representation of the pixmap is not
restricted in any way.
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 \fIpolygons\fR with 3 or
more \fIvertices\fR. 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,
\fIsurface\fR. Inside a surface, a surface normal is stored with each
vertex. This normal is the average of the normals of the polygons
surrounding the vertex.
.sp
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. Variations of these functions exist, but these
are the simple forms which 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 variations) 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.
.sp
The finished database can be rendered in a number of different modes.
\fIPHONG\fR rendering interpolates the surface normals over the polygons and
call the shading function at each point (See the section \fBSHADING
FUNCTIONS\fR for more details on them). This is the slowest method but it also
produces the best result and is the only mode which can do texture mapping
correctly. \fIGOURAUD\fR rendering calls the shading function only at the
vertices and then interpolates the resulting color over the polygon.
\fIFLAT\fR rendering calls the shading function only once per polygon and
fills the polygon with the resulting color. \fILINE\fR rendering draws only
the outlines of the polygons. This mode uses no color and is the fastest. No
hidden line removal is done.
X
.SH DATA TYPES
The \fIsipp\fR library defines a number of data types in the file
\fIsipp.h\fR. These data types are:
X
.IP \fIbool\fR
\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 which 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 TEXTURE COORDINATES
When defining a vertex of a polygon, up to 3 \fItexture coordinates\fR can be
assigned to it. These coordinates are floating point numbers and the
interpretation of them are up to the user. The texture coordinates are
interpolated across the polygon when it is being rendered and these
interpolated values are sent as parameters to the shading function. Since it
is the shader that decides how the texture coordinates are to be used it is
only the \fIPHONG\fR shading mode, which calls the shader in every point, that
can do correct texture mapping.
X
.SH SHADING FUNCTIONS
Each surface in a scene has a shading function associated with it.
\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\ sipp_show_backfaces(flag)\fR
.br
\fIbool\ flag;\fR
.sp
This function can be used if backface culling should not be performed. If
\fIflag\fR is \fITRUE\fR backfacing polygons are "inverted" (their surface
normal is negated) and then rendered. This is useful if an object description
does not use a consequent ordering of the vertices. Note, however, that the
rendering step can be slowed down considerably since, on the average, twice as
many polygons need to be rendered. The default (set by \fIsipp_init()\fR) is
that backface culling should be performed.
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 dangling
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_sub_surface(obj,\ surf)\fR
.br
\fIObject\ *obj;\fR
.br
\fISurface\ *surf;\fR
.sp
Remove the surface \fIsurf\fR from 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_add_subobj(obj,\ subobj)\fR
.br
\fIObject\ *obj;\fR
.br
\fIObject\ *subobj;\fR
.sp
Remove the subobject \fIsubobj\fR from the object \fIobj\fR. It is only
unlinked from the list of subobjects in \fIobj\fR. If the memory it uses
should be freed, \fIobject_delete()\fR must be used.
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 \fITransf_mat\ *object_get_transf(obj,\ matrix)\fR
.br
\fIObject\ *obj;\fR
.br
\fITransf_mat\ *matrix;\fR
.sp
Return the transformation matrix currently stored in the object \fIobj\fR. If
\fImatrix\fR is not NULL, the transformation matrix will be copied to that
location and a pointer to it (identical to \fImatrix\fR) is returned. If
\fImatrix\fR is NULL a new matrix will be allocated, the transformation matrix
copied into it and a pointer to the new matrix is returned.
.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 4
.nf
X screen
X |
X | d
viewpoint |
.tc -
* |
.tc
X s |
X |
X |
.sp 2
focal_ratio = d / s
.sp
.fi
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_file(xsize,\ ysize,\ outfile,\ mode,\ oversampling)\fR
.br
\fIint\ xsize, ysize;\fR
.br
\fIFILE\ *outfile;\fR
.br
\fIint\ mode;\fR
.br
\fIint\ oversampling;\fR
.sp
This function does the actual rendering of a 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.
\fImode\fR decides in which mode the image should be rendered and should be
one of \fIPHONG,\ GOURAUD,\ FLAT\fR or \fILINE\fR. \fIoversampling\fR controls
how much oversampling should be done for anti-aliasing. Each pixel will be the
average of a \fIoversampling\fR X \fIoversampling\fR matrix of subpixels. In
\fILINE\fR mode the \fIoversampling\fR argument is ignored.
X
.IP \fIvoid\ render_image_pixmap(xsize,\ ysize,\ pixmap,\ plot_func,\ mode,\ oversampling)\fR
.br
\fIint\ xsize, ysize;\fR
.br
\fIvoid\ *pixmap;\fR
.br
\fIvoid\ (*plot_func)();\fR
.br
\fIint\ mode;\fR
.br
\fIint\ oversampling;\fR
.sp
This function also does rendering of a scene but the image is rendered into a
pixmap instead of a file. It does not have to be a pixmap though. Anything
where it is possible to plot a pixel (or a line) could be used, e.g. a window
or a PostScript file. \fIxsize\fR, \fIysize\fR, \fImode\fR and
\fIoversampling\fR has the same meaning as in \fIrender_image_file()\fR.
\fIpixmap\fR is a pointer to a structure of any type, representing the pixmap.
\fIplot_func\fR is, unless \fImode\fR is \fILINE\fR, a pointer to a function
that sets a pixel in a pixmap of the same type as \fIpixmap\fR. If \fImode\fR
is \fILINE\fR, it should be a pointer to a function that draws a line in the
pixmap.
.sp
The point plotting function should be defined thus:
.sp
\fIvoid\ plot_func(pixmap,\ x,\ y,\ red,\ green,\ blue)\fR
.br
\ \fImy_pixmap_type\ *pixmap;\fR
.br
\ \fIint\ x,\ y;\fR
.br
\ \fIunsigned\ char\ red,\ green,\ blue;\fR
.sp
and the line drawing function like this:
.sp
\fIvoid\ plot_func(pixmap,\ x1,\ y1,\ x2,\ y2)\fR
.br
\ \fImy_pixmap_type\ *pixmap;\fR
.br
\ \fIint\ x1,\ y1;\fR
.br
\ \fIint\ x2,\ y2;\fR
.br
X
.IP \fIvoid\ render_image(xsize,\ ysize,\ outfile)\fR
.br
\fIint\ xsize, ysize;\fR
.br
\fIFILE\ *outfile;\fR
.sp
This is equivalent to calling \fIrender_image_file()\fR with
\fImode\fR = \fIPHONG\fR and \fIoversampling\fR = 2. This is a macro
which is provided for compatibility with older versions (2.0.2 and
older).
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
geometric(3X) - Vector and matrix functions for the sipp(3X) library
.br
primitives(3X) - a collection of geometric primitives for \fIsipp\fR.
.br
sipp_pixmap(3X) - pixmap handling code for \fIsipp\fR.
.br
sipp_bitmap(3X) - bitmap handling code for \fIsipp\fR.
X
.SH AUTHORS
Jonas Yngvesson\ \ (jonas-y@isy.liu.se)
.br
Inge Wallin\ (ingwa@isy.liu.se)
X
.SH BUGS
When flat shading is used, the normal vector that is sent to the shader
is not really the polygon normal. It is the average normal at one of
the vertices of the polygon.
.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.
SHAR_EOF
chmod 0664 doc/sipp.man ||
echo 'restore of doc/sipp.man failed'
Wc_c="`wc -c < 'doc/sipp.man'`"
test 25439 -eq "$Wc_c" ||
echo 'doc/sipp.man: original size 25439, current size' "$Wc_c"
fi
# ============= doc/sipp_pixmap.man ==============
if test -f 'doc/sipp_pixmap.man' -a X"$1" != X"-c"; then
echo 'x - skipping doc/sipp_pixmap.man (File already exists)'
else
echo 'x - extracting doc/sipp_pixmap.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/sipp_pixmap.man' &&
.\" Copyright 1990, Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH PIXMAP 3X "July , 1991" 3X
.SH NAME
sipp_pixmap - pixmap handling code for \fIsipp\fR.
.br
sipp_bitmap - bitmap handling code for \fIsipp\fR.
X
.SH SYNOPSIS
\fI#include <sipp_pixmap.h>\fR
.br
or
.br
\fI#include <sipp_bitmap.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
X
.SH DESCRIPTION
The sipp(3X) library has provisions to create an image in a pixmap in
core. The most common use of this will probably be rendering into X
bitmaps, Macintosh bitmaps or something similar but for those who do
not want to use system dependent pixmaps we provide the
\fISipp_pixmap\fR. When rendering a line image the target is a bitmap
file or a bitmap in core rather than a pixmap. To faciliate this, we
also provide a bitmap implementation, the \fISipp_bitmap\fR.
X
.SH PIXMAP
A \fISipp_pixmap\fR is defined like this:
.sp
.IP
\fItypedef\ struct {\fR
.br
\fI int width;\fR /* Width of the pixmap */
.br
\fI int height;\fR /* Height of the pixmap */
.br
\fI u_char * buffer;\fR /* A pointer to the image. */
.br
\fI}\ Sipp_pixmap;\fR
X
The pointer \fIbuffer\fR is a pointer to the image where each pixel is
stored as three unsigned chars in the order red, green blue. Thus, the
buffer is 3 * \fIwidth\fR * \fIheight\fR bytes long.
X
The following functions operate on a \fISipp_pixmap\fR:
X
.IP \fISipp_pixmap\ *sipp_pixmap_create(width,\ height)\fR
.br
\fIint\ width;\fR
.br
\fIint\ height;\fR
.sp
Returns a new \fISipp_pixmap\fR with the given size. The memory used
is allocated using malloc(3).
X
.IP \fIvoid\ sipp_pixmap_destruct(pm)\fR
.br
\fISipp_pixmap\ *pm;\fR
.sp
Frees all memory associated to the \fISipp_pixmap pm\fR.
X
.IP \fIvoid\ sipp_pixmap_set_pixel(pm,\ x,\ y,\ red,\ grn,\ blu)\fR
.br
\fISipp_pixmap\ *pm;\fR
.br
\fIint\ x;\fR
.br
\fIint\ y;\fR
.br
\fIu_char\ red;\fR
.br
\fIu_char\ grn;\fR
.br
\fIu_char\ blu\fR
.sp
Set the pixel at (\fIx\fR, \fIy\fR) in pixmap \fIpm\fR to be the color
(\fIred\fR, \fIgrn\fR, \fIblu\fR).
X
.IP \fIvoid\ sipp_pixmap_write(file,\ pm)\fR
.br
\fIFILE\ *file;\fR
.br
\fISipp_pixmap\ *pm\fR
.sp
Write the pixmap \fIpm\fR to the open file \fIfile\fR. The image is
written in the Portable Pixmap format (ppm), the same format sipp is
using when rendering to a file.
X
.SH BITMAP
A \fISipp_bitmap\fR is defined like this:
.sp
.IP
\fItypedef\ struct {\fR
.br
\fI int width;\fR /* Width of the bitmap in pixels */
.br
\fI int height;\fR /* Height of the bitmap in pixels */
.br
\fI int width_bytes;\fR /* Width of the bitmap in bytes. */
.br
\fI u_char * buffer;\fR /* A pointer to the image. */
.br
\fI}\ Sipp_bitmap;\fR
X
The pointer \fIbuffer\fR is a pointer to the image where each pixel is
a bit in an unsigned char. If the \fIwidth\fR field is not a multiple
of 8, the last bits in the last byte of a row are not used. The most
significant bit in each byte is the leftmost pixel. The entire buffer
is \fIwidth_bytes\fR * \fIheight\fR bytes long.
X
The following functions operate on a \fISipp_bitmap\fR:
X
.IP \fISipp_bitmap\ *sipp_bitmap_create(width,\ height)\fR
.br
\fIint\ width;\fR
.br
\fIint\ height;\fR
.sp
Returns a new \fISipp_bitmap\fR with the given size. The memory used
is allocated using malloc(3).
X
.IP \fIvoid\ sipp_bitmap_destruct(bm)\fR
.br
\fISipp_bitmap\ *bm;\fR
.sp
Frees all memory associated to the \fISipp_bitmap bm\fR.
X
.IP \fIvoid\ sipp_bitmap_line(bm,\ x1,\ y1,\ x2,\ y2)\fR
.br
\fISipp_bitmap\ *bm;\fR
.br
\fIint\ x1;\fR
.br
\fIint\ y1;\fR
.br
\fIint\ x2;\fR
.br
\fIint\ y2;\fR
.sp
Draw a line from (\fIx1\fR,\ \fIy1\fR) to (\fIx2\fR,\ \fIy2\fR) in
the bitmap \fIbm\fR.
X
.IP \fIvoid\ sipp_bitmap_write(file,\ bm)\fR
.br
\fIFILE\ *file;\fR
.br
\fISipp_bitmap\ *bm\fR
.sp
Write the bitmap \fIbm\fR to the open file \fIfile\fR. The image is
written in the Portable Bitmap format (pbm), the same format sipp is
using when rendering a line drawing to a file.
X
.SH SEE ALSO
sipp(3X) - simple polygon processor, a 3d-graphics library
.br
geometric(3X) - Vector and matrix functions for the sipp(3X) library
.br
primitives(3X) - a collection of geometric primitives for \fIsipp\fR.
.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
No known bugs.
SHAR_EOF
chmod 0644 doc/sipp_pixmap.man ||
echo 'restore of doc/sipp_pixmap.man failed'
Wc_c="`wc -c < 'doc/sipp_pixmap.man'`"
test 4438 -eq "$Wc_c" ||
echo 'doc/sipp_pixmap.man: original size 4438, 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
CFLAGS = -g -I../libsipp
X
SHELL = /bin/sh
RM = rm -f
X
SRCS = torustest.c conetest.c ellipsoid.c prismtest.c chain.c \
X teapot.c structure.c planettest.c isy90.c strausstest.c woodtest.c
PROGRAMS = torustest conetest ellipsoid prismtest chain \
X teapot structure planettest isy90 strausstest woodtest
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
conetest: conetest.o ../libsipp/libsipp.a
X $(CC) -o conetest conetest.o ../libsipp/libsipp.a -lm
X
prismtest: prismtest.o ../libsipp/libsipp.a
X $(CC) -o prismtest prismtest.o ../libsipp/libsipp.a -lm
X
strausstest: strausstest.o ../libsipp/libsipp.a
X $(CC) -o strausstest strausstest.o ../libsipp/libsipp.a -lm
X
woodtest: woodtest.o ../libsipp/libsipp.a
X $(CC) -o woodtest woodtest.o ../libsipp/libsipp.a -lm
X
X
# ================================================================
X
X
clean:
X $(RM) *~ .*~ *.o $(PROGRAMS) *.p?m TAGS
X
tags:
X etags $(SRCS)
X
X
# ================================================================
X
PRETTY = chain.ppm teapot.ppm structure.ppm planet.ppm isy90.ppm
TESTS = torus.ppm cone.ppm ellipsoid.ppm prism.ppm strauss.ppm wood.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
cone.ppm: conetest
X conetest
ellipsoid.ppm: ellipsoid
X ellipsoid
prism.ppm: prismtest
X prismtest
strauss.ppm: strausstest
X strausstest
wood.ppm: woodtest
X woodtest
SHAR_EOF
chmod 0664 demo/Makefile ||
echo 'restore of demo/Makefile failed'
Wc_c="`wc -c < 'demo/Makefile'`"
test 2878 -eq "$Wc_c" ||
echo 'demo/Makefile: original size 2878, 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.1. The images here can be divided into two
categories: the mere test images (boring) and the demonstrations
images (impressive).
X
All the testprograms takes the following switches:
X
X -p Render with PHONG shading.
X -g Render with GOURAUD shading.
X -f Render with FLAT shading.
X -l Render a LINE image.
X -s n Make the image (n X n) pixels big.
X
If no switches are given, the default is to render a (256 X 256) pixels
big image with PHONG shading. Note that if "-l" is used, the resulting
image will be a bitmap and have ".pbm" as extension instead of ".ppm".
X
X
Test image Created by Explanation
---------------------------------------------------
torus.ppm torustest A plain violet torus
cone.ppm conetest One ordinary cone, one truncated
X and one 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 (PHONG mode).
prism.ppm prismtest Three orange prisms of various form.
strauss.ppm strausstest Demo of the strauss_shader(). Four
X spheres with the same color but
X different smoothness and metalness.
wood.ppm woodtest Demo of the wood shader.
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 "eroded"
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 simulated marble and
X granite texture.
SHAR_EOF
chmod 0664 demo/README ||
echo 'restore of demo/README failed'
Wc_c="`wc -c < 'demo/README'`"
test 2643 -eq "$Wc_c" ||
echo 'demo/README: original size 2643, current size' "$Wc_c"
fi
# ============= demo/animation/Makefile ==============
if test ! -d 'demo/animation'; then
echo 'x - creating directory demo/animation'
mkdir 'demo/animation'
fi
if test -f 'demo/animation/Makefile' -a X"$1" != X"-c"; then
echo 'x - skipping demo/animation/Makefile (File already exists)'
else
echo 'x - extracting demo/animation/Makefile (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/animation/Makefile' &&
# Makefile for the animation demo.
X
LIBDIR=../../libsipp
X
CC = cc
#CFLAGS = -g -I$(LIBDIR)
CFLAGS = -O4 -I$(LIBDIR)
X
PROGS = animation
X
X
all: $(PROGS)
X
clean:
X rm -f *.o *~ $(PROGS) anim??.p?m core
X
X
animation: animation.o
X $(CC) -o $@ animation.o -L$(LIBDIR) -lsipp -lm
X
SHAR_EOF
chmod 0664 demo/animation/Makefile ||
echo 'restore of demo/animation/Makefile failed'
Wc_c="`wc -c < 'demo/animation/Makefile'`"
test 273 -eq "$Wc_c" ||
echo 'demo/animation/Makefile: original size 273, current size' "$Wc_c"
fi
# ============= demo/animation/animation.c ==============
if test -f 'demo/animation/animation.c' -a X"$1" != X"-c"; then
echo 'x - skipping demo/animation/animation.c (File already exists)'
else
echo 'x - extracting demo/animation/animation.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/animation/animation.c' &&
#include <stdio.h>
#include <math.h>
X
#include <geometric.h>
#include <sipp.h>
#include <shaders.h>
#include <primitives.h>
X
extern double atof();
X
extern char *optarg;
extern int optind, opterr;
X
X
#define RESOLUTION 5
#define FLOORSIZE 15.0
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
X
typedef struct {
X double sqsize;
X Surf_desc col1;
X Surf_desc col2;
} Floor_desc;
X
X
Floor_desc floor_surf = {
X 1.0,
X { 0.4, 0.0, 0.1, {0.9900, 0.9000, 0.7900} }, /* Eggshell white */
X { 0.4, 0.0, 0.1, {0.8300, 0.2400, 0.1000} } /* English red */
};
X
X
/*
X * A shader to produce a checkered floor.
X */
X
static void
floor_shader(nx, ny, nz, u, v, w, view_vec, lights, fd, color)
X double nx, ny, nz;
X double u, v, w;
X Vector view_vec;
X Lightsource *lights;
X Floor_desc *fd;
X Color *color;
{
X Surf_desc * col;
X int intu;
X int intw;
X
X intu = floor(u / fd->sqsize);
X if (intu < 0)
X intu = -intu;
X
X intw = floor(w / fd->sqsize);
X if (intw < 0)
X intw = -intw;
X
X if ((intu ^ intw) & 1)
X col = &fd->col1;
X else
X col = &fd->col2;
X
X basic_shader(nx, ny, nz, u, v, w, view_vec, lights, col, color);
}
X
X
X
main(argc, argv)
X int argc;
X char **argv;
{
X Object *teapot; /* The teapot and its parts. */
X Object *handle;
X Object *spout;
X Object *body;
X Object *lid;
X Object *bottom;
X Transf_mat * teapot_transf;
X
X Object *floor; /* The floor. */
X
X FILE *infile;
X int image_size;
X FILE *image;
X int frame;
X int mode;
X
X double time_start; /* Animation time values. */
X double time_stop;
X double time_step;
X double time;
X double t_jump;
X double height;
X double t_scale;
X double scaling;
X double angle;
X char filename[256];
X char *file_ext;
X char c;
X
X mode = LINE;
X time_start = 0.0;
X time_stop = 1.0;
X time_step = 0.04;
X image_size = 256;
X file_ext = "pbm";
X
X while ((c = getopt(argc, argv, "pgfls:")) != EOF) {
X switch (c) {
X case 'p':
X mode = PHONG;
X file_ext = "ppm";
X break;
X
X case 'g':
X mode = GOURAUD;
X file_ext = "ppm";
X break;
X
X case 'f':
X mode = FLAT;
X file_ext = "ppm";
X break;
X
X case 'l':
X mode = LINE;
X file_ext = "pbm";
X break;
X
X case 's':
X image_size = atoi(optarg);
X break;
X }
X }
X
X
X sipp_init();
X
X
X /* Create the floor. */
X floor = sipp_block(FLOORSIZE, 1.0, FLOORSIZE, &floor_surf, floor_shader);
X object_move(floor, 0.0, -0.5, 0.0);
X object_install(floor);
X
X
X /* Create the teapot and its parts. */
X infile = fopen("../tpt_handle.bez", "r");
X handle = sipp_bezier(infile, RESOLUTION, &teapot_surf, marble_shader);
X fclose(infile);
X
X infile = fopen("../tpt_spout.bez", "r");
X spout = sipp_bezier(infile, RESOLUTION, &teapot_surf, marble_shader);
X fclose(infile);
X
X infile = fopen("../tpt_body.bez", "r");
X body = sipp_bezier(infile, RESOLUTION, &teapot_surf, marble_shader);
X fclose(infile);
X
X infile = fopen("../tpt_lid.bez", "r");
X lid = sipp_bezier(infile, RESOLUTION, &teapot_surf, marble_shader);
X fclose(infile);
X
X bottom = sipp_cylinder(0.375, 0.01, RESOLUTION * 4, &teapot_surf,
X marble_shader);
X object_rot_x(bottom, M_PI / 2.0);
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 object_add_subobj(teapot, bottom);
X object_install(teapot);
X
X
X /* Lit the stage! */
X lightsource_push(0.2, 1.0, 2.0, 1.0);
X lightsource_push(1.0, 0.5, 0.0, 0.4);
X
X
X /* Viewing parameters. */
X view_from(16.0, 4.0, 24.0);
X view_at(0.0, 1.4, 0.0);
X view_up(0.0, 1.0, 0.0);
X view_focal(0.0625);
X
X
X /*
X * The following code is quite ugly and full of magic numbers.
X * It is basically two parabolas that describe the teapots jump
X * and its "squashing" when it lands.
X */
X frame = time_start / time_step;
X time = frame * time_step;
X while (time < time_stop) {
X
X if (time < 0.65) {
X /* During the jump */
X t_jump = time * 1.94464;
X height = 6.2 * t_jump - 9.81 * t_jump * t_jump / 2.0;
X angle = 2.0 * M_PI * time / 0.65;
X scaling = 1.0;
X
X } else {
X /* During the squashing phase. */
X height = 0.0;
X angle = 0.0;
X t_scale = (time - 0.65) * 0.64533;
X scaling = 1.0 - 6.2 * t_scale + 54.9 * t_scale * t_scale / 2.0;
X }
X
X /*
X * Save the original transformation state of the teapot.
X * It is easier to recreate the proper position from scratch
X * for each new frame than to calculate the difference between
X * one image and the next.
X */
X teapot_transf = object_get_transf(teapot, NULL);
X
X /* Place the teapot in its proper position. */
X object_scale(teapot, 1.0, scaling, 1.0);
X object_move(teapot, 0.0, -0.4, 0.0);
X object_rot_z(teapot, angle);
X object_move(teapot, 0.0, 0.4, 0.0);
X object_move(teapot, 0.0, height, 0.0);
X
X sprintf(filename, "anim%02d.%s", frame, file_ext);
X image = fopen(filename, "w");
X printf("\rRendering frame %2d...", frame);
X fflush(stdout);
X
X /* Render the image. */
X render_image_file(image_size, image_size, image, mode, 3);
X fclose(image);
X
X /* Reset the teapot to its original position and shape. */
X object_set_transf(teapot, teapot_transf);
X
X frame++;
X time = frame * time_step;
X }
X
X printf("done.\n");
X exit(0);
}
SHAR_EOF
chmod 0664 demo/animation/animation.c ||
echo 'restore of demo/animation/animation.c failed'
Wc_c="`wc -c < 'demo/animation/animation.c'`"
test 5885 -eq "$Wc_c" ||
echo 'demo/animation/animation.c: original size 5885, current size' "$Wc_c"
fi
# ============= demo/animation/README ==============
if test -f 'demo/animation/README' -a X"$1" != X"-c"; then
echo 'x - skipping demo/animation/README (File already exists)'
else
echo 'x - extracting demo/animation/README (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'demo/animation/README' &&
This directory contains a small demonstration of how one can create an
animation using the SIPP library. When run, it will produce a sequence of 24
images which is an animation of a somersaulting marble teapot on top of a
checkered floor.
X
The motions are designed to be a "closed loop", i.e. the sequence can be shown
many consecutive times and the motions should still look continuous.
X
The default rendering mode is lines, so that nobody accidently overflows his
diskspace, but any rendering mode (and image size) can be chosen using the
same flags as in the other demonstration programs (see ../README).
SHAR_EOF
chmod 0664 demo/animation/README ||
echo 'restore of demo/animation/README failed'
Wc_c="`wc -c < 'demo/animation/README'`"
test 608 -eq "$Wc_c" ||
echo 'demo/animation/README: original size 608, 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 39
X
extern char *optarg;
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
X char *imfile_name;
X int mode;
X char c;
X int size;
X
X imfile_name = "chain.ppm";
X mode = PHONG;
X size = 256;
X
X while ((c = getopt(argc, argv, "pgfls:")) != EOF) {
X switch (c) {
X case 'p':
X mode = PHONG;
X imfile_name = "chain.ppm";
X break;
X
X case 'g':
X mode = GOURAUD;
X imfile_name = "chain.ppm";
X break;
X
X case 'f':
X mode = FLAT;
X imfile_name = "chain.ppm";
X break;
X
X case 'l':
X mode = LINE;
X imfile_name = "chain.pbm";
X break;
X
X case 's':
X size = atoi(optarg);
X break;
X }
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(imfile_name, "w");
X render_image_file(size, size, fp, mode, 2);
X printf("Done.\n");
X
X exit(0);
}
SHAR_EOF
chmod 0664 demo/chain.c ||
echo 'restore of demo/chain.c failed'
Wc_c="`wc -c < 'demo/chain.c'`"
test 2581 -eq "$Wc_c" ||
echo 'demo/chain.c: original size 2581, current size' "$Wc_c"
fi
true || echo 'restore of demo/conetest.c failed'
echo End of part 7, continue with part 8
exit 0
exit 0 # Just in case...