From pa.dec.com!decwrl!uunet!sparky!kent Thu Jul 25 08:56:42 PDT 1991
Article: 2528 of comp.sources.misc
Newsgroups: comp.sources.misc
Path: pa.dec.com!decwrl!uunet!sparky!kent
From: Jonas Yngvesson <jonas-y@isy.liu.se>
Subject:  v21i028:  sipp - A 3D rendering library v2.1, Part03/08
Message-ID: <1991Jul23.181639.27742@sparky.IMD.Sterling.COM>
X-Md4-Signature: 9437cc6be08ae2027e031f34838dc298
Keywords: rendering graphics z-buffer
Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield)
Organization: Dept of EE, University of Linkoping
References: <csm-v21i026=sipp.130352@sparky.imd.sterling.com>
Date: Tue, 23 Jul 1991 18:16:39 GMT
Approved: kent@sparky.imd.sterling.com
Lines: 1593

Submitted-by: Jonas Yngvesson <jonas-y@isy.liu.se>
Posting-number: Volume 21, Issue 28
Archive-name: sipp/part03
Supersedes: sipp2.0: Volume 16, Issue 5-10
Environment: UNIX

#!/bin/sh
# This is part 03 of sipp-2.1
# ============= libsipp/noise.c ==============
if test ! -d 'libsipp'; then
    echo 'x - creating directory libsipp'
    mkdir 'libsipp'
fi
if test -f 'libsipp/noise.c' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/noise.c (File already exists)'
else
echo 'x - extracting libsipp/noise.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/noise.c' &&
#include <math.h>
X
#include <sipp.h>
#include <noise.h>
X
/* ================================================================ */
/*                      Noise and friends                           */
X
X
/*
X *	Noise and Dnoise routines
X *
X *	Many thanks to Jon Buller of Colorado State University for these
X *	routines.
X */
X
X
#define NUMPTS	512
#define P1	173
#define P2	263
#define P3	337
#define phi	0.6180339
X
X
bool noise_ready = FALSE;
X
static double pts[NUMPTS];
X
X
/*
X * Doubles might have values that is too large to be
X * stored in an int. If this is the case we "fold" the
X * value about MAXINT or MININT until it is of an
X * acceptable size.
X *
X * NOTE: 32 bit integers is assumed.
X */
static double
iadjust(f)
X    double f;
{
X    while ((f > 2147483647.0) || (f < -2147483648.0)) {
X        if (f > 2147483647.0) {         /* 2**31 - 1 */
X            f = (4294967294.0 - f);     /* 2**32 - 2 */
X        } else if (f < -2147483648.0){
X            f = (-4294967296.0 - f);
X        }
X    }
X    return f;
}
X
X
X
/*
X * Initialize the array of random numbers.
X * RANDOM() is defined in sipp.h
X */
void noise_init()
{
X    int i;
X   
X    for (i = 0; i < NUMPTS; ++i)
X        pts[i] = RANDOM();
X    noise_ready = TRUE;
}
X
X
X
double noise(v)
Vector *v;
{
X   Vector p;
X   int xi, yi, zi;
X   int xa, xb, xc, ya, yb, yc, za, zb, zc;
X   double xf, yf, zf;
X   double x2, x1, x0, y2, y1, y0, z2, z1, z0;
X   double p000, p100, p200, p010, p110, p210, p020, p120, p220;
X   double p001, p101, p201, p011, p111, p211, p021, p121, p221;
X   double p002, p102, p202, p012, p112, p212, p022, p122, p222;
X   double tmp;
X
X   p = *v;
X
X   p.x = iadjust(p.x);
X   p.y = iadjust(p.y);
X   p.z = iadjust(p.z);
X   xi = floor(p.x);
X   xa = floor(P1 * (xi * phi - floor(xi * phi)));
X   xb = floor(P1 * ((xi + 1) * phi - floor((xi + 1) * phi)));
X   xc = floor(P1 * ((xi + 2) * phi - floor((xi + 2) * phi)));
X
X   yi = floor(p.y);
X   ya = floor(P2 * (yi * phi - floor(yi * phi)));
X   yb = floor(P2 * ((yi + 1) * phi - floor((yi + 1) * phi)));
X   yc = floor(P2 * ((yi + 2) * phi - floor((yi + 2) * phi)));
X
X   zi = floor(p.z);
X   za = floor(P3 * (zi * phi - floor(zi * phi)));
X   zb = floor(P3 * ((zi + 1) * phi - floor((zi + 1) * phi)));
X   zc = floor(P3 * ((zi + 2) * phi - floor((zi + 2) * phi)));
X
X   p000 = pts[(xa + ya + za) % NUMPTS];
X   p100 = pts[(xb + ya + za) % NUMPTS];
X   p200 = pts[(xc + ya + za) % NUMPTS];
X   p010 = pts[(xa + yb + za) % NUMPTS];
X   p110 = pts[(xb + yb + za) % NUMPTS];
X   p210 = pts[(xc + yb + za) % NUMPTS];
X   p020 = pts[(xa + yc + za) % NUMPTS];
X   p120 = pts[(xb + yc + za) % NUMPTS];
X   p220 = pts[(xc + yc + za) % NUMPTS];
X   p001 = pts[(xa + ya + zb) % NUMPTS];
X   p101 = pts[(xb + ya + zb) % NUMPTS];
X   p201 = pts[(xc + ya + zb) % NUMPTS];
X   p011 = pts[(xa + yb + zb) % NUMPTS];
X   p111 = pts[(xb + yb + zb) % NUMPTS];
X   p211 = pts[(xc + yb + zb) % NUMPTS];
X   p021 = pts[(xa + yc + zb) % NUMPTS];
X   p121 = pts[(xb + yc + zb) % NUMPTS];
X   p221 = pts[(xc + yc + zb) % NUMPTS];
X   p002 = pts[(xa + ya + zc) % NUMPTS];
X   p102 = pts[(xb + ya + zc) % NUMPTS];
X   p202 = pts[(xc + ya + zc) % NUMPTS];
X   p012 = pts[(xa + yb + zc) % NUMPTS];
X   p112 = pts[(xb + yb + zc) % NUMPTS];
X   p212 = pts[(xc + yb + zc) % NUMPTS];
X   p022 = pts[(xa + yc + zc) % NUMPTS];
X   p122 = pts[(xb + yc + zc) % NUMPTS];
X   p222 = pts[(xc + yc + zc) % NUMPTS];
X
X   xf = p.x - xi;
X   x1 = xf * xf;
X   x2 = 0.5 * x1;
X   x1 = 0.5 + xf - x1;
X   x0 = 0.5 - xf + x2;
X
X   yf = p.y - yi;
X   y1 = yf * yf;
X   y2 = 0.5 * y1;
X   y1 = 0.5 + yf - y1;
X   y0 = 0.5 - yf + y2;
X
X   zf = p.z - zi;
X   z1 = zf * zf;
X   z2 = 0.5 * z1;
X   z1 = 0.5 + zf - z1;
X   z0 = 0.5 - zf + z2;
X
X   /*
X    * This expression is split up since some compilers
X    * chokes on expressions of this size.
X    */
X   tmp =  z0 * (y0 * (x0 * p000 + x1 * p100 + x2 * p200) +
X                y1 * (x0 * p010 + x1 * p110 + x2 * p210) +
X                y2 * (x0 * p020 + x1 * p120 + x2 * p220));
X   tmp += z1 * (y0 * (x0 * p001 + x1 * p101 + x2 * p201) +
X                y1 * (x0 * p011 + x1 * p111 + x2 * p211) +
X                y2 * (x0 * p021 + x1 * p121 + x2 * p221));
X   tmp += z2 * (y0 * (x0 * p002 + x1 * p102 + x2 * p202) +
X                y1 * (x0 * p012 + x1 * p112 + x2 * p212) +
X                y2 * (x0 * p022 + x1 * p122 + x2 * p222));
X
X   return tmp;
}
X
X
X
double turbulence(p, octaves)
X    Vector *p;
X    int     octaves;
{
X    Vector tmp;
X    double scale = 1.0;
X    double t     = 0.0;
X
X    while (octaves--) {
X        tmp.x = p->x * scale;
X        tmp.y = p->y * scale;
X        tmp.z = p->z * scale;
X        t += (noise(&tmp) / scale);
X        scale *= 2.0;
X    }
X    return t;
}
X
X
X
Vector Dnoise(p)
Vector *p;
{
X   Vector v;
X   int xi, yi, zi;
X   int xa, xb, xc, ya, yb, yc, za, zb, zc;
X   double xf, yf, zf;
X   double x2, x1, x0, y2, y1, y0, z2, z1, z0;
X   double xd2, xd1, xd0, yd2, yd1, yd0, zd2, zd1, zd0;
X   double p000, p100, p200, p010, p110, p210, p020, p120, p220;
X   double p001, p101, p201, p011, p111, p211, p021, p121, p221;
X   double p002, p102, p202, p012, p112, p212, p022, p122, p222;
X
X   xi = floor(p->x);
X   xa = floor(P1 * (xi * phi - floor(xi * phi)));
X   xb = floor(P1 * ((xi + 1) * phi - floor((xi + 1) * phi)));
X   xc = floor(P1 * ((xi + 2) * phi - floor((xi + 2) * phi)));
X
X   yi = floor(p->y);
X   ya = floor(P2 * (yi * phi - floor(yi * phi)));
X   yb = floor(P2 * ((yi + 1) * phi - floor((yi + 1) * phi)));
X   yc = floor(P2 * ((yi + 2) * phi - floor((yi + 2) * phi)));
X
X   zi = floor(p->z);
X   za = floor(P3 * (zi * phi - floor(zi * phi)));
X   zb = floor(P3 * ((zi + 1) * phi - floor((zi + 1) * phi)));
X   zc = floor(P3 * ((zi + 2) * phi - floor((zi + 2) * phi)));
X
X   p000 = pts[(xa + ya + za) % NUMPTS];
X   p100 = pts[(xb + ya + za) % NUMPTS];
X   p200 = pts[(xc + ya + za) % NUMPTS];
X   p010 = pts[(xa + yb + za) % NUMPTS];
X   p110 = pts[(xb + yb + za) % NUMPTS];
X   p210 = pts[(xc + yb + za) % NUMPTS];
X   p020 = pts[(xa + yc + za) % NUMPTS];
X   p120 = pts[(xb + yc + za) % NUMPTS];
X   p220 = pts[(xc + yc + za) % NUMPTS];
X   p001 = pts[(xa + ya + zb) % NUMPTS];
X   p101 = pts[(xb + ya + zb) % NUMPTS];
X   p201 = pts[(xc + ya + zb) % NUMPTS];
X   p011 = pts[(xa + yb + zb) % NUMPTS];
X   p111 = pts[(xb + yb + zb) % NUMPTS];
X   p211 = pts[(xc + yb + zb) % NUMPTS];
X   p021 = pts[(xa + yc + zb) % NUMPTS];
X   p121 = pts[(xb + yc + zb) % NUMPTS];
X   p221 = pts[(xc + yc + zb) % NUMPTS];
X   p002 = pts[(xa + ya + zc) % NUMPTS];
X   p102 = pts[(xb + ya + zc) % NUMPTS];
X   p202 = pts[(xc + ya + zc) % NUMPTS];
X   p012 = pts[(xa + yb + zc) % NUMPTS];
X   p112 = pts[(xb + yb + zc) % NUMPTS];
X   p212 = pts[(xc + yb + zc) % NUMPTS];
X   p022 = pts[(xa + yc + zc) % NUMPTS];
X   p122 = pts[(xb + yc + zc) % NUMPTS];
X   p222 = pts[(xc + yc + zc) % NUMPTS];
X
X   xf = p->x - xi;
X   x1 = xf * xf;
X   x2 = 0.5 * x1;
X   x1 = 0.5 + xf - x1;
X   x0 = 0.5 - xf + x2;
X   xd2 = xf;
X   xd1 = 1.0 - xf - xf;
X   xd0 = xf - 1.0;
X
X   yf = p->y - yi;
X   y1 = yf * yf;
X   y2 = 0.5 * y1;
X   y1 = 0.5 + yf - y1;
X   y0 = 0.5 - yf + y2;
X   yd2 = yf;
X   yd1 = 1.0 - yf - yf;
X   yd0 = yf - 1.0;
X
X   zf = p->z - zi;
X   z1 = zf * zf;
X   z2 = 0.5 * z1;
X   z1 = 0.5 + zf - z1;
X   z0 = 0.5 - zf + z2;
X   zd2 = zf;
X   zd1 = 1.0 - zf - zf;
X   zd0 = zf - 1.0;
X
X   /*
X    * This expressions are split up since some compilers
X    * chokes on expressions of this size.
X    */
X   v.x        = z0 * (y0 * (xd0 * p000 + xd1 * p100 + xd2 * p200) +
X                      y1 * (xd0 * p010 + xd1 * p110 + xd2 * p210) +
X                      y2 * (xd0 * p020 + xd1 * p120 + xd2 * p220));
X   v.x       += z1 * (y0 * (xd0 * p001 + xd1 * p101 + xd2 * p201) +
X                      y1 * (xd0 * p011 + xd1 * p111 + xd2 * p211) +
X                      y2 * (xd0 * p021 + xd1 * p121 + xd2 * p221));
X   v.x       += z2 * (y0 * (xd0 * p002 + xd1 * p102 + xd2 * p202) +
X                      y1 * (xd0 * p012 + xd1 * p112 + xd2 * p212) +
X                      y2 * (xd0 * p022 + xd1 * p122 + xd2 * p222));
X                                  
X   v.y        = z0 * (yd0 * (x0 * p000 + x1 * p100 + x2 * p200) +
X                      yd1 * (x0 * p010 + x1 * p110 + x2 * p210) +
X                      yd2 * (x0 * p020 + x1 * p120 + x2 * p220));
X   v.y       += z1 * (yd0 * (x0 * p001 + x1 * p101 + x2 * p201) +
X                      yd1 * (x0 * p011 + x1 * p111 + x2 * p211) +
X                      yd2 * (x0 * p021 + x1 * p121 + x2 * p221));
X   v.y       += z2 * (yd0 * (x0 * p002 + x1 * p102 + x2 * p202) +
X                      yd1 * (x0 * p012 + x1 * p112 + x2 * p212) +
X                      yd2 * (x0 * p022 + x1 * p122 + x2 * p222));
X                                  
X   v.z        = zd0 * (y0 * (x0 * p000 + x1 * p100 + x2 * p200) +
X                       y1 * (x0 * p010 + x1 * p110 + x2 * p210) +
X                       y2 * (x0 * p020 + x1 * p120 + x2 * p220));
X   v.z       += zd1 * (y0 * (x0 * p001 + x1 * p101 + x2 * p201) +
X                       y1 * (x0 * p011 + x1 * p111 + x2 * p211) +
X                       y2 * (x0 * p021 + x1 * p121 + x2 * p221));
X   v.z       += zd2 * (y0 * (x0 * p002 + x1 * p102 + x2 * p202) +
X                       y1 * (x0 * p012 + x1 * p112 + x2 * p212) +
X                       y2 * (x0 * p022 + x1 * p122 + x2 * p222));
X
X   return v;
}
X
X
X
/*
X * End of noise routines
X */
SHAR_EOF
chmod 0664 libsipp/noise.c ||
echo 'restore of libsipp/noise.c failed'
Wc_c="`wc -c < 'libsipp/noise.c'`"
test 9232 -eq "$Wc_c" ||
	echo 'libsipp/noise.c: original size 9232, current size' "$Wc_c"
fi
# ============= libsipp/noise.h ==============
if test -f 'libsipp/noise.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/noise.h (File already exists)'
else
echo 'x - extracting libsipp/noise.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/noise.h' &&
/*
X * Declarations needed to use noise() and friends...
X */
X
#ifndef _NOISE_H 
#define _NOISE_H 
X
#include <geometric.h>
X
extern void     noise_init();
extern double   noise();
extern double   turbulence();
extern Vector   Dnoise();
X
X
#endif /* _NOISE_H */
SHAR_EOF
chmod 0664 libsipp/noise.h ||
echo 'restore of libsipp/noise.h failed'
Wc_c="`wc -c < 'libsipp/noise.h'`"
test 257 -eq "$Wc_c" ||
	echo 'libsipp/noise.h: original size 257, current size' "$Wc_c"
fi
# ============= libsipp/objects.c ==============
if test -f 'libsipp/objects.c' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/objects.c (File already exists)'
else
echo 'x - extracting libsipp/objects.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/objects.c' &&
/**
X ** sipp - SImple Polygon Processor
X **
X **  A general 3d graphic package
X **
X **  Copyright Jonas Yngvesson  (jonas-y@isy.liu.se) 1988/89/90/91
X **            Inge Wallin      (ingwa@isy.liu.se)         1990/91
X **
X ** This program is free software; you can redistribute it and/or modify
X ** it under the terms of the GNU General Public License as published by
X ** the Free Software Foundation; either version 1, or any later version.
X ** This program is distributed in the hope that it will be useful,
X ** but WITHOUT ANY WARRANTY; without even the implied warranty of
X ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X ** GNU General Public License for more details.
X ** You can receive a copy of the GNU General Public License from the
X ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X **/
X
/**
X ** objects.c - Functions that handles object and surface creation
X **             and the object hierarchies and the object database.
X **/
X
#include <stdio.h>
X
#include <objects.h>
#include <sipp.h>
#include <smalloc.h>
X
X
static Vertex       *vertex_tree;     /* Vertex tree for current object. */
static Vertex_ref   *vertex_stack;    /* Vertex stack for current polygon. */
static Vertex_ref   *vstack_bottom;   /* Last entry in vertex stack. */
static Polygon      *poly_stack;      /* Polygon stack for current object. */
static int           first_vertex;    /* Used when determining if we are   */
X                                      /* installing the first vertex in an */
X                                      /* object. *Not* a boolean!          */
static double        dist_limit;      /* Minimal distance between two      */
X                                      /* vertices without them being       */
X                                      /* considered to be the same vertex. */
X
Inst_object         *object_db;       /* Object database. */
X
X
X
/*
X * Search for a vertex in a vertex tree. Vertices are asumed
X * to be equal if they differ less than dist_limit in all directions.
X *
X * If the vertex is not found, install it in the tree.
X */
static Vertex *
vertex_lookup(x, y, z, u, v, w, p)
X    double   x, y, z, u, v, w;
X    Vertex **p;
{
X    double  xdist, ydist, zdist;
X
X    if (*p == NULL) {
X        *p = (Vertex *)smalloc(sizeof(Vertex));
X        (*p)->x = x;
X        (*p)->y = y;
X        (*p)->z = z;
X        (*p)->a = 0;
X        (*p)->b = 0;
X        (*p)->c = 0;
X        (*p)->u = u;
X        (*p)->v = v;
X        (*p)->w = w;
X        (*p)->big = NULL;
X        (*p)->sml = NULL;
X        return *p;
X    } else if ((xdist = x - ((*p)->x)) > dist_limit) {
X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->big)));
X    } else if (xdist < -dist_limit) {
X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->sml)));
X    } else if ((ydist = y - ((*p)->y)) > dist_limit) {
X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->big)));
X    } else if (ydist < -dist_limit) {
X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->sml)));
X    } else if ((zdist = z - ((*p)->z)) > dist_limit) {
X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->big)));
X    } else if (zdist < -dist_limit) {
X        return (vertex_lookup(x, y, z, u, v, w, &((*p)->sml)));
X    } else {
X        return *p;
X    }
}
X
X
X
/*
X * Push a vertex on the vertex stack (without texture coordinates).
X */
void
vertex_push(x, y, z)
X    double  x, y, z;
{
X    vertex_tx_push(x, y, z, (double)0.0, (double)0.0, (double)0.0);
}
X
X
X
/*
X * Push a vertex on the vertex stack (with texture coordinates).
X */
void
vertex_tx_push(x, y, z, u, v, w)
X    double  x, y, z, u, v, w;
{
X    Vertex_ref *vref;
X
X   /* 
X    * To get a reasonable dist_limit we use the following "heuristic" 
X    * value:
X    * The distance between the first two vertices installed in
X    * the surface, multiplied by the magic number 1e-10, unless
X    * they are the same vertex. In that case 1e-10 is used until
X    * we get a vertex that differs from the first.
X    */
X    if (!first_vertex)
X        first_vertex++;
X    else if (first_vertex == 1) {
X        dist_limit = sqrt((x - vertex_tree->x) * (x - vertex_tree->x)
X                        + (y - vertex_tree->y) * (y - vertex_tree->y)
X                        + (z - vertex_tree->z) * (z - vertex_tree->z))
X                   * 1e-10;                      /* Magic!!! */
X        if (dist_limit != 0.0)
X            first_vertex++;
X        else
X            dist_limit = 1e-10;                  /* More Magic */
X    }
X    vref = (Vertex_ref *)smalloc(sizeof(Vertex_ref));
X    if (vertex_stack == NULL) {
X        vertex_stack = vref;
X    } else {
X        vstack_bottom->next = vref;
X    }
X    vstack_bottom = vref;
X    vref->vertex = vertex_lookup(x, y, z, u, v, w, &vertex_tree);
X    vref->next = NULL;
}
X
X
X
/*
X * Push a polygon on the polygon stack. Empty the vertex stack afterwards.
X */
void
polygon_push()
{
X    Polygon *polyref;
X
X    if (vertex_stack != NULL) {
X        polyref = (Polygon *)smalloc(sizeof(Polygon));
X        polyref->vertices = vertex_stack;
X        polyref->backface = 0;
X        polyref->next = poly_stack;
X        poly_stack = polyref;
X        vertex_stack = NULL;
X    }
}
X
X
X
/*
X * Create a surface of all polygons in the polygon stack.
X * Empty the polygon stack afterwards.
X */
Surface *
surface_create(surf_desc, shader)
X    void   *surf_desc;
X    Shader *shader;
{
X    Surface *surfref;
X    
X    if (poly_stack != NULL) {
X        surfref = (Surface *)smalloc(sizeof(Surface));
X        surfref->vertices = vertex_tree;
X        surfref->polygons = poly_stack;
X        surfref->surface = surf_desc;
X        surfref->shader = shader;
X        surfref->ref_count = 0;
X        surfref->next = NULL;
X        vertex_tree = NULL;
X        poly_stack = NULL;
X        first_vertex = 0;
X        return surfref;
X    } else
X        return NULL;
}
X
X
X
/*
X * Create a surface to be shaded with the simple shader.
X */
Surface *
surface_basic_create(ambient, red, grn, blu, specular, c3)
X    double ambient, red, grn, blu, specular, c3;
{
X    Surf_desc *surf_desc;
X
X    surf_desc = (Surf_desc *)smalloc(sizeof(Surf_desc));
X    surf_desc->ambient = ambient;
X    surf_desc->color.red = red;
X    surf_desc->color.grn = grn;
X    surf_desc->color.blu = blu;
X    surf_desc->specular = specular;
X    surf_desc->c3 = c3;
X    return surface_create(surf_desc, basic_shader);
}
X
X
X
/*
X * Set SURFACE to be shaded with the shading function SHADER
X * using the surface description SURF_DESC.
X */
void
surface_set_shader(surface, surf_desc, shader)
X    Surface *surface;
X    void    *surf_desc;
X    Shader  *shader;
{
X    
X    if (surface != NULL) {
X        surface->surface = surf_desc;
X        surface->shader = shader;
X    }
}
X
X
X
/*
X * Set SURFACE to be shaded with the simple shader.
X */
void
surface_basic_shader(surface, ambient, red, grn, blu, specular, c3)
X    Surface *surface;
X    double  ambient, red, grn, blu, specular, c3;
{
X    Surf_desc *surf_desc;
X
X    surf_desc = (Surf_desc *)smalloc(sizeof(Surf_desc));
X    surf_desc->ambient = ambient;
X    surf_desc->color.red = red;
X    surf_desc->color.grn = grn;
X    surf_desc->color.blu = blu;
X    surf_desc->specular = specular;
X    surf_desc->c3 = c3;
X    surface_set_shader(surface, surf_desc, basic_shader);
}
X
X
X
/*
X * Copy a vertex tree.
X */
static Vertex *
copy_vertices(vp)
X    Vertex *vp;
{
X    Vertex *tmp;
X
X    if (vp == NULL)
X        return NULL;
X    tmp = (Vertex *)smalloc(sizeof(Vertex));
X    *tmp = *vp;
X    tmp->big = copy_vertices(vp->big);
X    tmp->sml = copy_vertices(vp->sml);
X    return tmp;
}
X
X
X
/*
X * We have a list of vertes references, each pointing into a certain
X * vertex tree. Create a new list with pointers into a copy of the
X * first vertex tree.
X */
static Vertex_ref *
copy_vlist(vp, surface)
X    Vertex_ref *vp;
X    Surface    *surface;
{
X    Vertex_ref *tmp;
X    
X    if (vp == NULL)
X        return NULL;
X    tmp = (Vertex_ref *)smalloc(sizeof(Vertex_ref));
X    tmp->vertex = vertex_lookup(vp->vertex->x, vp->vertex->y, vp->vertex->z,
X                                vp->vertex->u, vp->vertex->v, vp->vertex->w,
X                                &(surface->vertices));
X    tmp->next = copy_vlist(vp->next, surface);
X    return tmp;
}
X
X
X
/*
X * Copy a list of polygons.
X */
static Polygon *
copy_polygons(pp, surface)
X    Polygon *pp;
X    Surface *surface;
{
X    Polygon *tmp;
X
X    if (pp == NULL)
X        return NULL;
X    tmp = (Polygon *)smalloc(sizeof(Polygon));
X    tmp->vertices = copy_vlist(pp->vertices, surface);
X    tmp->next = copy_polygons(pp->next, surface);
X    return tmp;
}
X
X
X
/*
X * Copy a list of surfaces. All polygons and vertices are copied but
X * the shader and surface descriptions are the same as in the
X * original surfaces.
X */
static Surface *
surface_copy(surface)
X    Surface  *surface;
{
X    Surface  *newsurf;
X
X    if (surface != NULL) {
X        newsurf = (Surface *)smalloc(sizeof(Surface));
X        if (newsurf == NULL) {
X            return NULL;
X        }
X        memcpy(newsurf, surface, sizeof(Surface));
X        newsurf->vertices = copy_vertices(surface->vertices);
X        newsurf->polygons = copy_polygons(surface->polygons, newsurf);
X        newsurf->ref_count = 1;
X        newsurf->next = surface_copy(surface->next);
X        return newsurf;
X    } else {
X        return NULL;
X    }
}
X
X
X
/*
X * Delete a vertex tree.
X */
static void
delete_vertices(vtree)
X    Vertex **vtree;
{
X    if (*vtree != NULL) {
X        delete_vertices(&((*vtree)->big));
X        delete_vertices(&((*vtree)->sml));
X        free(*vtree);
X        *vtree = NULL;
X    }
}
X
X
X
/*
X * Delete a surface list.
X */
static void
surface_delete(surface)
X    Surface *surface;
{
X    Vertex_ref *vref1, *vref2;
X    Polygon    *polyref1, *polyref2;
X
X    if (surface != NULL) {
X        if (--surface->ref_count == 0) {
X            if (surface->next != NULL) {
X                surface_delete(surface->next);
X            }
X            polyref2 = surface->polygons;
X            while (polyref2 != NULL) {
X                vref2 = polyref2->vertices;
X                while (vref2 != NULL) {
X                    vref1 = vref2;
X                    vref2 = vref2->next;
X                    free(vref1);
X                }
X                polyref1 = polyref2;
X                polyref2 = polyref2->next;
X                free(polyref1);
X            }
X            delete_vertices(&(surface->vertices));
X            free(surface);
X        }
X    }
}
X
X
X
/*
X * Install an object in the rendering database.
X */
static void
r_object_install(obj, obj_tree)
X    Object       *obj;
X    Inst_object **obj_tree;
{
X    if (obj != NULL) {
X        if (*obj_tree == NULL) {
X            obj->ref_count++;
X            *obj_tree = (Inst_object *)smalloc(sizeof(Inst_object));
X            (*obj_tree)->object = obj;
X            (*obj_tree)->big = NULL;
X            (*obj_tree)->sml = NULL;
X        } else if (obj > (*obj_tree)->object) {
X            r_object_install(obj, &(*obj_tree)->big);
X        } else if (obj < (*obj_tree)->object) {
X            r_object_install(obj, &(*obj_tree)->sml);
X        }
X    }
}
X
X
X
/*
X * Interface to r_object_install(). (Why are there no
X * subfunctions in C?...)
X */
void
object_install(obj)
X    Object *obj;
{
X    r_object_install(obj, &object_db);
}
X
X
X
/*
X * Subfunction to r_object_uninstall.
X */
static void
r_del(r, q)
X    Inst_object **r;
X    Inst_object  *q;
{
X    if ((*r)->big != NULL) {
X        r_del(&((*r)->big), q);
X    } else {
X        q->object = (*r)->object;
X        q = *r;
X        *r = (*r)->sml;
X        free(q);
X    }
}
X
X
X
/*
X * Delete an object from the rendering database.
X * The object itself is not deleted of course.
X */
static void
r_object_uninstall(obj, root)
X    Object       *obj;
X    Inst_object **root;
{
X    Inst_object *ptr;
X
X    if (*root == NULL) {
X        return;            /* Object is not in the tree */
X    } else if (obj < (*root)->object) {
X        r_object_uninstall(obj, &(*root)->sml);
X    } else if (obj > (*root)->object) {
X        r_object_uninstall(obj, &(*root)->big);
X    } else {
X        obj->ref_count--;
X        ptr = *root;
X        if (ptr->big == NULL) {
X            *root = ptr->sml;
X        } else if (ptr->sml == NULL) {
X            *root = ptr->big;
X        } else {
X            r_del(&ptr->sml, ptr);
X        }
X    }
}
X
X    
X    
/*
X * Interface to r_object_uninstall.
X */
void
object_uninstall(obj)
X    Object *obj;
{
X    r_object_uninstall(obj, &object_db);
}
X
X
X
/*
X * Create an empty object. Before it is rendered it
X * must get a surface or a subobject. 
X */
Object *
object_create()
{
X    Object *obj;
X
X    obj = (Object *)smalloc(sizeof(Object));
X    obj->surfaces = NULL;
X    obj->sub_obj = NULL;
X    MatCopy(&obj->transf, &ident_matrix);
X    obj->ref_count = 0;
X    obj->next = NULL;
X
X    return obj;
}
X
X
X
/*
X * Copy the top object in an object hierarchy.
X * The new object will reference the same
X * subobjects and surfaces as the original object.
X * if REF_COUNT_UPDATE is true, the reference counts
X * in the surfaces and subobjects will be incremented.
X */
static Object *
object_copy(object, ref_count_update)
X    Object *object;
X    bool    ref_count_update;
{
X    Object *newobj;
X
X    if (object == NULL) {
X        return NULL;
X    }
X
X    if ((newobj = (Object *)smalloc(sizeof(Object))) != NULL) {
X        memcpy(newobj, object, sizeof(Object));
X        if (ref_count_update) {
X            if (newobj->sub_obj != NULL) {
X                newobj->sub_obj->ref_count++;
X            }
X            if (newobj->surfaces != NULL) {
X                newobj->surfaces->ref_count++;
X            }
X        }
X        MatCopy(&newobj->transf, &ident_matrix);
X        newobj->ref_count = 0;
X        newobj->next = NULL;
X    }
X
X    return newobj;
}
X
X
X
/*
X * Copy a list of objects. If SURF_COPY is true
X * the surfaces in the objects will be copied too.
X */
static Object *
object_list_copy(object, surf_copy)
X    Object *object;
X    bool    surf_copy;
{
X    Object *newobj;
X
X    if (object == NULL) {
X        return NULL;
X    }
X
X    if ((newobj = (Object *)smalloc(sizeof(Object))) != NULL) {
X        memcpy(newobj, object, sizeof(Object));
X        newobj->ref_count = 0;
X    } else {
X        return NULL;
X    }
X
X    if (surf_copy) {
X        newobj->surfaces = surface_copy(object->surfaces);
X    } else if (newobj->surfaces != NULL){
X        newobj->surfaces->ref_count++;
X    }
X
X    newobj->sub_obj = object_list_copy(object->sub_obj, surf_copy);
X    if (newobj->sub_obj != NULL) {
X        newobj->sub_obj->ref_count++;
X    }
X    newobj->next = object_list_copy(object->next, surf_copy);
X    if (newobj->next != NULL) {
X        newobj->next->ref_count++;
X    }
X
X    return newobj;
}
X    
X
X
/*
X * Copy the top node of an object hierarchy. The
X * subobjects and surface references will be the
X * same as in the original.
X */
Object *
object_instance(obj)
X    Object *obj;
{
X    return object_copy(obj, TRUE);
}
X
X
X
/*
X * Copy an object hierarchy. The objects in
X * the new hierarchy will reference the same
X * surfaces as the object in
X * the old hierarchy, but all object nodes
X * will be duplicated.
X */
Object *
object_dup(object)
X    Object *object;
{
X    Object *newobj;
X
X    if ((newobj = object_copy(object, FALSE)) == NULL) {
X        return NULL;
X    }
X
X    newobj->sub_obj = object_list_copy(object->sub_obj, FALSE);
X    newobj->next = NULL;
X
X    return newobj;
}
X 
X
X
/*
X * Copy an object hierarchy. All object nodes
X * and surfaces in the old hierarchy
X * will be duplicated.
X */
Object *
object_deep_dup(object)
X    Object *object;
{
X    Object *newobj;
X
X    if ((newobj = object_copy(object, FALSE)) == NULL) {
X        return NULL;
X    }
X
X    newobj->surfaces = surface_copy(object->surfaces);
X    newobj->sub_obj = object_list_copy(object->sub_obj, TRUE);
X    newobj->next = NULL;
X
X    return newobj;
}
X
X
X
/*
X * Recursively delete an object hierarchy. Reference
X * counts are decremented and if the result is zero
X * the recursion continues and the memory used is freed.
X */
static void
r_object_delete(object)
X    Object * object;
{
X    if (object != NULL) {
X        if (--object->ref_count == 0) {
X            surface_delete(object->surfaces);
X            r_object_delete(object->sub_obj);
X            r_object_delete(object->next);
X            free(object);
X        }
X    }
}
X
X
X
/*
X * Delete an object hierarchy. This is only possible
X * to do on a top level object.
X */
void
object_delete(object)
X    Object * object;
{
X    if (object != NULL) {
X        if (object->ref_count == 0) {         /* Is it a top level object? */
X            surface_delete(object->surfaces);
X            r_object_delete(object->sub_obj);
X            r_object_delete(object->next);
X            free(object);
X        }
X    }
}
X
X
X
/*
X * Remove SUBOBJ as a subobject in OBJECT. SUBOBJ is only
X * removed from the list of subojects in OBJECT. If the
X * memory is uses should be freed, object_delete() must
X * be used.
X */
void
object_sub_subobj(object, subobj)
X    Object *object, *subobj;
{
X    Object *oref1;
X    Object *oref2;
X
X    if (object == NULL || subobj == NULL || object->sub_obj == NULL) {
X        return;
X    }
X
X    if (object->sub_obj == subobj) {
X        object->sub_obj = subobj->next;
X    } else {
X        oref1 = object->sub_obj;
X        oref2 = oref1->next;
X        while (oref2 != NULL && oref2 != subobj) {
X            oref1 = oref2;
X            oref2 = oref2->next;
X        }
X        if (oref2 == subobj) {
X            oref1->next = oref2->next;
X        }
X    }
X
X    subobj->ref_count--;
}
X
X
X
/*
X * Add SUBOBJ as a subobject in OBJECT. SUBOBJ is appended
X * on the *end* of OBJECT's subobject list, 
X * so that if SUBOBJ, for some obscure reason, 
X * were the head of an object list, we don't loose
X * the rest of that list. 
X * Remove SUBOBJ from the rendering database since it is no
X * longer a root object in an hierarchy.
X */
void
object_add_subobj(object, subobj)
X    Object *object, *subobj;
{
X    Object *oref;
X
X    if (object == NULL || subobj == NULL) {
X        return;
X    }
X
X    if (object->sub_obj == NULL) {
X        object->sub_obj = subobj;
X    } else {
X        oref = object->sub_obj;
X        while (oref->next != NULL) {
X            oref = oref->next;
X        }
X        oref->next = subobj;
X    }
X
X    subobj->ref_count++;
X    object_uninstall(subobj);
}
X
X
X
/*
X * Remove SURFACE as a surface in OBJECT.
X */
void
object_sub_surface(object, surface)
X    Object   *object;
X    Surface  *surface;
{
X    Surface *sref1;
X    Surface *sref2;
X
X    if (object == NULL || surface == NULL || object->surfaces == NULL) {
X        return;
X    }
X
X    if (object->surfaces == surface) {
X        object->surfaces = surface->next;
X    } else {
X        sref1 = object->surfaces;
X        sref2 = sref1->next;
X        while (sref2 != NULL && sref2 != surface) {
X            sref1 = sref2;
X            sref2 = sref2->next;
X        }
X        if (sref2 == surface) {
X            sref1->next = sref2->next;
X        }
X    }
X
X    surface->ref_count--;
}
X
X
X
/*
X * Add SURFACE to the list of surfaces belonging
X * to OBJECT. SURFACE is appended on the *end* of the
X * list for the same reasons as in object_add_subobj.
X */
void
object_add_surface(object, surface)
X    Object  *object;
X    Surface *surface;
{
X    Surface *sref;
X
X    if (object == NULL || surface == NULL) {
X        return;
X    }
X
X    if (object->surfaces == NULL) {
X        object->surfaces = surface;
X    } else {
X        sref = object->surfaces;
X        while (sref->next != NULL) {
X            sref = sref->next;
X        }
X        sref->next = surface;
X    }
X
X    surface->ref_count++;
}
X    
X    
X    
/*
X * Initialize the data structures.
X */
void
objects_init()
{
X    vertex_tree    = NULL;
X    vertex_stack   = NULL;
X    first_vertex   = 0;
X    poly_stack     = NULL;
X    object_db      = NULL;
}
SHAR_EOF
chmod 0644 libsipp/objects.c ||
echo 'restore of libsipp/objects.c failed'
Wc_c="`wc -c < 'libsipp/objects.c'`"
test 19672 -eq "$Wc_c" ||
	echo 'libsipp/objects.c: original size 19672, current size' "$Wc_c"
fi
# ============= libsipp/objects.h ==============
if test -f 'libsipp/objects.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/objects.h (File already exists)'
else
echo 'x - extracting libsipp/objects.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/objects.h' &&
/**
X ** sipp - SImple Polygon Processor
X **
X **  A general 3d graphic package
X **
X **  Copyright Jonas Yngvesson  (jonas-y@isy.liu.se) 1988/89/90/91
X **            Inge Wallin      (ingwa@isy.liu.se)         1990/91
X **
X ** This program is free software; you can redistribute it and/or modify
X ** it under the terms of the GNU General Public License as published by
X ** the Free Software Foundation; either version 1, or any later version.
X ** This program is distributed in the hope that it will be useful,
X ** but WITHOUT ANY WARRANTY; without even the implied warranty of
X ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X ** GNU General Public License for more details.
X ** You can receive a copy of the GNU General Public License from the
X ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X **/
X
/**
X ** objects.h - Types and interface to objects.c
X **/
X
#ifndef OBJECT_H
#define OBJECT_H
X
#include <sipp.h>
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
extern Inst_object         *object_db;       /* Object database. */
X
X
extern void   objects_init();
X
X
#endif /* OBJECT_H */
SHAR_EOF
chmod 0644 libsipp/objects.h ||
echo 'restore of libsipp/objects.h failed'
Wc_c="`wc -c < 'libsipp/objects.h'`"
test 1430 -eq "$Wc_c" ||
	echo 'libsipp/objects.h: original size 1430, current size' "$Wc_c"
fi
# ============= libsipp/patchlevel.h ==============
if test -f 'libsipp/patchlevel.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/patchlevel.h (File already exists)'
else
echo 'x - extracting libsipp/patchlevel.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/patchlevel.h' &&
#define PATCHLEVEL ""
SHAR_EOF
chmod 0664 libsipp/patchlevel.h ||
echo 'restore of libsipp/patchlevel.h failed'
Wc_c="`wc -c < 'libsipp/patchlevel.h'`"
test 22 -eq "$Wc_c" ||
	echo 'libsipp/patchlevel.h: original size 22, current size' "$Wc_c"
fi
# ============= libsipp/planet.c ==============
if test -f 'libsipp/planet.c' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/planet.c (File already exists)'
else
echo 'x - extracting libsipp/planet.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/planet.c' &&
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
#include <geometric.h>
#include <noise.h>
X
X
/* A reasonably nice brown color */
static Color  land = {0.28125, 0.1875, 0.09375};
X
/* Oceans are usually blue */
static Color  sea = {0.0, 0.0, 1.0};
X
/* And Clouds are white */
static Color  cloud = {1.0, 1.0, 1.0};
X
X
/* 
X * This was designed to work with a unit sphere.  
X * 
X * Thanks to Jon Buller       jonb@vector.dallas.tx.us
X */
double
turb(size, scale_factor, loc)
X    int size;
X    double scale_factor;
X    Vector loc;
{
X    double cur_scale, result;
X    int cur;
X
X    result = noise(&loc);
X    cur_scale = 1.0;
X
X    cur = 1;
X    while (cur < size) {
X        cur <<= 1;
X        cur_scale = cur_scale * scale_factor;
X        loc.x *= 2.0;
X        loc.y *= 2.0;
X        loc.z *= 2.0;
X        result += noise(&loc) * cur_scale;
X    }
X    return result;
}
X
X
X
extern bool noise_ready;
X
void
planet_shader(nx, ny, nz, u, v, w, view_vec, lights, sd, color)
X    double        nx, ny, nz, u, v, w;
X    Vector        view_vec;
X    Lightsource  *lights;
X    Surf_desc    *sd;
X    Color        *color;
{
X    Vector  tmp;
X    double  amt;
X
X    if (!noise_ready) {
X        noise_init();
X    }
X
X    tmp.x = u;
X    tmp.y = v;
X    tmp.z = w;
X
X    if (turb(430, 0.7, tmp) > 0.15)
X        sd->color = land;
X    else 
X        sd->color = sea;
X
X    VecScalMul(tmp, 12.0, tmp)
X
X    amt = turb(18, 0.6, tmp);
X    if (amt > -0.25) {
X        amt += 0.25;
X        sd->color.red += amt * (cloud.red - sd->color.red);
X        sd->color.grn += amt * (cloud.grn - sd->color.grn);
X        sd->color.blu += amt * (cloud.blu - sd->color.blu);
X    }
X
X    basic_shader(nx, ny, nz, u, v, w, view_vec, lights, sd, color);
}
SHAR_EOF
chmod 0664 libsipp/planet.c ||
echo 'restore of libsipp/planet.c failed'
Wc_c="`wc -c < 'libsipp/planet.c'`"
test 1700 -eq "$Wc_c" ||
	echo 'libsipp/planet.c: original size 1700, current size' "$Wc_c"
fi
# ============= libsipp/primitives.h ==============
if test -f 'libsipp/primitives.h' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/primitives.h (File already exists)'
else
echo 'x - extracting libsipp/primitives.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/primitives.h' &&
/**
X ** sipp - SImple Polygon Processor
X **
X **  A general 3d graphic package
X **
X **  Copyright Jonas Yngvesson  (jonas-y@isy.liu.se) 1988/89/90/91
X **            Inge Wallin      (ingwa@isy.liu.se)         1990/91
X **
X ** This program is free software; you can redistribute it and/or modify
X ** it under the terms of the GNU General Public License as published by
X ** the Free Software Foundation; either version 1, or any later version.
X ** This program is distributed in the hope that it will be useful,
X ** but WITHOUT ANY WARRANTY; without even the implied warranty of
X ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
X ** GNU General Public License for more details.
X ** You can receive a copy of the GNU General Public License from the
X ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X **/
X
/**
X ** primitives.h - Interface to the various primitive object functions.
X **/
X
#ifndef PRIMITIVES_H
#define PRIMITIVES_H
X
X
extern Object *sipp_torus();
extern Object *sipp_cone();
extern Object *sipp_cylinder();
extern Object *sipp_ellipsoid();
extern Object *sipp_sphere();
extern Object *sipp_prism();
extern Object *sipp_block();
extern Object *sipp_cube();
extern Object *sipp_bezier();
X
X
#endif /* PRIMITIVES_H */
SHAR_EOF
chmod 0664 libsipp/primitives.h ||
echo 'restore of libsipp/primitives.h failed'
Wc_c="`wc -c < 'libsipp/primitives.h'`"
test 1264 -eq "$Wc_c" ||
	echo 'libsipp/primitives.h: original size 1264, current size' "$Wc_c"
fi
# ============= libsipp/prism.c ==============
if test -f 'libsipp/prism.c' -a X"$1" != X"-c"; then
	echo 'x - skipping libsipp/prism.c (File already exists)'
else
echo 'x - extracting libsipp/prism.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'libsipp/prism.c' &&
/*
X * File: sipp_prism.c 
X *
X * Create a prism from a polygonal cross-section in XY.
X * The points must be given in counter-clockwise order as viewed from
X * the front (+ve Z).
X *
X * Author:  David Jones
X *          djones@awesome.berkeley.edu
X *          11may91 djones
X *
X * Adapted for inclusion into the SIPP package:  Inge Wallin
X */
X
#include <stdio.h>
#include <math.h>
X
#include <sipp.h>
X
X
Object *
sipp_prism(num_points, points, length, surface, shader)
X    int	      num_points;
X    Vector  * points;
X    double    length;
X    void    * surface;
X    Shader  * shader;
{
X    Object  * prism;
X    int	     i;
X    int	     j;
X
X    prism = object_create();
X
X    /* The top. */
X    for (i = 0; i < num_points ; ++i) {
X        vertex_tx_push(points[i].x, points[i].y, length / 2.0, 
X                       points[i].x, points[i].y, length / 2.0);
X    }
X    polygon_push();
X    object_add_surface(prism, surface_create(surface, shader) );
X
X    /* The bottom */
X    for (i = num_points - 1; i >= 0 ; --i) {
X        vertex_tx_push(points[i].x, points[i].y, -length / 2.0, 
X                       points[i].x, points[i].y, -length / 2.0);
X    }
X    polygon_push();
X    object_add_surface(prism, surface_create(surface, shader) );
X
X    /* The sides */
X    for (i = 0; i < num_points ; ++i) {
X        j = i + 1;
X        if (j == num_points)
X            j=0;
X        vertex_tx_push(points[i].x, points[i].y,  length / 2.0, 
X                       points[i].x, points[i].y,  length / 2.0);
X        vertex_tx_push(points[i].x, points[i].y, -length / 2.0, 
X                       points[i].x, points[i].y, -length / 2.0);
X        vertex_tx_push(points[j].x, points[j].y, -length / 2.0, 
X                       points[j].x, points[j].y, -length / 2.0);
X        vertex_tx_push(points[j].x, points[j].y,  length / 2.0, 
X                       points[j].x, points[j].y,  length / 2.0);
X        polygon_push();
X        object_add_surface(prism, surface_create(surface, shader) );
X    }
X    
X    return prism;
}
X
X
Object *
sipp_block(xsize, ysize, zsize, surface, shader)
X    double    xsize;
X    double    ysize;
X    double    zsize;
X    void    * surface;
X    Shader  * shader;
{
X    Vector   points[4];
X    int      i;
X
X    points[0].x =   xsize / 2.0;
X    points[0].y = - ysize / 2.0;
X    points[1].x =   xsize / 2.0;
X    points[1].y =   ysize / 2.0;
X    points[2].x = - xsize / 2.0;
X    points[2].y =   ysize / 2.0;
X    points[3].x = - xsize / 2.0;
X    points[3].y = - ysize / 2.0;
X    for (i = 0; i < 4; ++i) {
X        points[i].z = 0.0;
X    }
X
X    return sipp_prism(4, &points[0], zsize, surface, shader);
}
X
X
Object *
sipp_cube(size, surface, shader)
X    double   size;
X    void     *surface;
X    Shader   *shader;
{
X    return sipp_block(size, size, size, surface, shader);
}
SHAR_EOF
chmod 0664 libsipp/prism.c ||
echo 'restore of libsipp/prism.c failed'
Wc_c="`wc -c < 'libsipp/prism.c'`"
test 2773 -eq "$Wc_c" ||
	echo 'libsipp/prism.c: original size 2773, current size' "$Wc_c"
fi
true || echo 'restore of libsipp/rendering.c failed'
echo End of part 3, continue with part 4
exit 0

-- 
------------------------------------------------------------------------------
 J o n a s   Y n g v e s s o n
Dept. of Electrical Engineering	                         jonas-y@isy.liu.se
University of Linkoping, Sweden                   ...!uunet!isy.liu.se!jonas-y

exit 0 # Just in case...


