home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-23 | 49.8 KB | 1,681 lines |
- Newsgroups: comp.sources.misc
- From: Jonas Yngvesson <jonas-y@isy.liu.se>
- Subject: v21i029: sipp - A 3D rendering library v2.1, Part04/08
- Message-ID: <1991Jul23.181700.27805@sparky.IMD.Sterling.COM>
- X-Md4-Signature: b09f7aedec58793386724d8ce2f19af1
- Date: Tue, 23 Jul 1991 18:17:00 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Jonas Yngvesson <jonas-y@isy.liu.se>
- Posting-number: Volume 21, Issue 29
- Archive-name: sipp/part04
- Supersedes: sipp2.0: Volume 16, Issue 5-10
- Environment: UNIX
-
- #!/bin/sh
- # This is part 04 of sipp-2.1
- # ============= libsipp/rendering.c ==============
- if test ! -d 'libsipp'; then
- echo 'x - creating directory libsipp'
- mkdir 'libsipp'
- fi
- if test -f 'libsipp/rendering.c' -a X"$1" != X"-c"; then
- echo 'x - skipping libsipp/rendering.c (File already exists)'
- else
- echo 'x - extracting libsipp/rendering.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'libsipp/rendering.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 ** rendering.c - Functions that handles rendering of the scene.
- X **/
- X
- #include <stdio.h>
- #ifndef NOMEMCPY
- #include <memory.h>
- #endif
- X
- #include <xalloca.h>
- #include <smalloc.h>
- X
- #include <lightsource.h>
- #include <geometric.h>
- #include <rendering.h>
- #include <objects.h>
- #include <sipp.h>
- #include <sipp_bitmap.h>
- #include <viewpoint.h>
- #include <patchlevel.h>
- X
- char *SIPP_VERSION = "2.1";
- X
- /*
- X * Static global variables.
- X */
- static bool show_backfaces; /* Don't do backface culling */
- static Edge **y_bucket; /* Y-bucket for edge lists. */
- static FILE *image_file; /* File to store image in */
- X /* when rendering into a file. */
- static void *image_pm; /* Pixmap to store image in when */
- X /* rendering into a pix/bitmap. */
- static void (*pixmap_set)(); /* Pointer to function for setting */
- X /* a pixel or draw a line in image_pm */
- X
- X
- /*
- X * Stack of transformation matrices used
- X * when traversing an object hierarchy.
- X */
- static struct tm_stack_t {
- X Transf_mat mat;
- X struct tm_stack_t *next;
- } *tm_stack;
- X
- static Transf_mat curr_mat; /* Current transformation matrix */
- X
- X
- X
- /*
- X * Calculate the normal vector for all polygons in the polygon list PSTART.
- X *
- X * Check if the polygon is backfacing with respect to the current
- X * viewpoint.
- X *
- X * The normalized normal is added to a normal kept at each vertex
- X * in the polygon. This will produce, at each vertex, an average of the
- X * normals of the adjectent plygons.
- X */
- static void
- calc_normals(pstart, eyepoint)
- X Polygon *pstart; /* Head of polygon list */
- X Vector eyepoint; /* Viewpoint transformed to local coordinate system */
- {
- X Vector normal;
- X Vertex_ref *vref1, *vref2;
- X Polygon *polyref;
- X double plane_const;
- X
- X for (polyref = pstart; polyref != NULL; polyref = polyref->next) {
- X vref1 = polyref->vertices;
- X vref2 = vref1->next;
- X
- X normal.x = normal.y = normal.z = 0.0;
- X do {
- X normal.x += ((vref1->vertex->y - vref2->vertex->y)
- X * (vref1->vertex->z + vref2->vertex->z));
- X normal.y += ((vref1->vertex->z - vref2->vertex->z)
- X * (vref1->vertex->x + vref2->vertex->x));
- X normal.z += ((vref1->vertex->x - vref2->vertex->x)
- X * (vref1->vertex->y + vref2->vertex->y));
- X vref1 = vref1->next;
- X vref2 = ((vref2->next == NULL)?polyref->vertices:vref2->next);
- X } while (vref1 != NULL);
- X vecnorm(&normal);
- X
- X /*
- X * Take care of backfacing polygons.
- X */
- X plane_const = -(normal.x * vref2->vertex->x
- X + normal.y * vref2->vertex->y
- X + normal.z * vref2->vertex->z);
- X if (VecDot(eyepoint, normal) + plane_const <= 0.0) {
- X if (show_backfaces) {
- X polyref->backface = FALSE;
- X VecNegate(normal);
- X } else {
- X polyref->backface = TRUE;
- X }
- X } else {
- X polyref->backface = FALSE;
- X }
- X
- X /*
- X * Add the calculated normal to all vertices
- X * in the poygon. This will result in an avaraged normal
- X * at each vertex after all polygons have been pprocessed.
- X */
- X for (vref1 = polyref->vertices; vref1 != NULL; vref1 = vref1->next) {
- X vref1->vertex->a += normal.x;
- X vref1->vertex->b += normal.y;
- X vref1->vertex->c += normal.z;
- X }
- X }
- }
- X
- X
- X
- /*
- X * Walk around a polygon, create the surrounding
- X * edges and sort them into the y-bucket.
- X */
- static void
- create_edges(view_vert, polygon, surface, render_mode)
- X View_coord *view_vert;
- X int polygon;
- X Surface *surface;
- X int render_mode;
- {
- X Edge *edge;
- X View_coord *view_ref, *last;
- X int nderiv, y1, y2;
- X double deltay;
- X double x1, x2, xstep;
- X double z1, z2, zstep;
- X double nx1, nx2, nxstep;
- X double ny1, ny2, nystep;
- X double nz1, nz2, nzstep;
- X double u1, u2, ustep;
- X double v1, v2, vstep;
- X double w1, w2, wstep;
- X
- X
- X view_ref = last = view_vert;
- X
- X do {
- X view_ref = view_ref->next;
- X
- X /*
- X * If we are drawing a line image we dont need
- X * to build a complete edgelist. We draw the
- X * lines directly instead.
- X *
- X * Since many lines are drawn twice (edges shared between
- X * two polygons) and many line drawing algorithms are unsymmetrical
- X * we need to make sure lines are always drawn in the same
- X * direction
- X */
- X if (render_mode == LINE) {
- X if (view_ref->y < view_ref->next->y) {
- X (*pixmap_set)(image_pm,
- X (int)(view_ref->x + 0.5),
- X (int)(view_ref->y + 0.5),
- X (int)(view_ref->next->x + 0.5),
- X (int)(view_ref->next->y + 0.5));
- X } else {
- X (*pixmap_set)(image_pm,
- X (int)(view_ref->next->x + 0.5),
- X (int)(view_ref->next->y + 0.5),
- X (int)(view_ref->x + 0.5),
- X (int)(view_ref->y + 0.5));
- X }
- X continue;
- X }
- X
- X /*
- X * Check if the slope of the edge is positive or negative
- X * or zero.
- X */
- X y1 = (int)(view_ref->y + 0.5);
- X y2 = (int)(view_ref->next->y + 0.5);
- X deltay = (double)(y2 - y1);
- X
- X if (deltay > 0.0)
- X nderiv = 1;
- X else if (deltay < 0.0)
- X nderiv = -1;
- X else
- X nderiv = 0;
- X
- X /*
- X * Check if the edge is horizontal. In that case we
- X * just skip it.
- X */
- X if (nderiv != 0) {
- X
- X edge = (Edge *)smalloc(sizeof(Edge));
- X
- X x1 = view_ref->x;
- X x2 = view_ref->next->x;
- X z1 = view_ref->z;
- X z2 = view_ref->next->z;
- X nx1 = view_ref->nx;
- X nx2 = view_ref->next->nx;
- X ny1 = view_ref->ny;
- X ny2 = view_ref->next->ny;
- X nz1 = view_ref->nz;
- X nz2 = view_ref->next->nz;
- X u1 = view_ref->u;
- X u2 = view_ref->next->u;
- X v1 = view_ref->v;
- X v2 = view_ref->next->v;
- X w1 = view_ref->w;
- X w2 = view_ref->next->w;
- X
- X deltay = fabs(deltay);
- X xstep = (x2 - x1) / deltay;
- X zstep = (z2 - z1) / deltay;
- X if (render_mode != FLAT) {
- X nxstep = (nx2 - nx1) / deltay;
- X nystep = (ny2 - ny1) / deltay;
- X nzstep = (nz2 - nz1) / deltay;
- X if (render_mode == PHONG) {
- X ustep = (u2 - u1) / deltay;
- X vstep = (v2 - v1) / deltay;
- X wstep = (w2 - w1) / deltay;
- X }
- X }
- X
- X if (nderiv > 0) {
- X
- X /*
- X * The edge has positive slope
- X */
- X edge->y = y2;
- X edge->y_stop = y1;
- X edge->x = x2;
- X edge->z = z2;
- X edge->nx = nx2;
- X edge->ny = ny2;
- X edge->nz = nz2;
- X edge->u = u2;
- X edge->v = v2;
- X edge->w = w2;
- X edge->xstep = -xstep;
- X edge->zstep = -zstep;
- X if (render_mode != FLAT) {
- X edge->nxstep = -nxstep;
- X edge->nystep = -nystep;
- X edge->nzstep = -nzstep;
- X if (render_mode == PHONG) {
- X edge->ustep = -ustep;
- X edge->vstep = -vstep;
- X edge->wstep = -wstep;
- X }
- X }
- X
- X } else {
- X
- X /*
- X * The edge has negative slope.
- X */
- X edge->y = y1;
- X edge->y_stop = y2;
- X edge->x = x1;
- X edge->z = z1;
- X edge->nx = nx1;
- X edge->ny = ny1;
- X edge->nz = nz1;
- X edge->u = u1;
- X edge->v = v1;
- X edge->w = w1;
- X edge->xstep = xstep;
- X edge->zstep = zstep;
- X if (render_mode != FLAT) {
- X edge->nxstep = nxstep;
- X edge->nystep = nystep;
- X edge->nzstep = nzstep;
- X if (render_mode == PHONG) {
- X edge->ustep = ustep;
- X edge->vstep = vstep;
- X edge->wstep = wstep;
- X }
- X }
- X }
- X edge->polygon = polygon;
- X edge->surface = surface;
- X edge->next = y_bucket[edge->y];
- X y_bucket[edge->y] = edge;
- X }
- X } while (view_ref != last);
- }
- X
- X
- X
- /*
- X * Calculate a new vertex by interpolation between
- X * V1 and V2.
- X */
- static View_coord *
- interpolate(v1, v2, ratio)
- X View_coord *v1, *v2;
- X double ratio;
- {
- X View_coord *tmp;
- X
- X tmp = (View_coord *)smalloc(sizeof(View_coord));
- X
- X tmp->x = v1->x + ratio * (v2->x - v1->x);
- X tmp->y = v1->y + ratio * (v2->y - v1->y);
- X tmp->z = v1->z + ratio * (v2->z - v1->z);
- X tmp->nx = v1->nx + ratio * (v2->nx - v1->nx);
- X tmp->ny = v1->ny + ratio * (v2->ny - v1->ny);
- X tmp->nz = v1->nz + ratio * (v2->nz - v1->nz);
- X tmp->u = v1->u + ratio * (v2->u - v1->u);
- X tmp->v = v1->v + ratio * (v2->v - v1->v);
- X tmp->w = v1->w + ratio * (v2->w - v1->w);
- X tmp->next = NULL;
- X
- X return tmp;
- }
- X
- X
- X
- /*
- X * Clip a polygon using the Sutherland-Hodgeman algorithm for
- X * reentrant clipping;
- X */
- #define XMIN 0
- #define XMAX 1
- #define YMIN 2
- #define YMAX 3
- #define ZMIN 4
- #define ZMAX 5
- X
- static View_coord *
- polygon_clip(vlist, plane, first_vert)
- X View_coord *vlist;
- X int plane;
- X bool first_vert;
- {
- X static View_coord *first;
- X static View_coord *curr;
- X View_coord *out1;
- X View_coord *out2;
- X double curr_limit;
- X double first_limit;
- X double vlist_limit;
- X double ratio;
- X bool visible;
- X
- X out1 = out2 = NULL;
- X
- X if (vlist == NULL) {
- X
- X /*
- X * Did we get an empty list from the start?
- X */
- X if (first_vert) {
- X return NULL;
- X }
- X
- X /*
- X * Last vertex, close the polygon.
- X */
- X ratio = 0.0;
- X curr_limit = curr->z * camera.focal_ratio;
- X first_limit = first->z * camera.focal_ratio;
- X
- X switch (plane) {
- X
- X case XMIN:
- X if ((curr->x < -curr_limit && first->x >= -first_limit)
- X || (curr->x >= -curr_limit && first->x < -first_limit)) {
- X ratio = fabs(curr->x + curr_limit);
- X ratio /= (ratio + fabs(first->x + first_limit));
- X }
- X break;
- X
- X case XMAX:
- X if ((curr->x <= curr_limit && first->x > first_limit)
- X || (curr->x > curr_limit && first->x <= first_limit)) {
- X ratio = fabs(curr->x - curr_limit);
- X ratio /= (ratio + fabs(first->x - first_limit));
- X }
- X break;
- X
- X case YMIN:
- X if ((curr->y < -curr_limit && first->y >= -first_limit)
- X || (curr->y >= -curr_limit && first->y < -first_limit)) {
- X ratio = fabs(curr->y + curr_limit);
- X ratio /= (ratio + fabs(first->y + first_limit));
- X }
- X break;
- X
- X case YMAX:
- X if ((curr->y <= curr_limit && first->y > first_limit)
- X || (curr->y > curr_limit && first->y <= first_limit)) {
- X ratio = fabs(curr->y - curr_limit);
- X ratio /= (ratio + fabs(first->y - first_limit));
- X }
- X break;
- X
- X case ZMIN:
- X if ((curr->z < hither && first->z >= hither)
- X || (curr->z >= hither && first->z < hither)) {
- X ratio = fabs(curr->z - hither);
- X ratio = ratio / (ratio + fabs(first->z - hither));
- X }
- X break;
- X
- X case ZMAX:
- X if ((curr->z <= yon && first->z > yon)
- X || (curr->z > yon && first->z <= yon)) {
- X ratio = fabs(curr->z - yon);
- X ratio = ratio / (ratio + fabs(first->z - yon));
- X }
- X break;
- X }
- X
- X if (ratio != 0.0) {
- X out1 = interpolate(curr, first, ratio);
- X return out1;
- X } else {
- X return NULL;
- X }
- X }
- X
- X vlist_limit = vlist->z * camera.focal_ratio;
- X
- X if (first_vert) {
- X first = vlist;
- X } else {
- X ratio = 0.0;
- X curr_limit = curr->z * camera.focal_ratio;
- X
- X switch (plane) {
- X
- X case XMIN:
- X if ((curr->x < -curr_limit && vlist->x >= -vlist_limit)
- X || (curr->x >= -curr_limit && vlist->x < -vlist_limit)) {
- X ratio = fabs(curr->x + curr_limit);
- X ratio /= (ratio + fabs(vlist->x + vlist_limit));
- X }
- X break;
- X
- X case XMAX:
- X if ((curr->x <= curr_limit && vlist->x > vlist_limit)
- X || (curr->x > curr_limit && vlist->x <= vlist_limit)) {
- X ratio = fabs(curr->x - curr_limit);
- X ratio /= (ratio + fabs(vlist->x - vlist_limit));
- X }
- X break;
- X
- X case YMIN:
- X if ((curr->y < -curr_limit && vlist->y >= -vlist_limit)
- X || (curr->y >= -curr_limit && vlist->y < -vlist_limit)) {
- X ratio = fabs(curr->y + curr_limit);
- X ratio /= (ratio + fabs(vlist->y + vlist_limit));
- X }
- X break;
- X
- X case YMAX:
- X if ((curr->y <= curr_limit && vlist->y > vlist_limit)
- X || (curr->y > curr_limit && vlist->y <= vlist_limit)) {
- X ratio = fabs(curr->y - curr_limit);
- X ratio /= (ratio + fabs(vlist->y - vlist_limit));
- X }
- X break;
- X
- X case ZMIN:
- X if ((curr->z < hither && vlist->z >= hither)
- X || (curr->z >= hither && vlist->z < hither)) {
- X ratio = fabs(curr->z - hither);
- X ratio = ratio / (ratio + fabs(vlist->z - hither));
- X }
- X break;
- X
- X case ZMAX:
- X if ((curr->z <= yon && vlist->z > yon)
- X || (curr->z > yon && vlist->z <= yon)) {
- X ratio = fabs(curr->z - yon);
- X ratio = ratio / (ratio + fabs(vlist->z - yon));
- X }
- X break;
- X }
- X
- X if (ratio != 0.0) {
- X out1 = interpolate(curr, vlist, ratio);
- X out1->next = vlist;
- X }
- X }
- X
- X curr = vlist;
- X visible = FALSE;
- X switch (plane) {
- X
- X case XMIN:
- X visible = (curr->x >= -vlist_limit);
- X break;
- X
- X case XMAX:
- X visible = (curr->x <= vlist_limit);
- X break;
- X
- X case YMIN:
- X visible = (curr->y >= -vlist_limit);
- X break;
- X
- X case YMAX:
- X visible = (curr->y <= vlist_limit);
- X break;
- X
- X case ZMIN:
- X visible = (curr->z >= hither);
- X break;
- X
- X case ZMAX:
- X visible = (curr->z <= yon);
- X break;
- X }
- X
- X if (visible) {
- X out2 = curr;
- X out2->next = polygon_clip(curr->next, plane, FALSE);
- X return ((out1) ? (out1) : (out2));
- X
- X } else {
- X if (out1) {
- X out1->next = polygon_clip(curr->next, plane, FALSE);
- X } else {
- X out1 = polygon_clip(curr->next, plane, FALSE);
- X }
- X free(vlist);
- X return out1;
- X }
- }
- X
- X
- X
- /*
- X * Transform vertices into view coordinates. The transform is
- X * defined in MATRIX. Store the transformed vertices in a
- X * temporary list, create edges in the y_bucket.
- X */
- static void
- transf_vertices(vertex_list, surface, view_mat, tr_mat,
- X xsiz, ysiz, render_mode)
- X Vertex_ref *vertex_list;
- X Surface *surface;
- X Transf_mat *view_mat;
- X Transf_mat *tr_mat;
- X double xsiz, ysiz;
- X int render_mode;
- {
- X static int polygon = 0; /* incremented for each call to provide */
- X /* unique polygon id numbers */
- X Vertex_ref *vref;
- X View_coord *nhead;
- X View_coord *view_ref;
- X View_coord *mark;
- X Color color;
- X double minsize;
- X double tmp;
- X
- X vref = vertex_list;
- X nhead = NULL;
- X
- X minsize = ((xsiz > ysiz) ? ysiz : xsiz);
- X
- X while (vref != NULL) {
- X
- X view_ref = (View_coord *)smalloc(sizeof(View_coord));
- X
- X
- X /*
- X * Transform the normal (world coordinates).
- X */
- X view_ref->nx = (vref->vertex->a * tr_mat->mat[0][0]
- X + vref->vertex->b * tr_mat->mat[1][0]
- X + vref->vertex->c * tr_mat->mat[2][0]);
- X view_ref->ny = (vref->vertex->a * tr_mat->mat[0][1]
- X + vref->vertex->b * tr_mat->mat[1][1]
- X + vref->vertex->c * tr_mat->mat[2][1]);
- X view_ref->nz = (vref->vertex->a * tr_mat->mat[0][2]
- X + vref->vertex->b * tr_mat->mat[1][2]
- X + vref->vertex->c * tr_mat->mat[2][2]);
- X
- X /*
- X * Transform the vertex into view coordinates.
- X */
- X view_ref->x = (vref->vertex->x * view_mat->mat[0][0]
- X + vref->vertex->y * view_mat->mat[1][0]
- X + vref->vertex->z * view_mat->mat[2][0]
- X + view_mat->mat[3][0]);
- X view_ref->y = (vref->vertex->x * view_mat->mat[0][1]
- X + vref->vertex->y * view_mat->mat[1][1]
- X + vref->vertex->z * view_mat->mat[2][1]
- X + view_mat->mat[3][1]);
- X view_ref->z = (vref->vertex->x * view_mat->mat[0][2]
- X + vref->vertex->y * view_mat->mat[1][2]
- X + vref->vertex->z * view_mat->mat[2][2]
- X + view_mat->mat[3][2]);
- X
- X /*
- X * Texture coordinates is not affected by transformations.
- X */
- X view_ref->u = vref->vertex->u;
- X view_ref->v = vref->vertex->v;
- X view_ref->w = vref->vertex->w;
- X
- X view_ref->next = nhead;
- X nhead = view_ref;
- X
- X vref = vref->next;
- X }
- X
- X /*
- X * Clip the resulting polygon. We need to do this
- X * before the perpective transformation to keep texture
- X * coordinates correct.
- X */
- X nhead = polygon_clip(nhead, ZMIN, TRUE);
- X nhead = polygon_clip(nhead, ZMAX, TRUE);
- X if (xsiz > ysiz) {
- X tmp = camera.focal_ratio;
- X camera.focal_ratio *= xsiz / ysiz;
- X nhead = polygon_clip(nhead, XMIN, TRUE);
- X nhead = polygon_clip(nhead, XMAX, TRUE);
- X camera.focal_ratio = tmp;
- X nhead = polygon_clip(nhead, YMIN, TRUE);
- X nhead = polygon_clip(nhead, YMAX, TRUE);
- X } else {
- X tmp = camera.focal_ratio;
- X camera.focal_ratio *= ysiz / xsiz;
- X nhead = polygon_clip(nhead, YMIN, TRUE);
- X nhead = polygon_clip(nhead, YMAX, TRUE);
- X camera.focal_ratio = tmp;
- X nhead = polygon_clip(nhead, XMIN, TRUE);
- X nhead = polygon_clip(nhead, XMAX, TRUE);
- X }
- X
- X if (nhead == NULL) { /* Nothing left? */
- X return;
- X }
- X
- X
- X
- X /*
- X * If we are flat shading, we need a color for the polygon.
- X * We call the shader at the first vertex to get this.
- X * (This is not quite correct since the normal here is
- X * an averaged normal of the surrounding polygons)
- X */
- X if (render_mode == FLAT) {
- X (*surface->shader)
- X (nhead->nx, nhead->ny, nhead->nz,
- X nhead->u, nhead->v, nhead->w,
- X camera.vec, lightsrc_stack,
- X surface->surface, &color);
- X }
- X
- X
- X /*
- X * Walk around the new (clipped and transformed) polygon and
- X * transform it into perspective screen coordinates.
- X * We have to transform the texture coordinates too in order
- X * to interpolate them linearly in "screen space". This
- X * transformation is inverted in render_line().
- X * If we are doing gouraud shading we call the shader at each
- X * vertex.
- X * Last we tie the head and tail together forming a cirkular
- X * list, this simplifies edge creation.
- X */
- X for (view_ref = nhead;; view_ref = view_ref->next) {
- X view_ref->z *= camera.focal_ratio;
- X view_ref->x = view_ref->x * minsize / view_ref->z + xsiz;
- X view_ref->y = view_ref->y * minsize / view_ref->z + ysiz;
- X view_ref->u /= view_ref->z;
- X view_ref->v /= view_ref->z;
- X view_ref->w /= view_ref->z;
- X
- X if (render_mode == GOURAUD) {
- X (*surface->shader)
- X (view_ref->nx, view_ref->ny, view_ref->nz,
- X view_ref->u, view_ref->v, view_ref->w,
- X camera.vec, lightsrc_stack,
- X surface->surface, &color);
- X }
- X
- X if (render_mode == GOURAUD || render_mode == FLAT) {
- X view_ref->nx = color.red;
- X view_ref->ny = color.grn;
- X view_ref->nz = color.blu;
- X }
- X
- X if (view_ref->next == NULL) {
- X view_ref->next = nhead;
- X break;
- X }
- X }
- X
- X create_edges(nhead, polygon++, surface, render_mode);
- X
- X /*
- X * Free the memory used by the transformed polygon.
- X */
- X mark = nhead;
- X do {
- X view_ref = nhead;
- X nhead = nhead->next;
- X free(view_ref);
- X } while (nhead != mark);
- }
- X
- X
- X
- /*
- X * Initialize the scanline z-buffer and the actual picture
- X * scanline buffer.
- X */
- static void
- init_buffers(res, z_buffer, scanline)
- X int res;
- X double *z_buffer;
- X unsigned char *scanline;
- {
- X int i;
- X
- #ifdef NOMEMCPY
- X bzero(scanline, res * 3);
- #else
- X memset(scanline, 0, res * 3);
- #endif
- X for (i = 0; i < res; i++)
- X z_buffer[i] = 1.0e100;
- }
- X
- X
- /*
- X * Read edge pairs from the edge list EDGE_LIST. Walk along the scanline
- X * and interpolate z value, texture coordinates and normal vector as
- X * we go. Call the shader and write into scanline buffer according to
- X * result on z-buffer test.
- X */
- static void
- render_line(res, z_buffer, scanline, edge_list, render_mode)
- X int res;
- X double *z_buffer;
- X unsigned char *scanline;
- X Edge *edge_list;
- X int render_mode;
- {
- X double z, zstep;
- X double nx, nxstep;
- X double ny, nystep;
- X double nz, nzstep;
- X double u, ustep;
- X double v, vstep;
- X double w, wstep;
- X double ur, vr, wr;
- X double ratio;
- X Color color;
- X int i, j, x, xstop;
- X Edge *startedge, *stopedge;
- X
- X startedge = edge_list;
- X stopedge = NULL;
- X while (startedge != NULL) {
- X stopedge = startedge->next;
- X x = (int)(startedge->x + 0.5);
- X xstop = (int)(stopedge->x + 0.5);
- X z = startedge->z;
- X nx = startedge->nx;
- X ny = startedge->ny;
- X nz = startedge->nz;
- X u = startedge->u;
- X v = startedge->v;
- X w = startedge->w;
- X if (x < xstop) {
- X ratio = (double)(xstop - x);
- X zstep = (stopedge->z - z) / ratio;
- X if (render_mode != FLAT) {
- X nxstep = (stopedge->nx - nx) / ratio;
- X nystep = (stopedge->ny - ny) / ratio;
- X nzstep = (stopedge->nz - nz) / ratio;
- X if (render_mode == PHONG) {
- X ustep = (stopedge->u - u) / ratio;
- X vstep = (stopedge->v - v) / ratio;
- X wstep = (stopedge->w - w) / ratio;
- X }
- X }
- X } else {
- X zstep = 0.0;
- X nxstep = nystep = nzstep = 0.0;
- X ustep = vstep = wstep = 0.0;
- X }
- X
- X for (i = x, j = i * 3; i <= xstop; i++) {
- X
- X if (z < z_buffer[i]) {
- X
- X if (render_mode == PHONG) {
- X ur = u * z; /* Transform texture coordinates back */
- X vr = v * z; /* from their homogenouos form */
- X wr = w * z;
- X (*startedge->surface->shader)
- X (nx, ny, nz, ur, vr, wr,
- X camera.vec, lightsrc_stack,
- X startedge->surface->surface, &color);
- X scanline[j++] = (unsigned char)(color.red * 255.0 + 0.5);
- X scanline[j++] = (unsigned char)(color.grn * 255.0 + 0.5);
- X scanline[j++] = (unsigned char)(color.blu * 255.0 + 0.5);
- X
- X } else if (render_mode == FLAT || render_mode == GOURAUD) {
- X scanline[j++] = (unsigned char)(nx * 255.0 + 0.5);
- X scanline[j++] = (unsigned char)(ny * 255.0 + 0.5);
- X scanline[j++] = (unsigned char)(nz * 255.0 + 0.5);
- X }
- X
- X z_buffer[i] = z;
- X
- X } else if (i >= res) {
- X break;
- X
- X } else {
- X j += 3;
- X }
- X
- X z += zstep;
- X if (render_mode != FLAT) {
- X nx += nxstep;
- X ny += nystep;
- X nz += nzstep;
- X if (render_mode == PHONG) {
- X u += ustep;
- X v += vstep;
- X w += wstep;
- X }
- X }
- X }
- X startedge = stopedge->next;
- X }
- }
- X
- X
- X
- X
- /*
- X * Insert an edge into an edge list. Edges belonging to the same
- X * polygon must be inserted sorted in x, so that edge pairs are
- X * created.
- X */
- static Edge *
- insert_edge(edge_list, edge, poly_found)
- X Edge *edge_list, *edge;
- X bool poly_found;
- {
- X if (edge_list == NULL) {
- X edge_list = edge;
- X edge->next = NULL;
- X } else if (edge_list->polygon == edge->polygon) {
- X if (edge_list->x > edge->x) {
- X edge->next = edge_list;
- X edge_list = edge;
- X } else if ((((int)(edge_list->x + 0.5)) == ((int)(edge->x + 0.5)))
- X && (edge_list->xstep > edge->xstep)) {
- X edge->next = edge_list;
- X edge_list = edge;
- X } else {
- X edge_list->next = insert_edge(edge_list->next, edge, TRUE);
- X }
- X } else if (poly_found) {
- X edge->next = edge_list;
- X edge_list = edge;
- X } else {
- X edge_list->next = insert_edge(edge_list->next, edge, FALSE);
- X }
- X
- X return edge_list;
- }
- X
- X
- X
- /*
- X * Merge two edge lists.
- X */
- static Edge *
- merge_edge_lists(list1, list2)
- X Edge *list1, *list2;
- {
- X Edge *eref1, *eref2, *next;
- X
- X if (list2 == NULL)
- X return list1;
- X
- X eref1 = list1;
- X eref2 = list2;
- X do {
- X next = eref2->next;
- X eref1 = insert_edge(eref1, eref2, FALSE);
- X eref2 = next;
- X } while (eref2 != NULL);
- X
- X return eref1;
- }
- X
- X
- X
- /*
- X * Store a rendered line on the place indicated by STORAGE_MODE.
- X */
- static void
- store_line(buf, npixels, line, storage_mode)
- X unsigned char *buf;
- X int npixels;
- X int line;
- X int storage_mode;
- {
- X int i, j;
- X
- X switch (storage_mode) {
- X case PBM_FILE:
- X fwrite(buf, sizeof(unsigned char), npixels, image_file);
- X fflush(image_file);
- X break;
- X
- X case PPM_FILE:
- X fwrite(buf, sizeof(unsigned char), npixels * 3, image_file);
- X fflush(image_file);
- X break;
- X
- X case PIXMAP:
- X for (i = 0, j = 0; j < npixels; j++, i += 3) {
- X (*pixmap_set)(image_pm, j, line, buf[i], buf[i + 1], buf[i + 2]);
- X }
- X break;
- X
- X default:
- X break;
- X }
- }
- X
- X
- /*
- X * Allocate the needed buffers. Create a list of active edges and
- X * move down the y-bucket, inserting and deleting edges from this
- X * active list as we go. Call render_line for each scanline and
- X * do an average filtering before storing the scanline.
- X */
- static void
- scan_and_render(xres, yres, storage_mode, render_mode, oversampl)
- X int xres, yres;
- X int storage_mode;
- X int render_mode;
- X int oversampl;
- {
- X Edge *active_list, *edgep, *edgep2;
- X double *z_buffer;
- X unsigned char **linebuf;
- X int curr_line;
- X int y, next_edge;
- X int sum;
- X int i, j, k, l;
- X
- X z_buffer = (double *)scalloc(xres, sizeof(double));
- X linebuf = (unsigned char **)alloca(oversampl * sizeof(unsigned char *));
- X for (i = 0; i < oversampl; i++) {
- X linebuf[i] = (unsigned char *)scalloc(xres * 3, sizeof(unsigned char));
- X }
- X
- X if (storage_mode == PPM_FILE) {
- X fprintf(image_file, "P6\n");
- X fprintf(image_file, "#Image rendered with SIPP %s%s\n",
- X SIPP_VERSION, PATCHLEVEL);
- X fprintf(image_file, "%d\n%d\n255\n", xres / oversampl,
- X yres / oversampl);
- X }
- X
- X y = yres - 1;
- X active_list = NULL;
- X curr_line = 0;
- X
- X while (y >= 0) {
- X
- X active_list = merge_edge_lists(active_list, y_bucket[y]);
- X next_edge = y - 1;
- X
- X while (next_edge >=0 && y_bucket[next_edge] == NULL)
- X next_edge--;
- X
- X while (y > next_edge) {
- X
- X init_buffers(xres, z_buffer, linebuf[curr_line]);
- X render_line(xres, z_buffer, linebuf[curr_line], active_list,
- X render_mode);
- X
- X if (++curr_line == oversampl) {
- X
- X /*
- X * Average the pixel.
- X */
- X for (i = 0; i < ((xres / oversampl)); i++) {
- X for (l = 0; l < 3; l++) {
- X sum = 0;
- X for (j = i * 3 * oversampl + l;
- X j < (i * 3 * oversampl + l + 3 * oversampl);
- X j += 3) {
- X for (k = 0; k < oversampl; k++) {
- X sum += *(linebuf[k] + j);
- X }
- X }
- X *(linebuf[0] + i * 3 + l)
- X = sum / (oversampl * oversampl);
- X }
- X }
- X store_line(linebuf[0], xres / oversampl,
- X (yres - y - 1) / oversampl, storage_mode);
- X curr_line = 0;
- X }
- X
- X if (active_list != NULL) {
- X
- X edgep2 = active_list;
- X edgep = active_list->next;
- X while (edgep != NULL) {
- X if (edgep->y <= (edgep->y_stop + 1)) {
- X edgep2->next = edgep->next;
- X free(edgep);
- X edgep = edgep2->next;
- X } else {
- X edgep2 = edgep;
- X edgep = edgep->next;
- X }
- X }
- X
- X if (active_list->y <= (active_list->y_stop + 1)) {
- X edgep = active_list;
- X active_list = active_list->next;
- X free(edgep);
- X }
- X
- X edgep = active_list;
- X while (edgep != NULL) {
- X edgep->y--;
- X edgep->x += edgep->xstep;
- X edgep->z += edgep->zstep;
- X if (render_mode != FLAT) {
- X edgep->nx += edgep->nxstep;
- X edgep->ny += edgep->nystep;
- X edgep->nz += edgep->nzstep;
- X if (render_mode == PHONG) {
- X edgep->u += edgep->ustep;
- X edgep->v += edgep->vstep;
- X edgep->w += edgep->wstep;
- X }
- X }
- X edgep = edgep->next;
- X }
- X }
- X y--;
- X }
- X }
- X free(z_buffer);
- X for (i = 0; i < oversampl; i++) {
- X free(linebuf[i]);
- X }
- }
- X
- X
- X
- /*
- X * Reset the averaged normals in the vertex tree P.
- X */
- static void
- reset_normals(vref)
- X Vertex *vref;
- {
- X if (vref != NULL) {
- X vref->a = 0;
- X vref->b = 0;
- X vref->c = 0;
- X reset_normals(vref->big);
- X reset_normals(vref->sml);
- X }
- }
- X
- X
- X
- /*
- X * Push the current transformation matrix on the matrix stack.
- X */
- static void
- matrix_push()
- {
- X struct tm_stack_t *new_tm;
- X
- X new_tm = (struct tm_stack_t *)smalloc(sizeof(struct tm_stack_t));
- X MatCopy(&new_tm->mat, &curr_mat);
- X new_tm->next = tm_stack;
- X tm_stack = new_tm;
- }
- X
- X
- /*
- X * Pop the top of the matrix stack and make
- X * it the new current transformation matrix.
- X */
- static void
- matrix_pop()
- {
- X struct tm_stack_t *tmp;
- X
- X MatCopy(&curr_mat, &tm_stack->mat);
- X tmp = tm_stack;
- X tm_stack = tm_stack->next;
- X free(tmp);
- }
- X
- X
- X
- /*
- X * Traverse an object hierarchy, transform each object
- X * according to its transformation matrix.
- X * Transform all polygons in the object to view coordinates.
- X * Build the edge lists in y_bucket.
- X */
- static void
- traverse_object_tree(object, view_mat, xres, yres, render_mode)
- X Object *object;
- X Transf_mat *view_mat;
- X int xres, yres;
- X int render_mode;
- {
- X Object *objref;
- X Surface *surfref;
- X Polygon *polyref;
- X Vector eyepoint, tmp;
- X Transf_mat loc_view_mat;
- X double m[3][4], dtmp;
- X int i, j;
- X
- X
- X if (object == NULL) {
- X return;
- X }
- X
- X for (objref = object; objref != NULL; objref = objref->next) {
- X
- X matrix_push();
- X mat_mul(&curr_mat, &objref->transf, &curr_mat);
- X mat_mul(&loc_view_mat, &curr_mat, view_mat);
- X
- X tmp.x = camera.x0;
- X tmp.y = camera.y0;
- X tmp.z = camera.z0;
- X
- X /*
- X * Do an inverse transformation of the viewpoint to use
- X * when doing backface culling (in calc_normals()).
- X */
- X tmp.x -= curr_mat.mat[3][0];
- X tmp.y -= curr_mat.mat[3][1];
- X tmp.z -= curr_mat.mat[3][2];
- X m[0][0] = curr_mat.mat[0][0] ; m[0][1] = curr_mat.mat[1][0];
- X m[0][2] = curr_mat.mat[2][0] ; m[0][3] = tmp.x;
- X m[1][0] = curr_mat.mat[0][1] ; m[1][1] = curr_mat.mat[1][1];
- X m[1][2] = curr_mat.mat[2][1] ; m[1][3] = tmp.y;
- X m[2][0] = curr_mat.mat[0][2] ; m[2][1] = curr_mat.mat[1][2];
- X m[2][2] = curr_mat.mat[2][2] ; m[2][3] = tmp.z;
- X
- X if (m[0][0] == 0.0) {
- X if (m[1][0] != 0.0)
- X j = 1;
- X else
- X j = 2;
- X for (i = 0; i < 4; i++) {
- X dtmp = m[0][i];
- X m[0][i] = m[j][i];
- X m[j][i] = dtmp;
- X }
- X }
- X
- X for (j = 1; j < 3; j++) {
- X m[j][0] /= (-m[0][0]);
- X for (i = 1; i < 4; i++)
- X m[j][i] += m[0][i] * m[j][0];
- X }
- X
- X if (m[1][1] == 0.0)
- X for (i = 1; i < 4; i++) {
- X dtmp = m[1][i];
- X m[1][i] = m[2][i];
- X m[2][i] = dtmp;
- X }
- X
- X if (m[1][1] != 0.0) {
- X m[2][1] /= (-m[1][1]);
- X m[2][2] += m[1][2] * m[2][1];
- X m[2][3] += m[1][3] * m[2][1];
- X }
- X
- X eyepoint.z = m[2][3] / m[2][2];
- X eyepoint.y = (m[1][3] - eyepoint.z * m[1][2]) / m[1][1];
- X eyepoint.x = (m[0][3] - eyepoint.z * m[0][2]
- X - eyepoint.y * m[0][1]) / m[0][0];
- X
- X for (surfref = objref->surfaces; surfref != NULL;
- X surfref = surfref->next) {
- X
- X calc_normals(surfref->polygons, eyepoint);
- X
- X for (polyref = surfref->polygons; polyref != NULL;
- X polyref = polyref->next) {
- X
- X if (!polyref->backface) {
- X transf_vertices(polyref->vertices, surfref,
- X &loc_view_mat,
- X &curr_mat, (double)xres / 2.0,
- X (double)yres / 2.0, render_mode);
- X }
- X
- X }
- X reset_normals(surfref->vertices);
- X
- X }
- X traverse_object_tree(objref->sub_obj, view_mat, xres, yres,
- X render_mode);
- X matrix_pop();
- X }
- }
- X
- X
- X
- /*
- X * Recursively traverse the rendering database (preorder).
- X * Call traverse_object_tree for each object.
- X */
- static void
- traverse_object_db(obj_root, view_mat, xres, yres, render_mode)
- X Inst_object *obj_root;
- X Transf_mat *view_mat;
- X int xres, yres;
- X int render_mode;
- {
- X if (obj_root != NULL) {
- X traverse_object_tree(obj_root->object, view_mat,
- X xres, yres, render_mode);
- X traverse_object_db(obj_root->sml, view_mat,
- X xres, yres, render_mode);
- X traverse_object_db(obj_root->big, view_mat,
- X xres, yres, render_mode);
- X }
- }
- X
- X
- X
- X
- /*
- X * "Main" functions in rendering. Allocate y-bucket, transform vertices
- X * into viewing coordinates, make edges and sort them into the y-bucket.
- X * Call scan_and_render to do the real work.
- X */
- static void
- render_main(xres, yres, storage_mode, render_mode, oversampling)
- X int xres, yres;
- X int storage_mode;
- X int render_mode;
- X int oversampling;
- {
- X Transf_mat view_mat;
- X
- X if (render_mode != LINE) {
- X xres *= oversampling;
- X yres *= oversampling;
- X y_bucket = (Edge **)scalloc(yres, sizeof(Edge *));
- X
- X } else if (storage_mode == PBM_FILE) {
- X image_pm = sipp_bitmap_create(xres, yres);
- X pixmap_set = sipp_bitmap_line;
- X }
- X
- X get_view_transf(&view_mat);
- X MatCopy(&curr_mat, &ident_matrix);
- X
- X vecnorm(&camera.vec);
- X
- X traverse_object_db(object_db, &view_mat,
- X xres - 1, yres - 1, render_mode);
- X
- X if (render_mode != LINE) {
- X scan_and_render(xres, yres, storage_mode, render_mode, oversampling);
- X free(y_bucket);
- X
- X } else if (storage_mode == PBM_FILE) {
- X sipp_bitmap_write(image_file, image_pm);
- X sipp_bitmap_destruct(image_pm);
- X }
- X
- X view_vec_eval();
- X
- }
- X
- X
- void
- render_image_file(xres, yres, im_file, render_mode, oversampling)
- X int xres, yres;
- X FILE *im_file;
- X int render_mode;
- X int oversampling;
- {
- X image_file = im_file;
- X
- X if (render_mode == LINE) {
- X render_main(xres, yres, PBM_FILE, render_mode, oversampling);
- X } else {
- X render_main(xres, yres, PPM_FILE, render_mode, oversampling);
- X }
- }
- X
- X
- void
- render_image_pixmap(xres, yres, pixmap, pixmap_func, render_mode, oversampling)
- X int xres, yres;
- X void *pixmap;
- X void (*pixmap_func)();
- X int render_mode;
- X int oversampling;
- {
- X image_pm = pixmap;
- X pixmap_set = pixmap_func;
- X render_main(xres, yres, PIXMAP, render_mode, oversampling);
- }
- X
- X
- X
- /*============= Functions that handles global initializations==============*/
- X
- /*
- X * If called with TRUE as argument, no backface culling will
- X * be performed. If a polygon is backfacing it will be rendered
- X * as facing in the opposit direction.
- X */
- void
- sipp_show_backfaces(flag)
- X bool flag;
- {
- X show_backfaces = flag;
- }
- X
- X
- X
- /*
- X * Necessary initializations.
- X */
- void
- sipp_init()
- {
- X objects_init();
- X lightsource_init();
- X sipp_show_backfaces(FALSE);
- X viewpoint(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.25);
- }
- SHAR_EOF
- chmod 0644 libsipp/rendering.c ||
- echo 'restore of libsipp/rendering.c failed'
- Wc_c="`wc -c < 'libsipp/rendering.c'`"
- test 39990 -eq "$Wc_c" ||
- echo 'libsipp/rendering.c: original size 39990, current size' "$Wc_c"
- fi
- # ============= libsipp/rendering.h ==============
- if test -f 'libsipp/rendering.h' -a X"$1" != X"-c"; then
- echo 'x - skipping libsipp/rendering.h (File already exists)'
- else
- echo 'x - extracting libsipp/rendering.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'libsipp/rendering.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 ** rendering.h - Types and interface to the rendering.c
- X **/
- X
- #ifndef RENDERING_H
- #define RENDERING_H
- X
- #include <sipp.h>
- X
- X
- /*
- X * Modes for storing the image.
- X */
- #define PBM_FILE 0
- #define PPM_FILE 1
- #define PIXMAP 2
- X
- X
- /*
- X * Temporary storage of transformed vertices.
- X */
- typedef struct view_coord_3d {
- X double x, y, 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
- #endif /* RENDERING_H */
- SHAR_EOF
- chmod 0644 libsipp/rendering.h ||
- echo 'restore of libsipp/rendering.h failed'
- Wc_c="`wc -c < 'libsipp/rendering.h'`"
- test 2300 -eq "$Wc_c" ||
- echo 'libsipp/rendering.h: original size 2300, current size' "$Wc_c"
- fi
- # ============= libsipp/shaders.h ==============
- if test -f 'libsipp/shaders.h' -a X"$1" != X"-c"; then
- echo 'x - skipping libsipp/shaders.h (File already exists)'
- else
- echo 'x - extracting libsipp/shaders.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'libsipp/shaders.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 ** shaders.h - This include file defines the different shaders availiable
- X ** in sipp. Each shader is defined by a structure containing
- X ** the necessary parameters to describe how a surface should
- X ** be shaded with that particular shader, and the extern
- X ** declaration of the shader function itself.
- X **/
- X
- X
- #ifndef _SHADERS_H
- #define _SHADERS_H
- X
- X
- #include <sipp.h>
- X
- X
- X
- /*
- X * Surface description used in strauss_shader().
- X */
- typedef struct {
- X double ambient; /* Fraction of color visible in ambient light */
- X double smoothness; /* Smoothness of the surface [0, 1] */
- X double metalness; /* Metalness of the surface [0, 1] */
- X Color color; /* Base color of the surface */
- } Strauss_desc;
- X
- X
- X
- /*
- X * Surface description for the bozo shader.
- X */
- typedef struct {
- X Color *colors;
- X int no_of_cols;
- X double ambient;
- X double specular;
- X double c3;
- X double scale; /* Scale the texture by this value */
- } Bozo_desc;
- X
- X
- X
- /*
- X * Surface description used by the wood shader. This shader
- X * creates a solid texture (using noise & turbulence) that
- X * simulates wood.
- X */
- typedef struct {
- X double ambient;
- X double specular;
- X double c3;
- X double scale; /* Scale the wood texture by this value */
- X Color base; /* "Base" color of the surface */
- X Color ring; /* Color of the darker rings */
- } Wood_desc;
- X
- X
- X
- /*
- X * Surface description used by the marble shader. marble_shader
- X * creates a solid texture (using noise & turbulence) that
- X * simulates marble.
- X */
- typedef struct {
- X double ambient;
- X double specular;
- X double c3;
- X double scale; /* Scale the marble texture by this value */
- X Color base; /* "Base" color of the surface */
- X Color strip; /* Color of the "stripes" in the marble */
- } Marble_desc;
- X
- X
- X
- /*
- X * Surface description used by the granite shader. granite_shader
- X * creates a solid texture (using noise) that mixes two colors
- X * to simulate granite.
- X */
- typedef struct {
- X double ambient;
- X double specular;
- X double c3;
- X double scale; /* Scale the texture by this value */
- X Color col1; /* The two color components */
- X Color col2; /* */
- } Granite_desc;
- X
- X
- X
- /*
- X * Mask shader. It uses mask image (ususally a bitmap) to
- X * choose between two other shaders. It projects the mask
- X * image on the u-v plane (in texture coordinates). When a
- X * surface is shaded it calls pixel_test() to check the
- X * u, v coordinate in the mask and calls one of two other
- X * shaders depending of the outcome of that test.
- X */
- typedef struct {
- X Shader *fg_shader; /* Shader to call if mask(x, y) != 0 */
- X void *fg_surface; /* Surface description for fg_shader */
- X Shader *bg_shader; /* Shader to call if mask(x, y) == 0 */
- X void *bg_surface; /* Surface description for bg_shader */
- X void *mask; /* Pointer to mask image */
- X bool (*pixel_test)(); /* Function that tests a pixel value */
- X int x0, y0; /* Where to put origo in the mask image */
- X int xsize, ysize; /* Size of the mask image */
- X double xscale, yscale; /* Scale the mask image with these values */
- } Mask_desc;
- X
- X
- /*
- X * Surface description for the bumpy_shader(). This shader
- X * fiddles with the surface normals of a surface so the surface
- X * looks bumpy.
- X */
- X
- typedef struct {
- X Shader *shader;
- X void *surface;
- X double scale;
- X bool bumpflag;
- X bool holeflag;
- } Bumpy_desc;
- X
- X
- /*
- X * Declarations of the actual shading functions.
- X */
- extern void strauss_shader();
- extern void wood_shader();
- extern void marble_shader();
- extern void granite_shader();
- extern void bozo_shader();
- extern void mask_shader();
- extern void bumpy_shader();
- extern void planet_shader();
- X
- #endif /* _SHADERS_H */
- SHAR_EOF
- chmod 0664 libsipp/shaders.h ||
- echo 'restore of libsipp/shaders.h failed'
- Wc_c="`wc -c < 'libsipp/shaders.h'`"
- test 4808 -eq "$Wc_c" ||
- echo 'libsipp/shaders.h: original size 4808, current size' "$Wc_c"
- fi
- true || echo 'restore of libsipp/sipp.h failed'
- echo End of part 4, continue with part 5
- 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...
-