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