home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume21
/
sipp
/
part06
< prev
next >
Wrap
Text File
|
1991-07-23
|
40KB
|
1,243 lines
Newsgroups: comp.sources.misc
From: Jonas Yngvesson <jonas-y@isy.liu.se>
Subject: v21i031: sipp - A 3D rendering library v2.1, Part06/08
Message-ID: <1991Jul23.181745.27934@sparky.IMD.Sterling.COM>
X-Md4-Signature: 182a24e2e62f55a1e2b7ed2a11f9a9d4
Date: Tue, 23 Jul 1991 18:17:45 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: Jonas Yngvesson <jonas-y@isy.liu.se>
Posting-number: Volume 21, Issue 31
Archive-name: sipp/part06
Supersedes: sipp2.0: Volume 16, Issue 5-10
Environment: UNIX
#!/bin/sh
# This is part 06 of sipp-2.1
# ============= libsipp/xalloca.c ==============
if test ! -d 'libsipp'; then
echo 'x - creating directory libsipp'
mkdir 'libsipp'
fi
if test -f 'libsipp/xalloca.c' -a X"$1" != X"-c"; then
echo 'x - skipping libsipp/xalloca.c (File already exists)'
else
echo 'x - extracting libsipp/xalloca.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/xalloca.c' &&
#ifdef HAVE_NO_ALLOCA
X
/*
X alloca -- (mostly) portable public-domain implementation -- D A Gwyn
X
X last edit: 86/05/30 rms
X include config.h, since on VMS it renames some symbols.
X Use xmalloc instead of malloc.
X
X This implementation of the PWB library alloca() function,
X which is used to allocate space off the run-time stack so
X that it is automatically reclaimed upon procedure exit,
X was inspired by discussions with J. Q. Johnson of Cornell.
X
X It should work under any C implementation that uses an
X actual procedure stack (as opposed to a linked list of
X frames). There are some preprocessor constants that can
X be defined when compiling for your specific system, for
X improved efficiency; however, the defaults should be okay.
X
X The general concept of this implementation is to keep
X track of all alloca()-allocated blocks, and reclaim any
X that are found to be deeper in the stack than the current
X invocation. This heuristic does not reclaim storage as
X soon as it becomes invalid, but it will do so eventually.
X
X As a special case, alloca(0) reclaims storage without
X allocating any. It is a good idea to use alloca(0) in
X your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
X
#include "xalloca.h"
X
extern void free();
X
/* ================================================================ */
/* This is entered from general.h in the GNU shell bash. */
X
X
#include <stdio.h>
X
/* **************************************************************** */
/* */
/* Memory Allocation and Deallocation. */
/* */
/* **************************************************************** */
X
static char *
xmalloc (size)
X int size;
{
X char *temp = (char *)malloc (size);
X
X if (!temp) {
X fprintf (stderr, "Out of virtual memory!");
X exit(1);
X }
X
X return (temp);
}
X
X
/* ================================================================ */
X
/*
X Define STACK_DIRECTION if you know the direction of stack
X growth for your system; otherwise it will be automatically
X deduced at run-time.
X
X STACK_DIRECTION > 0 => grows toward higher addresses
X STACK_DIRECTION < 0 => grows toward lower addresses
X STACK_DIRECTION = 0 => direction of growth unknown
*/
X
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* direction unknown */
#endif
X
#if STACK_DIRECTION != 0
X
#define STACK_DIR STACK_DIRECTION /* known at compile-time */
X
#else /* STACK_DIRECTION == 0; need run-time code */
X
static int stack_dir; /* 1 or -1 once known */
#define STACK_DIR stack_dir
X
static void
find_stack_direction (/* void */)
{
X static char *addr = NULL; /* address of first
X `dummy', once known */
X auto char dummy; /* to get stack address */
X
X if (addr == NULL)
X { /* initial entry */
X addr = &dummy;
X
X find_stack_direction (); /* recurse once */
X }
X else /* second entry */
X if (&dummy > addr)
X stack_dir = 1; /* stack grew upward */
X else
X stack_dir = -1; /* stack grew downward */
}
X
#endif /* STACK_DIRECTION == 0 */
X
/*
X An "alloca header" is used to:
X (a) chain together all alloca()ed blocks;
X (b) keep track of stack depth.
X
X It is very important that sizeof(header) agree with malloc()
X alignment chunk size. The following default should work okay.
*/
X
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
X
typedef union hdr
{
X char align[ALIGN_SIZE]; /* to force sizeof(header) */
X struct
X {
X union hdr *next; /* for chaining headers */
X char *deep; /* for stack depth measure */
X } h;
} header;
X
/*
X alloca( size ) returns a pointer to at least `size' bytes of
X storage which will be automatically reclaimed upon exit from
X the procedure that called alloca(). Originally, this space
X was supposed to be taken from the current stack frame of the
X caller, but that method cannot be made to work for some
X implementations of C, for example under Gould's UTX/32.
*/
X
static header *last_alloca_header = NULL; /* -> last alloca header */
X
pointer
alloca (size) /* returns pointer to storage */
X unsigned size; /* # bytes to allocate */
{
X auto char probe; /* probes stack depth: */
X register char *depth = &probe;
X
#if STACK_DIRECTION == 0
X if (STACK_DIR == 0) /* unknown growth direction */
X find_stack_direction ();
#endif
X
X /* Reclaim garbage, defined as all alloca()ed storage that
X was allocated from deeper in the stack than currently. */
X {
X register header *hp; /* traverses linked list */
X
X for (hp = last_alloca_header; hp != NULL;)
X if (STACK_DIR > 0 && hp->h.deep > depth
X || STACK_DIR < 0 && hp->h.deep < depth)
X {
X register header *np = hp->h.next;
X
X free ((pointer) hp); /* collect garbage */
X
X hp = np; /* -> next header */
X }
X else
X break; /* rest are not deeper */
X
X last_alloca_header = hp; /* -> last valid storage */
X }
X
X if (size == 0)
X return NULL; /* no allocation required */
X
X /* Allocate combined header + user data storage. */
X
X {
X register pointer new = xmalloc (sizeof (header) + size);
X /* address of header */
X
X ((header *)new)->h.next = last_alloca_header;
X ((header *)new)->h.deep = depth;
X
X last_alloca_header = (header *)new;
X
X /* User storage begins just after header. */
X
X return (pointer)((char *)new + sizeof(header));
X }
}
X
#endif /* HAVE_NO_ALLOCA */
SHAR_EOF
chmod 0664 libsipp/xalloca.c ||
echo 'restore of libsipp/xalloca.c failed'
Wc_c="`wc -c < 'libsipp/xalloca.c'`"
test 5405 -eq "$Wc_c" ||
echo 'libsipp/xalloca.c: original size 5405, current size' "$Wc_c"
fi
# ============= libsipp/xalloca.h ==============
if test -f 'libsipp/xalloca.h' -a X"$1" != X"-c"; then
echo 'x - skipping libsipp/xalloca.h (File already exists)'
else
echo 'x - extracting libsipp/xalloca.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/xalloca.h' &&
#ifdef HAVE_NO_ALLOCA
X
#ifdef X3J11
typedef void *pointer; /* generic pointer type */
pointer alloca (unsigned); /* returns pointer to storage */
#else
typedef char *pointer; /* generic pointer type */
pointer alloca (); /* returns pointer to storage */
#endif /* X3J11 */
X
#else
X
#include <alloca.h>
X
#endif
SHAR_EOF
chmod 0664 libsipp/xalloca.h ||
echo 'restore of libsipp/xalloca.h failed'
Wc_c="`wc -c < 'libsipp/xalloca.h'`"
test 314 -eq "$Wc_c" ||
echo 'libsipp/xalloca.h: original size 314, current size' "$Wc_c"
fi
# ============= doc/geometric.man ==============
if test ! -d 'doc'; then
echo 'x - creating directory doc'
mkdir 'doc'
fi
if test -f 'doc/geometric.man' -a X"$1" != X"-c"; then
echo 'x - skipping doc/geometric.man (File already exists)'
else
echo 'x - extracting doc/geometric.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/geometric.man' &&
.\" Copyright Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH GEOMETRIC 3X "July , 1991" 3X
.SH NAME
geometric - Vector and matrix functions for the sipp(3X) library
X
.SH SYNOPSIS
\fI#include <geometric.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
X
.SH DESCRIPTION
The sipp(3X) 3D rendering library uses a lot of vector calculations
and geometric transformations. The functions which implement these
features are declared in geometric.h and are described in this manual.
X
.SH VECTOR OPERATIONS
Sipp uses row vectors, not column vectors and a vector is defined as
follows:
X
\fItypedef \ struct\ {\fR
.br
\fI double\ x;\fR
.br
\fI double\ y;\fR
.br
\fI double\ z;\fR
.br
\fI}\ Vector;\fR
X
A vector is used both for directional vectors and points (positional
vectors). In the description of the sipp vector macros and functions
below, lower case letters denote scalar values and upper case letters
denote vectors.
X
.IP \fIMakeVector(V,\ xx,\ yy,\ zz)
Put \fIxx\fR, \fIyy\fR and \fIzz\fR in the x, y and z slot of the
Vector \fIV\fR respectively.
X
.IP \fIVecNegate(A)\fR
Negate all components of the Vector \fIA\fR.
X
.IP \fIVecDot(A,\ B)\fR
Return the dot product of the two Vectors \fIA\fR and \fIB\fR.
X
.IP \fIVecLen(A)\fR
Return the length of the Vector \fIA\fR.
X
.IP \fIVecCopy(B,\ A)\fR
Copy the Vector \fIA\fR to the Vector \fIB\fR (\fIB\fR = \fIA\fR;
using C notation).
X
.IP \fIVecAdd(C,\ A,\ B)\fR
Add the two Vectors \fIA\fR and \fIB\fR and put the result in \fIC\fR
(Add \fIA\fR to \fIB\fR giving \fIC\fR; using COBOL notation).
X
.IP \fIVecSub(C,\ A,\ B)\fR
Subtract the Vector \fIB\fR from Vector \fIA\fR and put the result in
\fIC\fR (\fIC\fR = \fIA\fR - \fIB\fR; using C notation).
X
.IP \fIVecScalMul(B,\ a,\ A)\fR
Multiply the Vector \fIA\fR with the scalar \fIa\fR and put the result
in Vector \fIB\fR (\fIB\fR = \fIa\fR * \fIA\fR; using C notation).
X
.IP \fIVecAddS(C,\ a,\ A,\ B)\fR
Multiply the Vector \fIA\fR with the scalar \fIa\fR, add it to Vector
\fIB\fR and put the result in Vector \fIC\fR (\fIC\fR = \fIa\fR *
\fIA\fR + \fIB\fR; using C notation).
X
.IP \fIVecComb(C,\ a,\ A,\ b,\ B)\fR
Linearly combine the two Vectors \fIA\fR and \fIB\fR and put the
result in Vector \fIC\fR (\fIC\fR = \fIa\fR * \fIA\fR + \fIb\fR *
\fIB\fR; using C notation).
X
.IP \fIVecCross(C,\ A,\ B)\fR
Cross multiply Vector \fIA\fR with Vector \fIB\fR and put the result
in \fIC\fR (\fIC\fR = \fIA\fR X \fIB\fR; using C notation).
X
.IP \fIvoid\ vecnorm(v)\fR
.br
\fIVector\ *v;\fR
.sp
Normalize the vector \fIv\fR, i.e. keep the direction but make it have
length 1. The length of \fIv\fR should not be equal to 0 to begin with.
.B NOTE:
This is the only function operating on vectors in sipp.
X
.SH MATRIX OPERATIONS
An ordinary homogenous transformation matrix has 4 X 4 elements.
However, all linear transformations only use 4 X 3 values so to save
space a sipp transformation matrix only store 4 X 3 values. Thus the
transformation matrix used in sipp is defined as follows:
X
\fItypedef\ struct\ {\fR
.br
\fI double\ mat[4][3];\fR
.br
\fI}\ Transf_mat;\fR
X
We wrap a struct around the two-dimensional array since we want to be
able to say things like \fI&mat\fR without being forced to write
\fI(Transf_mat\ *)\ &mat[0]\fR which we find horribly ugly.
X
There is a predefined identity matrix declared in geometric.h which
you can use if you want to:
X
\fIextern\ Transf_mat\ ident_matrix;\fR
X
The rest of this section describes the macro and functions defined in
the sipp library which work on sipp transformation matrixes.
X
.IP \fIMatCopy(A,\ B)\fR
This macro copies the matrix \fIB\fR to the matrix \fIA\fR. \fIA\fR
and \fIB\fR should both be pointers.
.B NOTE:
This is the only macro operating on matrices in sipp.
X
X
.IP \fITransf_mat\ *transf_mat_create(initmat)\fR
.br
\fITransf_mat\ *initmat;\fR
.sp
Allocate memory for a new transformation matrix and if \fIinitmat\fR
is equal to \fINULL\fR, set the new matrix to the identity matrix.
Otherwise set the new matrix to the contents of \fIinitmat\fR. Return
a pointer to the new matrix.
X
.IP \fITransf_mat\ *transf_mat_destruct(mat)\fR
.br
\fITransf_mat\ *initmat;\fR
.sp
Free the memory associated with the matrix \fImat\fR.
X
.IP \fIvoid\ mat_translate(mat,\ dx,\ dy,\ dz)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIdouble\ dx;\fR
.br
\fIdouble\ dy;\fR
.br
\fIdouble\ dz;\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
translation along the vector (\fIdx\fR,\ \fIdy\fR,\ \fIdz\fR).
X
.IP \fIvoid\ mat_rotate_x(mat,\ ang)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIdouble\ ang;\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
rotation with the angle \fIang\fR around the X axis. The angle
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ mat_rotate_y(mat,\ ang)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIdouble\ ang;\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
rotation with the angle \fIang\fR around the Y axis. The angle
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ mat_rotate_z(mat,\ ang)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIdouble\ ang;\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
rotation with the angle \fIang\fR around the Z axis. The angle
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ mat_rotate(mat,\ point,\ vector,\ ang)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIVector\ *point;\fR
.br
\fIVector\ *vector\fR
.br
\fIdouble\ ang;\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
rotation with the angle \fIang\fR around the line represented by the
point \fIpoint\fR and the vector \fIvector\fR. The angle
\fIang\fR is expressed in radians.
X
.IP \fIvoid\ mat_scale(mat,\ xscale,\ yscale,\ zscale)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIdouble\ xscale;\fR
.br
\fIdouble\ yscale;\fR
.br
\fIdouble\ zscale;\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
scaling with the scaling factors (\fIxscale\fR,\ \fIyscale\fR,\ \fIzscale\fR).
X
.IP \fIvoid\ mat_mirror_plane(mat,\ point,\ normal)\fR
.br
\fITransf_mat\ *mat;\fR
.br
\fIVector\ *point;\fR
.br
\fIVector\ *normal\fR
.sp
Set \fImat\fR to the transformation matrix that represents the
concatenation of the previous transformation in \fImat\fR and a
mirroring in the plane defined by the point \fIpoint\fR and the normal
vector \fInormal\fR.
X
.IP \fIvoid\ mat_mul(res,\ a,\ b)\fR
.br
\fITransf_mat\ *res\fR
.br
\fITransf_mat\ *a\fR
.br
\fITransf_mat\ *b\fR
.sp
Multiply the two matrixes \fIa\fR and \fIb\fR and put the result in
the matrix \fIres\fR. All three parameters are pointers to matrixes.
It is possible for \fIres\fR to point at the same matrix as either
\fIa\fR or \fIb\fR since the result is stored in a temporary matrix
during the computations.
X
.IP \fIvoid\ point_transform(res,\ vec,\ mat)\fR
.br
\fIVector\ *res\fR
.br
\fIVector\ *vec;\fR
.br
\fITransf_mat\ *mat;\fR
.sp
Transform the point (vector) \fIvec\fR with the transformation matrix
\fImat\fR and put the result into the vector \fIres\fR. The two
vectors \fIres\fR and \fIvec\fR should not be the same vector since no
temporary is used during the computations.
X
.SH SEE ALSO
sipp(3X) - simple polygon processor, a 3d-graphics library
.br
shaders(3X) - a collection of shaders for \fIsipp\fR.
.br
primitives(3X) - a collection of object 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
No known bugs.
SHAR_EOF
chmod 0644 doc/geometric.man ||
echo 'restore of doc/geometric.man failed'
Wc_c="`wc -c < 'doc/geometric.man'`"
test 8030 -eq "$Wc_c" ||
echo 'doc/geometric.man: original size 8030, current size' "$Wc_c"
fi
# ============= doc/primitives.man ==============
if test -f 'doc/primitives.man' -a X"$1" != X"-c"; then
echo 'x - skipping doc/primitives.man (File already exists)'
else
echo 'x - extracting doc/primitives.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/primitives.man' &&
.\" Copyright 1990, Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH PRIMITIVES 3X "December , 1990" 3X
.SH NAME
primitives - a collection of object primitives for \fIsipp\fR.
.SH SYNOPSIS
\fI#include <primitives.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
X
.SH DESCRIPTION
\fIsipp\fR gives the user access to a number of rather low level functions
to create polygons, surfaces and objects. This manual describes a set of
functions that use the low level functions in \fIsipp\fR to create
geometric primitives. Each primitive is a complete \fIsipp\fR object.
.sp
All primitives described here will get texture coordinates equal to the
respective world coordinates.
X
.SH PRIMITIVES
.IP \fIObject\ *sipp_torus(bigradius,\ smallradius,\ res1,\ res2,\ surface,\ shader)\fR
.br
\fIdouble\ bigradius;\fR
.br
\fIdouble\ smallradius;\fR
.br
\fIint\ res1;\fR
.br
\fIint\ res2;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_torus()\fR creates a torus centered about the origin and with the
z-axis pointing up through the ring. \fIbigradius\fR is the radius of the
ring and \fIsmallradius\fR is the radius of the "tube" itself. \fIres1\fR
is the number of polygons that will be created radially around the ring
and \fIres2\fR is the number of polygons that will be created around the
tube. \fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the torus.
X
.IP \fIObject\ *sipp_cone(bot_rad,\ ,top_rad,\ length,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\ bot_rad;\fR
.br
\fIdouble\ top_rad;\fR
.br
\fIdouble\ length;\fR
.br
\fIint\ resolution;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_cone()\fR creates a cone centered about the origin and with the z-axis
along the cones main axis. \fIbot_rad\fR and \fItop_rad\fR determines the
radius of the cone in its bottom and top, if both of these are non zero a
truncated cone is created. \fIlength\fR defines the length of the cone.
\fIresolution\fR is the number of polygons that will be created radially
around the rim. \fIsurface\fR is the surface description used by
\fIshader()\fR which is the shading function used when shading the cone.
X
.IP \fIObject\ *sipp_cylinder(radius,\ length,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\ radius;\fR
.br
\fIdouble\ length;\fR
.br
\fIint\ resolution;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_cylinder()\fR creates a cylinder centered about the origin and with the
z-axis along the cylinders main axis. \fIradius\fR and \fIlength\fR
defines the size of the cylinder. \fIresolution\fR
is the number of polygons that will be created radially around the rim.
\fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the cylinder.
X
.IP \fIObject\ *sipp_ellipsoid(x_rad,\ y_rad,\ z_rad,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\ x_rad;\fR
.br
\fIdouble\ y_rad;\fR
.br
\fIdouble\ z_rad;\fR
.br
\fIint\ resolution;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_ellipsoid()\fR creates a ellipsoid centered about the origin.
\fIx_rad\fR, \fIy_rad\fR and \fIz_rad\fR
defines the size of the ellipsoid. \fIresolution\fR
is the number of polygons that will be created around it's "equator".
\fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the ellipsoid.
X
.IP \fIObject\ *sipp_sphere(radius,\ resolution,\ surface,\ shader)\fR
.br
\fIdouble\ radius;\fR
.br
\fIint\ resolution;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_sphere()\fR creates a sphere centered about the origin.
\fIradius\fR defines the size of the sphere. \fIresolution\fR
is the number of polygons that will be created around it's "equator".
\fIsurface\fR is the surface description used by \fIshader()\fR
which is the shading function used when shading the sphere.
X
.IP \fIObject\ *sipp_prism(num_points,\ points,\ length,\ surface,\ shader)\fR
.br
\fIint\ num_points;\fR
.br
\fIVector\ *points;\fR
.br
\fIdouble\ length;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_prism()\fR creates a prism defined by the polygon in
\fIpoints\fR. Only the x and y values are used and the prism will
ascend and descend equally far (\fIlength\fR / 2.0) from the x-y plane
along the z axis. The number of points in the polygon is determined
by \fInum_points\fR. \fIsurface\fR is the surface description used by
\fIshader()\fR which is the shading function used when shading the
prism.
X
.IP \fIObject\ *sipp_block(x_size,\ y_size,\ z_size,\ surface,\ shader)\fR
.br
\fIdouble\ x_size;\fR
.br
\fIdouble\ y_size;\fR
.br
\fIdouble\ z_size;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_block()\fR creates a square block with the size defined by
\fIx_size\fR, \fIz_size\fR and \fIz_size\fR. The block is centered
about the origin. \fIsurface\fR is the surface description used by
\fIshader()\fR which is the shading function used when shading the
block.
X
.IP \fIObject\ *sipp_cube(side,\ surface,\ shader)\fR
.br
\fIdouble\ side;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_cube()\fR creates a cube with the side of length \fIside\fR. The
cube is centered about the origin. \fIsurface\fR is the surface description
used by \fIshader()\fR which is the shading function used when shading the
cube.
X
.IP \fIObject\ *sipp_bezier(file,\ res,\ surface,\ shader)\fR
.br
\fIFILE\ *file;\fR
.br
\fIint\ res;\fR
.br
\fIvoid\ *surface;\fR
.br
\fIShader\ *shader;\fR
.sp
\fIsipp_bezier()\fR reads a file containing descriptions of a set of bezier
patches or bezier curves. If the file contains descriptions of patches, these
patches will be tesselated into \fIres\fR by \fIres\fR polygons and installed
in a \fIsipp\fR object as one surface. The surface will be shaded by
\fIshader\fR using the surface description \fIsurface\fR.
.sp
If the file contains descriptions of curves, a rotational surface will be
created by rotating these curves about the y-axis. The resulting surface will
be tesselated into polygons and installed in a \fIsipp\fR object as one
surface. The surface will be shaded by \fIshader\fR using the surface
description \fIsurface\fR.
.sp
The format of the description file is rather simple. First a keyword defining
the type of description in the file, \fIbezier_curves:\fR or
\fIbezier_patches:\fR. Then follows a description of the vertices (control
points). First the word \fIvertices:\fR followed by an integer number that
tells how many vertices there are in the description, then the word
\fIvertex_list:\fR followed by the x, y and z coordinates for each vertex. The
number of vertices must be same as the number given above. This is, however,
not checked for.
.sp
If the file contains curves, the keyword \fIcurves:\fR followed by the number
of bezier curves in the file stand on the next line. After this line, a line
with the single keyword \fIcurve_list:\fR follows. Lastly, the bezier curves
themselves follow as numbers in groups of four by four. Each number is an
index into the vertex list with the first index having number 1.
.sp
If the file contains patches, the format is the same with the following
exceptions: The word \fIpatches:\fR is substituted for \fIcurves:\fR, the word
\fIpatch_list:\fR is substituted for \fIcurve_list:\fR and the indices into
the vertex list are grouped 16 by 16 instead of 4 by 4.
.sp
Comments can be inserted anywhere in a bezier curve/patch description file by
using the hashmark character, #. The comment lasts to the end of the line.
.sp
See any standard computer graphics reference, e.g. Newman & Sproull, for a
more detailed description of Bezier curves and patches.
.sp
Example: the body of a standard Newell teapot.
.sp
.nf
# Bezier curves (rotational body) for teapot body.
X
bezier_curves:
X
vertices: 10
vertex_list:
X 3.500000E-01 5.625000E-01 0.000000E+00
X 3.343750E-01 5.953125E-01 0.000000E+00
X 3.593750E-01 5.953125E-01 0.000000E+00
X 3.750000E-01 5.625000E-01 0.000000E+00
X 4.375000E-01 4.312500E-01 0.000000E+00
X 5.000000E-01 3.000000E-01 0.000000E+00
X 5.000000E-01 1.875000E-01 0.000000E+00
X 5.000000E-01 7.500000E-02 0.000000E+00
X 3.750000E-01 1.875000E-02 0.000000E+00
X 3.750000E-01 0.000000E+00 0.000000E+00
X
curves: 3
curve_list:
X
X 1 2 3 4
X
X 4 5 6 7
X
X 7 8 9 10
X
#End of teapot bezier file
.fi
X
.SH SEE ALSO
sipp(3X) - simple polygon processor, a 3d-graphics library
.br
shaders(3X) - a collection of shaders for \fIsipp\fR.
.br
geometric(3X) - Vector and matrix functions for the sipp(3X) library
.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
The format for the bezier patches and curves is prohibitively ugly.
SHAR_EOF
chmod 0664 doc/primitives.man ||
echo 'restore of doc/primitives.man failed'
Wc_c="`wc -c < 'doc/primitives.man'`"
test 9153 -eq "$Wc_c" ||
echo 'doc/primitives.man: original size 9153, current size' "$Wc_c"
fi
# ============= doc/shaders.man ==============
if test -f 'doc/shaders.man' -a X"$1" != X"-c"; then
echo 'x - skipping doc/shaders.man (File already exists)'
else
echo 'x - extracting doc/shaders.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'doc/shaders.man' &&
.\" Copyright 1990, Jonas Yngvesson, Inge Wallin
.\" This program and documentation may be distributed freely under
.\" the terms of GNU GENERAL PUBLIC LICENSE.
.TH SHADERS 3X "December , 1990" 3X
.SH NAME
shaders - a collection of shaders for \fIsipp\fR.
.SH SYNOPSIS
\fI#include <sipp.h>\fR
.br
\fI#include <shaders.h>\fR
.sp
[g]cc [\fIflags\fR] \fIfiles\fR -lsipp -lm [ \fIlibraries\fR ]
X
.SH DESCRIPTION
\fIsipp\fR provides, internally, a simple shading model and a shading
function called \fIbasic_shader()\fR. If this shader is not sufficient for a
particular surface, the user can
implement his/her own shading function and have \fIsipp\fR call that one
instead. Different shaders usually
need different parameters to describe the surface. \fIsipp\fR supports this by
allowing every shader to have it's own unique kind of structure stored with
the surface that is to be shaded with that shader.
The structure used for \fIbasic_shader()\fR
is called \fISurf_desc\fR. See \fIsipp\fR(3X) for more details about
shaders and their parameters.
.sp
This manual describes the parameters for a \fIsipp\fR shading function and a
set of shaders beside \fIbasic_shader()\fR that are included in the library.
All shaders described here, except \fIstrauss_shader()\fR, provide some kind of
special effect on a surface and call \fIbasic_shader()\fR to do the actual
shading calculations.
X
.SH SIPP SHADING FUNCTIONS
Each surface in a scene has a shading function associated with it.
This function is called by \fIsipp\fR as the surface 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 my_surf_desc *surface;\fR
.br
\fI Color\ *color;\fR
.sp
\fInx, ny\fR and \fInz\fR is the \fInon-normalized\fR surface normal at the
point that should be rendered.
.br
\fIu, v\fR and \fIw\fR are the interpolated texture coordinates at the rendered
point. If no texture coordinates have been given at some vertices these
values are undefined and contains garbage at best.
.br
\fIview_vec\fR is a normalized vector, pointing from the rendered
point at the viewpoint.
.br
\fIlights\fR is a pointer to a linked list of lightsource descriptions. See
the function \fIlightsource_push()\fR for a description of the structure of
the links.
.br
\fIsurface\fR is the same \fIsurface\fR-pointer that was sent to the
function \fIsurface_create()\fR. In the case of \fIbasic_shader\fR this is
a pointer to a \fISurf_desc\fR. If the user provides his own shader, he
can also provide his own surface description.
.br
Upon return, the shader should place the calculated rgb colour
components in the areas pointed to by \fIcolor\fR. The rgb components
must be values between 0 and 1.
X
.SH SHADERS AND SURFACE DESCRIPTORS
The following shader functions are provided with the \fIsipp\fR library.
X
.IP \fIstrauss_shader()\fR
\fIstrauss_shader()\fR is an implementation of a shader described by Paul
Strauss in IEEE CG&A Nov. 1990. In his article he explains that most shading
models in use today, ie Phong, Cook-Torrance, are difficult to use for
non-experts, and this for several reasons. The parameters and their effect on
a surface are non-intuitive and/or complicated. The shading model Strauss
designed has parameters that is easy to grasp and have a reasonably
deterministic effect on a surface, but yet produces very realistic results.
.sp
The surface description used in \fIstrauss_shader()\fR is called
\fIStrauss_desc\fR and looks like this:
.br
\fItypedef struct {\fR
.br
\fI\ double ambient;\fR
.br
\fI\ double smoothness;\fR
.br
\fI\ double metalness;\fR
.br
\fI\ Color color;\fR
.br
\fI} Strauss_desc;\fR
.sp
\fIambient\fR is a value between 0 and 1 which determines how much of the base
color of a surface that is visible when it is not illuminated by any
lightsource.
.br
\fIsmoothness\fR is a value between 0 and 1 that describes how smooth the
surface is. This parameter controls both diffuse and specular reflections. 0
means a dull surface while 1 means a very smooth and shiny one.
.br
\fImetalness\fR is alo a value between 0 and 1. It describes how metallic the
material is. It controls among other things how much of the surface color
should be mixed into the specular reflections at different angles. 0 means a
non-metal while 1 means a very metallic surface.
.br
\fIcolor\fR is (of course) the base color of the surface.
X
.IP \fIwood_shader()\fR
\fIwood_shader()\fR creates a simulated wood texture on a surface.
It uses two colors, one as the base (often lighter) color of the wood
and one as the color of the (often darker) rings in it.
The rings is put into the base color about the x-axis and are then distorted
using \fInoise()\fR and \fIturbulence()\fR. A similar pattern is repeated at
regular intervals to create an illusion of logs or boards.
.sp
The surface description for a wood surface is called
\fIWood_desc\fR and is defined as follows:
.br
\fItypedef struct {\fR
.br
\fI\ double ambient;\fR
.br
\fI\ double specular;\fR
.br
\fI\ double c3;\fR
.br
\fI\ double scale;\fR
.br
\fI\ Color base;\fR
.br
\fI\ Color ring;\fR
.br
\fI} Wood_desc;\fR
.sp
Except for the two colors and the field \fIscale\fR, \fIWood_desc\fR
looks exactly like a \fISurf_desc\fR and the fields are used in the
same way.
.br
\fIscale\fR is a factor which determines the size of the
wood pattern depending on the size of the texture coordinate system
in relation to the world coordinate system. You will have to
experiment some to get this right.
.br
\fIbase\fR is the color of the base material, and \fIring\fR is the
color of the darker rings.
X
.IP \fImarble_shader()\fR
\fImarble_shader()\fR creates a simulated marble texture on a surface.
It uses two colors, one as the base material and one as the
interspersed material. The interspersed material is put into the
base material in strips that are distorted using \fInoise()\fR and
\fIturbulence()\fR.
.sp
The surface description for a marble surface is called
\fIMarble_desc\fR and is defined as follows:
.br
\fItypedef struct {\fR
.br
\fI\ double ambient;\fR
.br
\fI\ double specular;\fR
.br
\fI\ double c3;\fR
.br
\fI\ double scale;\fR
.br
\fI\ Color base;\fR
.br
\fI\ Color strip;\fR
.br
\fI} Marble_desc;\fR
.sp
Except for the two colors and the field \fIscale\fR, \fIMarble_desc\fR
looks exactly like a \fISurf_desc\fR and the fields are used in the
same way.
.br
\fIscale\fR is a factor which determines the size of the
marble pattern depending on the size of the texture coordinate system
in relation to the world coordinate system.
.br
\fIbase\fR is the color of the base material, and \fIstrip\fR is the
color of the interspersed material.
X
.IP \fIgranite_shader()\fR
\fIgranite_shader()\fR is very similar to \fImarble_shader()\fR in
that it also
mixes two colors using \fInoise()\fR and \fIturbulence()\fR. The
difference is in
how the mixing is done. The two colors are mixed whithout treating
them separately in any way.
.sp
The surface description used in \fIgranite_shader()\fR is called
\fIGranite_desc\fR and is defined as follows:
.br
\fItypedef struct {\fR
.br
\fI\ double ambient;\fR
.br
\fI\ double specular;\fR
.br
\fI\ double c3;\fR
.br
\fI\ double scale;\fR
.br
\fI\ Color col1;\fR
.br
\fI\ Color col2;\fR
.br
\fI} Granite_desc;\fR
.sp
The fields have the same meaning as in \fIMarble_desc\fR.
X
.IP \fIbozo_shader()\fR
\fIbozo_shader()\fR uses \fInoise()\fR to chose a color from a fixed set.
The range of possible return value from \fInoise()\fR are divided into parts
of equal size and each part is assigned a color. The size of the parts
are dependent on the number of colors.
.sp
The surface description is called \fIBozo_desc\fR and is defined as
follows:
.br
\fItypedef struct {\fR
.br
\fI\ Color *colors;\fR
.br
\fI\ int no_of_cols;\fR
.br
\fI\ double ambient;\fR
.br
\fI\ double specular;\fR
.br
\fI\ double c3;\fR
.br
\fI\ double scale;
.br
\fI} Bozo_desc;\fR
.sp
\fIcolors\fR is a pointer to an array of \fIColor\fR structs and
\fIno_of_cols\fR defines the number of entries in this array. The other
fields have the same function as in the prevoiusly described shaders.
X
.IP \fImask_shader()\fR
\fImask_shader()\fR uses another image (ususally a bitmap) as a mask,
and calls two different shaders depending on the values in this image.
The mask image can be of any format. The user supplies a pointer
to the image and a function that tests the value of a certain pixel in it.
The mapping uses only the \fIu\fR and \fIv\fR texture coordinates.
.sp
The surface description is called \fIMask_desc\fR and has the
following definition:
.br
\fItypedef struct {\fR
.br
\fI\ Shader *fg_shader;\fR
.br
\fI\ void *fg_surface;\fR
.br
\fI\ Shader *bg_shader;\fR
.br
\fI\ void *bg_surface;\fR
.br
\fI\ void *mask;\fR
.br
\fI\ bool (*pixel_test)();\fR
.br
\fI\ int x0, y0;\fR
.br
\fI\ int xsize, ysize;\fR
.br
\fI\ double xscale, yscale;\fR
.br
\fI} Mask_desc;\fR
.sp
\fIfg_shader\fR is used together with the surface description
\fIfg_surface\fR when \fIpixel_test\fR (see below) returns TRUE.
.br
\fIbg_shader\fR is used together with the surface description
\fIbg_surface\fR when \fIpixel_test\fR (see below) returns FALSE.
.br
\fImask\fR is a pointer to the image. This could be a pointer to a raw array
of pixels or a complicated struct, the image representation is completely up
to the user.
.br
\fIpixel_test\fR is a function that is called to evaluate pixels in the mask
image. This function should be declared as follows:
.br
\fI\ bool my_pixel_test(image, x, y)\fR
.br
\fI\ my_image_struct *image;\fR
.br
\fI\ int x, y;\fR
.br
\ \ \fIimage\fR is the same pointer that is stored in the \fIMask_desc\fR.
.br
\ \ \fIx\fR and \fIy\fR are the coordinates of the pixel that should be
tested.
.br
\fIx0\fR and \fIy0\fR define where (in mask image coordinates) the
origo of the texture coordinate system should be placed.
.br
\fIxsize\fR and \fIysize\fR is the size of the mask image.
.br
\fIxscale\fR and \fIyscale\fR scales the texture coordinate system
relative the mask image coordinates.
X
.IP \fIbumpy_shader()\fR
\fIbumpy_shader()\fR is a function that perturbates the normal of a
surface using \fIDnoise()\fR. Any other shader can be used to do the final
shading calculations.
.sp
The surface description is called \fIBumpy_desc\fR and is defined as
follows:
.br
\fItypedef struct {\fR
.br
\fI\ Shader *shader;\fR
.br
\fI\ void *surface;\fR
.br
\fI\ double scale;\fR
.br
\fI\ bool bumpflag;\fR
.br
\fI\ bool holeflag;\fR
.br
\fI} Bumpy_desc;\fR
.sp
\fIshader\fR and \fIsurface\fR define the shader to be used for the
final shading calculations.
.br
\fIscale\fR has the same meaning as in previous shaders using \fInoise()\fR.
.br
\fIbumpflag\fR and \fIholeflag\fR make it possible to flatten out
half of the bumps. If only \fIbumpflag\fR is TRUE only bumps "standing
out" from the surface are visible. The rest of the surface will be smooth.
If, on the other hand, only \fIholeflag\fR is TRUE only bumps going
"into" the surface will be visible, thus giving the surface an
eroded look. If both flags are true, the whole surface will get a
bumpy appearence, rather like an orange.
X
.IP \fIplanet_shader()\fR
\fIplanet_shader()\fR is a somewhat specialized shader that produces a texture
that resembles a planet surface. The planet is of the Tellus type with a
mixture of oceans and continents. Some of the surface is covered by
semi-transparent clouds which enhances the effect greatly. On the other hand,
no polar caps are provided and this decreases the realism.
.sp
The texture is 3-dimensional, so it is possible to create cube planets or even
planets with cut-out parts that still have surfaces that resemble the earth
surface. The texture is not scalable, and is designed to be used with texture
coordinats in the range -1.0 to 1.0, e.g. a unit sphere. Of course the world
coordinats need not have the same order of magnitude.
.sp
\fIplanet_shader()\fR uses an ordinary \fISurf_desc\fR in which the
\fIcolor\fR field is ignored.
X
.SH SEE ALSO
sipp(3X) - simple polygon processor, a 3d-graphics library
.br
geometric - Vector and matrix functions for the sipp(3X) library
.br
primitives(3X) - a collection of geometric primitives for \fIsipp\fR.
.br
sipp_pixmapq(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
The planet texture should be enhanced with polar caps and it should be
possible to give parameters to control, among other factors, the ratio of
ocean/land and the cloudiness.
SHAR_EOF
chmod 0664 doc/shaders.man ||
echo 'restore of doc/shaders.man failed'
Wc_c="`wc -c < 'doc/shaders.man'`"
test 13374 -eq "$Wc_c" ||
echo 'doc/shaders.man: original size 13374, current size' "$Wc_c"
fi
true || echo 'restore of doc/sipp.man failed'
echo End of part 6, continue with part 7
exit 0
exit 0 # Just in case...