home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume21
/
sipp
/
part03
< prev
next >
Wrap
Text File
|
1991-07-23
|
42KB
|
1,602 lines
Newsgroups: comp.sources.misc
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
Date: Tue, 23 Jul 1991 18:16:39 GMT
Approved: kent@sparky.imd.sterling.com
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...