home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / graphics / ftpovstc / addon0.c < prev    next >
Text File  |  1994-07-24  |  36KB  |  15 lines

  1. /******************************************************************************  ATTENTION!!!**  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL*  POV-RAY 2.2 DISTRIBUTION!!!**  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 1.1),*  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!**  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h**  The additional modules were written by Dieter Bayer.**  Send comments, suggestions, bugs, ideas ... to:**  dieter@cip.e-technik.uni-erlangen.de**  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif**  The vista projection was taken from:**    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective*    Projection Image", New Advances in Computer Graphics, Proceedings*    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), *    Springer, ..., pp. 549-560**  The idea for the light buffer was taken from:**    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16******************************************************************************//******************************************************************************  addon0.c**  This module was written by Dieter Bayer.**  This module contains functions for initialisation, statistics, previewing,*  and other gegeneral purposes.**  01.03.1994 : Creation**  29.04.1994 : Version 2.0*******************************************************************************/#include <time.h>#include "frame.h"#include "vector.h"#include "povproto.h"#include "addon.h"#ifdef DB_CODE#define RED 0#define GREEN 1#define BLUE 2#define NUMBER_OF_TYPES      19#define TYPE_BICUBIC_PATCH    0#define TYPE_BLOB             1#define TYPE_BOX              2#define TYPE_CONE             3#define TYPE_CSG_INTERSECTION 4#define TYPE_CSG_MERGE        5#define TYPE_CSG_UNION        6#define TYPE_DISC             7#define TYPE_ELLIPSOID        8#define TYPE_HEIGHT_FIELD     9#define TYPE_LIGHT_SOURCE    10#define TYPE_PLANE           11#define TYPE_POLY            12#define TYPE_POLYGON         13#define TYPE_QUADRIC         14#define TYPE_SMOOTH_TRIANGLE 15#define TYPE_SPHERE          16#define TYPE_TRIANGLE        17#define TYPE_UNKNOWN         18#define NUMBER_OF_FLAGS     7#define FLAG_SUM            0#define FLAG_INFINITE       1#define FLAG_USED_IN_CSG    2#define FLAG_BOUNDED        3#define FLAG_CLIPPED        4#define FLAG_BOUND_OBJECT   5#define FLAG_CLIP_OBJECT    6/****************************************************************************** External variables******************************************************************************/extern FRAME Frame;extern unsigned int Options;extern METHODS Ellipsoid_Methods;extern METHODS Sphere_Methods;extern time_t tstart, tstop;extern int Use_Slabs;extern unsigned long Quality_Flags;extern METHODS Bicubic_Patch_Methods;extern METHODS Blob_Methods;extern METHODS Box_Methods;extern METHODS Cone_Methods;extern METHODS Csg_Height_Field_Methods;extern METHODS CSG_Intersection_Methods;extern METHODS CSG_Merge_Methods;extern METHODS CSG_Union_Methods;extern METHODS Disc_Methods;extern METHODS Ellipsoid_Methods;extern METHODS Height_Field_Methods;extern METHODS Light_Source_Methods;extern METHODS Plane_Methods;extern METHODS Poly_Methods;extern METHODS Quadric_Methods;extern METHODS Smooth_Triangle_Methods;extern METHODS Sphere_Methods;extern METHODS Triangle_Methods;extern PROJECT_TREE_NODE *Root_Vista;extern size_t Mem_Polygon;/****************************************************************************** Global variables******************************************************************************/unsigned int Extended_Options = 0;/* Amount of memory occupied by the vista buffer and light buffers */size_t Mem_Vista_Buffer  = 0;size_t Mem_Light_Buffers = 0;size_t Allocated_Memory  = 0;/****************************************************************************** Static variables******************************************************************************/static int Point_Counter;static DBL time_used1, time_used2;static long counter[NUMBER_OF_TYPES][NUMBER_OF_FLAGS];/****************************************************************************** Static functions******************************************************************************/static int Get_Object_Type PARAMS((OBJECT *Object));static void Print_Object_Info PARAMS((int type));static void Get_Object_Stats PARAMS((OBJECT *Object, int Csg, int Bound_Object, int Clip_Object));static void Print_Object_Stats PARAMS((void));static void Draw_Projection PARAMS((PROJECT *Project, int color));static void Draw_Vista PARAMS((PROJECT_TREE_NODE *Tree));/******************************************************************************* FUNCTION      : VB_malloc** ARGUMENTS     : size   - Amount of memory to allocate** MODIFIED ARGS : none** RETURN VALUE  : void * - Pointer at allocated memory** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Allocate memory for the vista buffer and keep track of the memory allocated.** CHANGES**   -*******************************************************************************/void *VB_malloc(size)size_t size;{  Allocated_Memory += size;  Mem_Vista_Buffer += size;  return(malloc(size));}/******************************************************************************* FUNCTION      : LB_malloc** ARGUMENTS     : size   - Amount of memory to allocate** MODIFIED ARGS : none** RETURN VALUE  : void * - Pointer at allocated memory** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Allocate memory for the light buffer and keep track of the memory allocated.** CHANGES**   -*******************************************************************************/void *LB_malloc(size)size_t size;{  Allocated_Memory += size;  Mem_Light_Buffers += size;  return(malloc(size));}/******************************************************************************* FUNCTION      : new_malloc** ARGUMENTS     : size   - Amount of memory to allocate** MODIFIED ARGS : none** RETURN VALUE  : void * - Pointer at allocated memory** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Allocate memory and keep track of the memory allocated.**   Use instead of malloc when allocating memory!** CHANGES**   -*******************************************************************************/void *new_malloc(size)size_t size;{  Allocated_Memory += size;  return(malloc(size));}/******************************************************************************* FUNCTION      : new_free** ARGUMENTS     : pointer - Memory to free*                 size    - Amount of memory that will be freed** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Free memory and keep track of the memory allocated.**   Use instead of free when freeing memory!** CHANGES**   -*******************************************************************************/void new_free(pointer, size)void *pointer;size_t size;{  Allocated_Memory -= size;  free(pointer);}/******************************************************************************* FUNCTION      : Init_Additional_1** ARGUMENTS     : none** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Additional initialisation before boundind slabs are build.**   Split union objects and pass bounding objects to the children if they*   aren't already bounded (most bounding objects will be removed later).** CHANGES**   -*******************************************************************************/void Init_Additionals_1(){  int children_finite;  long count;  DBL Volume;  OBJECT **Object, *Sib, *Last_Sib, *Bound;  Print_Quadric_Stats();  /* If slabs are not used --> vista and light buffer can't be used */  if (!Use_Slabs)  {    Extended_Options &= ~USE_VISTA_BUFFER;    Extended_Options &= ~USE_LIGHT_BUFFER;  }  /* We don't use shadows so we don't need a light buffer */  if (!(Quality_Flags & Q_SHADOW))  {    Extended_Options &= ~USE_LIGHT_BUFFER;  }  if ((Extended_Options & USE_SPLIT_FINITE_UNIONS) ||      (Extended_Options & USE_SPLIT_INFINITE_UNIONS))  {    START_TIME    Recompute_Bboxes();    fprintf(stderr, "Splitting union objects");    Begin_Point();    count = 0;    for (Object = &Frame.Objects; (*Object) != NULL; )    {      children_finite = FALSE;      if (Extended_Options & USE_SPLIT_INFINITE_UNIONS)      {    /* +usi option is used, i.e. split all unions */    children_finite = TRUE;      }      else      {    /* Check, if all children of the union have finite bounding boxes */    if ((*Object)->Methods == &CSG_Union_Methods)    {      children_finite = TRUE;      for (Sib = ((CSG *)(*Object))->Children; Sib != NULL; Sib = Sib->Sibling)      {        BOUNDS_VOLUME(Volume, Sib->Bounds);        if (Volume > INFINITE_VOLUME) children_finite = FALSE;      }    }      }      /* Split union object, if all children are finite (or tracing slows     down!) and the union isn't clipped */      if (((*Object)->Methods == &CSG_Union_Methods) &&      ((*Object)->Clip == NULL) && (children_finite))      {    count++;    Print_Point(POINT_MOD);    Bound = (*Object)->Bound;    if ((Sib = ((CSG *)(*Object))->Children) != NULL)    {      for (; Sib != NULL; Sib = Sib->Sibling)      {        /* Set child's bound to father's bound (some peolpe use objects           that don't fit in the bounding object. Argh!!!           The question is: should this be done or not?) */        if (Sib->Bound == NULL) Sib->Bound = Bound;        Last_Sib = Sib;      }      Last_Sib->Sibling = (*Object)->Sibling;      (*Object) = ((CSG *)(*Object))->Children;    }    else    {      (*Object) = (*Object)->Sibling;    }      }      else      {    Object = &(*Object)->Sibling;      }    }    fprintf(stderr, "(%ld split)", count);    End_Point();    if (count > 0)    {      /* Just to be sure */      Recompute_Bboxes();    }    STOP_TIME    time_used1 = TIME_ELAPSED  }  else  {    Recompute_Bboxes();  }}/******************************************************************************* FUNCTION      : Init_Additionals_2** ARGUMENTS     : none** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Additional initialisation after boundind slabs have been build.**   - Project objects onto the screen.*   - Build the light buffers.*   - Remove all unnecessary bounding objects.*   - Print a statistic of the scene.** CHANGES**   -*******************************************************************************/void Init_Additionals_2(){  DBL time_used;  if ((Extended_Options & USE_VISTA_BUFFER) ||      (Extended_Options & USE_LIGHT_BUFFER))  {    START_TIME    if (Use_Slabs)    {      Init_Project_Tree_Queues();      if (Extended_Options & USE_VISTA_BUFFER)      {    Init_View_Coordinates();    Build_Vista_Tree();      }      if (Extended_Options & USE_LIGHT_BUFFER)      {    Build_Light_Buffers();      }    }    Remove_Unnecessary_Bounds();    Print_Object_Stats();    STOP_TIME    time_used2 = TIME_ELAPSED    time_used = time_used1 + time_used2;    fprintf(stderr, "Time Overhead : %.0f seconds\n", time_used);  }  else  {    Remove_Unnecessary_Bounds();  }}/******************************************************************************* FUNCTION      : Get_Object_Type** ARGUMENTS     : Object - Point to an object** MODIFIED ARGS : none** RETURN VALUE  : int - Type of object** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Returns the type of an object.** CHANGES**   -*******************************************************************************/static int Get_Object_Type(Object)OBJECT *Object;{  if (Object->Methods == &Bicubic_Patch_Methods)    return(TYPE_BICUBIC_PATCH);  if (Object->Methods == &Blob_Methods)             return(TYPE_BLOB);  if (Object->Methods == &Box_Methods)              return(TYPE_BOX);  if (Object->Methods == &Cone_Methods)             return(TYPE_CONE);  if (Object->Methods == &CSG_Intersection_Methods) return(TYPE_CSG_INTERSECTION);  if (Object->Methods == &CSG_Merge_Methods)        return(TYPE_CSG_MERGE);  if (Object->Methods == &CSG_Union_Methods)        return(TYPE_CSG_UNION);  if (Object->Methods == &Disc_Methods)             return(TYPE_DISC);  if (Object->Methods == &Ellipsoid_Methods)        return(TYPE_ELLIPSOID);  if (Object->Methods == &Height_Field_Methods)     return(TYPE_HEIGHT_FIELD);  if (Object->Methods == &Csg_Height_Field_Methods) return(TYPE_HEIGHT_FIELD);  if (Object->Methods == &Light_Source_Methods)     return(TYPE_LIGHT_SOURCE);  if (Object->Methods == &Plane_Methods)            return(TYPE_PLANE);  if (Object->Methods == &Poly_Methods)             return(TYPE_POLY);  if (Object->Methods == &Quadric_Methods)          return(TYPE_QUADRIC);  if (Object->Methods == &Smooth_Triangle_Methods)  return(TYPE_SMOOTH_TRIANGLE);  if (Object->Methods == &Sphere_Methods)           return(TYPE_SPHERE);  if (Object->Methods == &Triangle_Methods)         return(TYPE_TRIANGLE);  return(TYPE_UNKNOWN);}/******************************************************************************* FUNCTION      : Get_Object_Stats** ARGUMENTS     : Object       - object*                 csg          - Flag if inside a csg object*                 bound_object - Flag if object is part of a bounding object*                 clip_object  - Flag if object is part of a clipping object** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Get some information about an object and add it to the scene statistic.** CHANGES**   -*******************************************************************************/static void Get_Object_Stats(Object, csg, bound_object, clip_object)OBJECT *Object;int csg, bound_object, clip_object;{  int bounded, clipped, infinite, type;  DBL Volume;  OBJECT *Sib;  if (Object == NULL)    return;  /* Bounded/Clipped object? */  bounded = (Object->Bound != NULL);  clipped = (Object->Clip != NULL);  /* Don't care about infinite objects if they are inside     a CSG object or used as clipping/bounding objects */  if (csg || bound_object || clip_object)  {    infinite = FALSE;  }  else  {    /* Infinte object? */    BOUNDS_VOLUME(Volume, Object->Bounds);    infinite = (Volume > INFINITE_VOLUME);  }  /* Get object type */  type = Get_Object_Type(Object);  /* Count bounding objects */  if (Object->Bound != NULL)  {    for (Sib = Object->Bound; Sib != NULL; Sib = Sib->Sibling)    {      Get_Object_Stats(Sib, csg, TRUE, clip_object);    }  }  /* Count clipping objects */  if (Object->Clip != NULL)  {    for (Sib = Object->Clip; Sib != NULL; Sib = Sib->Sibling)    {      Get_Object_Stats(Sib, csg, bound_object, TRUE);    }  }  if (Object->Type & COMPOUND_OBJECT)  {    if (Object->Type & LIGHT_SOURCE_OBJECT)    {      /* Count light source */      counter[type][FLAG_SUM]++;      Get_Object_Stats(((LIGHT_SOURCE *)Object)->Children, csg, bound_object, clip_object);    }    else    {      /* Count CSG object */      counter[type][FLAG_SUM]++;      if (csg)            counter[type][FLAG_USED_IN_CSG]++;      if (infinite)       counter[type][FLAG_INFINITE]++;      if (bounded)        counter[type][FLAG_BOUNDED]++;      if (clipped)        counter[type][FLAG_CLIPPED]++;      if (bound_object)   counter[type][FLAG_BOUND_OBJECT]++;      if (clip_object)    counter[type][FLAG_CLIP_OBJECT]++;      for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)      {    Get_Object_Stats(Sib, TRUE, bound_object, clip_object);      }    }  }  else  {    /* Count the primitive object */    counter[type][FLAG_SUM]++;    if (csg)            counter[type][FLAG_USED_IN_CSG]++;    if (infinite)       counter[type][FLAG_INFINITE]++;    if (bounded)        counter[type][FLAG_BOUNDED]++;    if (clipped)        counter[type][FLAG_CLIPPED]++;    if (bound_object)   counter[type][FLAG_BOUND_OBJECT]++;    if (clip_object)    counter[type][FLAG_CLIP_OBJECT]++;  }}/******************************************************************************* FUNCTION      : Print_Object_Info** ARGUMENTS     : type - Object's type** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Print the statistics of one type of object.** CHANGES**   -*******************************************************************************/static void Print_Object_Info(type)int type;{  fprintf(stderr, " : %5ld %5ld %5ld %5ld %5ld   %5ld   %5ld\n",    counter[type][FLAG_SUM],    counter[type][FLAG_USED_IN_CSG],    counter[type][FLAG_INFINITE],    counter[type][FLAG_BOUND_OBJECT],    counter[type][FLAG_CLIP_OBJECT],    counter[type][FLAG_BOUNDED],    counter[type][FLAG_CLIPPED]);}/******************************************************************************* FUNCTION      : Print_Object_Stats** ARGUMENTS     : none** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Collect and print a statistic about the scene.** CHANGES**   -*******************************************************************************/static void Print_Object_Stats(){  int i, j;  long sum1, sum2, sum3, sum4, sum5, sum6, sum7, frame_level;  OBJECT *Sib;  /* Initialize counters */  for (i = 0; i < NUMBER_OF_TYPES; i++)  {    for (j = 0; j < NUMBER_OF_FLAGS; j++)    {      counter[i][j] = 0;    }  }  frame_level = 0;  for (Sib = Frame.Objects; Sib != NULL; Sib = Sib->Sibling)  {    if (Sib->Type & LIGHT_SOURCE_OBJECT)    {      if (((LIGHT_SOURCE *)Sib)->Children != NULL)      {    frame_level++;      }    }    else    {      frame_level++;    }    Get_Object_Stats(Sib, FALSE, FALSE, FALSE);  }  sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = 0;  for (i = 0; i < NUMBER_OF_TYPES; i++)  {    sum1 += counter[i][FLAG_SUM];    sum2 += counter[i][FLAG_USED_IN_CSG];    sum3 += counter[i][FLAG_INFINITE];    sum4 += counter[i][FLAG_BOUND_OBJECT];    sum5 += counter[i][FLAG_CLIP_OBJECT];    sum6 += counter[i][FLAG_BOUNDED];    sum7 += counter[i][FLAG_CLIPPED];  }  fprintf(stderr, "                  Sum   CSG Infin Bound  Clip Bounded Clipped\n");  fprintf(stderr, "Blob         "); Print_Object_Info(TYPE_BLOB);  fprintf(stderr, "Box          "); Print_Object_Info(TYPE_BOX);  fprintf(stderr, "Cone/Cylinder"); Print_Object_Info(TYPE_CONE);  fprintf(stderr, "Ellipsoid    "); Print_Object_Info(TYPE_ELLIPSOID);  fprintf(stderr, "Heightfield  "); Print_Object_Info(TYPE_HEIGHT_FIELD);  fprintf(stderr, "Sphere       "); Print_Object_Info(TYPE_SPHERE);  fprintf(stderr, "Bezierpatch  "); Print_Object_Info(TYPE_BICUBIC_PATCH);  fprintf(stderr, "Disc         "); Print_Object_Info(TYPE_DISC);  fprintf(stderr, "Tri (Phong)  "); Print_Object_Info(TYPE_SMOOTH_TRIANGLE);  fprintf(stderr, "Tri (Flat)   "); Print_Object_Info(TYPE_TRIANGLE);  fprintf(stderr, "Plane        "); Print_Object_Info(TYPE_PLANE);  fprintf(stderr, "Quartic/Poly "); Print_Object_Info(TYPE_POLY);  fprintf(stderr, "Quadric      "); Print_Object_Info(TYPE_QUADRIC);  fprintf(stderr, "CSG-ISect    "); Print_Object_Info(TYPE_CSG_INTERSECTION);  fprintf(stderr, "CSG-Merge    "); Print_Object_Info(TYPE_CSG_MERGE);  fprintf(stderr, "CSG-Union    "); Print_Object_Info(TYPE_CSG_UNION);  fprintf(stderr, "Lightsource  "); Print_Object_Info(TYPE_LIGHT_SOURCE);  fprintf(stderr, "Grand totals  : %5ld %5ld %5ld %5ld %5ld   %5ld   %5ld\n", sum1, sum2, sum3, sum4, sum5, sum6, sum7);
  2.   fprintf(stderr, "Root objects  : %5ld\n\n", frame_level);/*
  3.   fprintf(stderr, "Scene contains %ld frame level objects.\n", frame_level);*/  /* Print amount of allocated memory */  if (Mem_Vista_Buffer)    fprintf(stderr, "Vista Buffer  : %.2f KBytes\n", (DBL)(Mem_Vista_Buffer) / 1024.0);  if (Mem_Light_Buffers)    fprintf(stderr, "Light Buffer  : %.2f KBytes\n", (DBL)(Mem_Light_Buffers) / 1024.0);/*  if (Allocated_Memory)    fprintf(stderr, "RAM Overhead  : %.2f KBytes\n", (DBL)Allocated_Memory / 1024.0);*/
  4. }/******************************************************************************* FUNCTION      : Clip_Polygon** ARGUMENTS     : Points             - polygon's points*                 PointCnt           - Number of points in polygon*                 VX1, VY1, VX2, VY1 - Normal vectors of the clipping planes*                 DX1, DY1, DX2, DY2 - Distances of the clipping planes from*                                      the origin** MODIFIED ARGS : Points, PointCnt** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Clip polygon at the viewing pyramid define by the normal vectors*   VX1, VX2, VY1, VY2 and the distances DX1, DX2, DY1, DY2.** CHANGES**   -*******************************************************************************/void Clip_Polygon (Points, PointCnt, VX1, VX2, VY1, VY2, DX1, DX2, DY1, DY2)VECTOR *Points;int *PointCnt;VECTOR *VX1, *VX2, *VY1, *VY2;DBL DX1, DX2, DY1, DY2;{  DBL aktd, pred, fird, k;  VECTOR aktP, intP, preP, firP, d;  int i, pc;  VECTOR ClipPoints[MAX_CLIP_POINTS];  /********** clip polygon at "left" plane **********/  pc = 0;  firP = Points[0];  fird = VX1->x * firP.x + VX1->y * firP.y + VX1->z * firP.z - DX1;  if (fird <= 0.0)    ClipPoints[pc++] = firP;  aktP = preP = firP;  aktd = pred = fird;  for (i = 1; i < *PointCnt; i++)  {    aktP = Points[i];    aktd = VX1->x * aktP.x + VX1->y * aktP.y + VX1->z * aktP.z - DX1;    if (((aktd < 0.0) && (pred > 0.0)) || ((aktd > 0.0) && (pred < 0.0)))    {      d.x = preP.x - aktP.x;      d.y = preP.y - aktP.y;      d.z = preP.z - aktP.z;      k = -aktd / (VX1->x * d.x + VX1->y * d.y + VX1->z * d.z);      intP.x = aktP.x + k * d.x;      intP.y = aktP.y + k * d.y;      intP.z = aktP.z + k * d.z;      ClipPoints[pc++] = intP;    }    if (aktd <= 0.0)      ClipPoints[pc++] = aktP;    preP = aktP;    pred = aktd;  }  if (((fird < 0.0) && (aktd > 0.0)) || ((fird > 0.0) && (aktd < 0.0)))  {    d.x = firP.x - aktP.x;    d.y = firP.y - aktP.y;    d.z = firP.z - aktP.z;    k = -aktd / (VX1->x * d.x + VX1->y * d.y + VX1->z * d.z);    intP.x = aktP.x + k * d.x;    intP.y = aktP.y + k * d.y;    intP.z = aktP.z + k * d.z;    ClipPoints[pc++] = intP;  }  for (i = 0; i < pc; i++)    Points[i] = ClipPoints[i];  if ((*PointCnt = pc) == 0)    return;  /********** clip polygon at "right" plane **********/  pc = 0;  firP = Points[0];  fird = VX2->x * firP.x + VX2->y * firP.y + VX2->z * firP.z - DX2;  if (fird <= 0.0)    ClipPoints[pc++] = firP;  aktP = preP = firP;  aktd = pred = fird;  for (i = 1; i < *PointCnt; i++)  {    aktP = Points[i];    aktd = VX2->x * aktP.x + VX2->y * aktP.y + VX2->z * aktP.z - DX2;    if (((aktd < 0.0) && (pred > 0.0)) || ((aktd > 0.0) && (pred < 0.0)))    {      d.x = preP.x - aktP.x;      d.y = preP.y - aktP.y;      d.z = preP.z - aktP.z;            k = -aktd / (VX2->x * d.x + VX2->y * d.y + VX2->z * d.z);            intP.x = aktP.x + k * d.x;      intP.y = aktP.y + k * d.y;      intP.z = aktP.z + k * d.z;      ClipPoints[pc++] = intP;    }    if (aktd <= 0.0)      ClipPoints[pc++] = aktP;    preP = aktP;    pred = aktd;  }  if (((fird < 0.0) && (aktd > 0.0)) || ((fird > 0.0) && (aktd < 0.0)))  {    d.x = firP.x - aktP.x;    d.y = firP.y - aktP.y;    d.z = firP.z - aktP.z;    k = -aktd / (VX2->x * d.x + VX2->y * d.y + VX2->z * d.z);    intP.x = aktP.x + k * d.x;    intP.y = aktP.y + k * d.y;    intP.z = aktP.z + k * d.z;    ClipPoints[pc++] = intP;  }  for (i = 0; i < pc; i++)    Points[i] = ClipPoints[i];  if ((*PointCnt = pc) == 0)    return;  /********** clip polygon at "bottom" plane **********/  pc = 0;  firP = Points[0];  fird = VY1->x * firP.x + VY1->y * firP.y + VY1->z * firP.z - DY1;  if (fird <= 0.0)    ClipPoints[pc++] = firP;  aktP = preP = firP;  aktd = pred = fird;  for (i = 1; i < *PointCnt; i++)  {    aktP = Points[i];    aktd = VY1->x * aktP.x + VY1->y * aktP.y + VY1->z * aktP.z - DY1;    if (((aktd < 0.0) && (pred > 0.0)) || ((aktd > 0.0) && (pred < 0.0)))    {      d.x = preP.x - aktP.x;      d.y = preP.y - aktP.y;      d.z = preP.z - aktP.z;            k = -aktd / (VY1->x * d.x + VY1->y * d.y + VY1->z * d.z);            intP.x = aktP.x + k * d.x;      intP.y = aktP.y + k * d.y;      intP.z = aktP.z + k * d.z;      ClipPoints[pc++] = intP;    }    if (aktd <= 0.0)      ClipPoints[pc++] = aktP;    preP = aktP;    pred = aktd;  }  if (((fird < 0.0) && (aktd > 0.0)) || ((fird > 0.0) && (aktd < 0.0)))  {    d.x = firP.x - aktP.x;    d.y = firP.y - aktP.y;    d.z = firP.z - aktP.z;    k = -aktd / (VY1->x * d.x + VY1->y * d.y + VY1->z * d.z);    intP.x = aktP.x + k * d.x;    intP.y = aktP.y + k * d.y;    intP.z = aktP.z + k * d.z;    ClipPoints[pc++] = intP;  }  for (i = 0; i < pc; i++)    Points[i] = ClipPoints[i];  if ((*PointCnt = pc) == 0)    return;  /********** clip polygon at "top" plane **********/  pc = 0;  firP = Points[0];  fird = VY2->x * firP.x + VY2->y * firP.y + VY2->z * firP.z - DY2;  if (fird <= 0.0)    ClipPoints[pc++] = firP;  aktP = preP = firP;  aktd = pred = fird;  for (i = pc = 0; i < *PointCnt; i++)  {    aktP = Points[i];    aktd = VY2->x * aktP.x + VY2->y * aktP.y + VY2->z * aktP.z - DY2;    if (((aktd < 0.0) && (pred > 0.0)) || ((aktd > 0.0) && (pred < 0.0)))    {      d.x = preP.x - aktP.x;      d.y = preP.y - aktP.y;      d.z = preP.z - aktP.z;            k = -aktd / (VY2->x * d.x + VY2->y * d.y + VY2->z * d.z);           intP.x = aktP.x + k * d.x;      intP.y = aktP.y + k * d.y;      intP.z = aktP.z + k * d.z;            ClipPoints[pc++] = intP;    }    if (aktd <= 0.0)      ClipPoints[pc++] = aktP;    preP = aktP;    pred = aktd;  }  if (((fird < 0.0) && (aktd > 0.0)) || ((fird > 0.0) && (aktd < 0.0)))  {    d.x = firP.x - aktP.x;    d.y = firP.y - aktP.y;    d.z = firP.z - aktP.z;    k = -aktd / (VY2->x * d.x + VY2->y * d.y + VY2->z * d.z);    intP.x = aktP.x + k * d.x;    intP.y = aktP.y + k * d.y;    intP.z = aktP.z + k * d.z;    ClipPoints[pc++] = intP;  }  for (i = 0; i < pc; i++)    Points[i] = ClipPoints[i];  *PointCnt = pc;}/******************************************************************************* FUNCTION      : MInvers** ARGUMENTS     : m - matrix to invert*                 r - inverted matrix** MODIFIED ARGS : r** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Invert a 4x4 matrix.** CHANGES**   -*******************************************************************************/void MInvers(r, m)MATRIX *r, *m;{  DBL d00, d01, d02, d03;  DBL d10, d11, d12, d13;  DBL d20, d21, d22, d23;  DBL d30, d31, d32, d33;  DBL m00, m01, m02, m03;  DBL m10, m11, m12, m13;  DBL m20, m21, m22, m23;  DBL m30, m31, m32, m33;  DBL D;  m00 = (*m)[0][0];  m01 = (*m)[0][1];  m02 = (*m)[0][2];  m03 = (*m)[0][3];  m10 = (*m)[1][0];  m11 = (*m)[1][1];  m12 = (*m)[1][2];  m13 = (*m)[1][3];  m20 = (*m)[2][0];  m21 = (*m)[2][1];  m22 = (*m)[2][2];  m23 = (*m)[2][3];  m30 = (*m)[3][0];  m31 = (*m)[3][1];  m32 = (*m)[3][2];  m33 = (*m)[3][3];  d00 = m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m31*m22*m13 - m32*m23*m11 - m33*m21*m12;  d01 = m10*m22*m33 + m12*m23*m30 + m13*m20*m32 - m30*m22*m13 - m32*m23*m10 - m33*m20*m12;  d02 = m10*m21*m33 + m11*m23*m30 + m13*m20*m31 - m30*m21*m13 - m31*m23*m10 - m33*m20*m11;  d03 = m10*m21*m32 + m11*m22*m30 + m12*m20*m31 - m30*m21*m12 - m31*m22*m10 - m32*m20*m11;  d10 = m01*m22*m33 + m02*m23*m31 + m03*m21*m32 - m31*m22*m03 - m32*m23*m01 - m33*m21*m02;  d11 = m00*m22*m33 + m02*m23*m30 + m03*m20*m32 - m30*m22*m03 - m32*m23*m00 - m33*m20*m02;  d12 = m00*m21*m33 + m01*m23*m30 + m03*m20*m31 - m30*m21*m03 - m31*m23*m00 - m33*m20*m01;  d13 = m00*m21*m32 + m01*m22*m30 + m02*m20*m31 - m30*m21*m02 - m31*m22*m00 - m32*m20*m01;  d20 = m01*m12*m33 + m02*m13*m31 + m03*m11*m32 - m31*m12*m03 - m32*m13*m01 - m33*m11*m02;  d21 = m00*m12*m33 + m02*m13*m30 + m03*m10*m32 - m30*m12*m03 - m32*m13*m00 - m33*m10*m02;  d22 = m00*m11*m33 + m01*m13*m30 + m03*m10*m31 - m30*m11*m03 - m31*m13*m00 - m33*m10*m01;  d23 = m00*m11*m32 + m01*m12*m30 + m02*m10*m31 - m30*m11*m02 - m31*m12*m00 - m32*m10*m01;  d30 = m01*m12*m23 + m02*m13*m21 + m03*m11*m22 - m21*m12*m03 - m22*m13*m01 - m23*m11*m02;  d31 = m00*m12*m23 + m02*m13*m20 + m03*m10*m22 - m20*m12*m03 - m22*m13*m00 - m23*m10*m02;  d32 = m00*m11*m23 + m01*m13*m20 + m03*m10*m21 - m20*m11*m03 - m21*m13*m00 - m23*m10*m01;  d33 = m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m21*m12*m00 - m22*m10*m01;  D = m00*d00 - m01*d01 + m02*d02 - m03*d03;  if (fabs(D) < EPSILON)    Fatal_Error("Singular matrix in MInvers.\n");  (*r)[0][0] = +d00/D; (*r)[0][1] = -d10/D;  (*r)[0][2] = +d20/D; (*r)[0][3] = -d30/D;  (*r)[1][0] = -d01/D; (*r)[1][1] = +d11/D;  (*r)[1][2] = -d21/D; (*r)[1][3] = +d31/D;  (*r)[2][0] = +d02/D; (*r)[2][1] = -d12/D;  (*r)[2][2] = +d22/D; (*r)[2][3] = -d32/D;  (*r)[3][0] = -d03/D; (*r)[3][1] = +d13/D;  (*r)[3][2] = -d23/D; (*r)[3][3] = +d33/D;}/******************************************************************************* FUNCTION      : Fatal_Error** ARGUMENTS     : str - String to print to stderr** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Print an error message and leave program.** CHANGES**   -*******************************************************************************/void Fatal_Error(str)char *str;{  fputs(str, stderr);  exit(1);}/******************************************************************************* FUNCTION      : Fatal_MAError** ARGUMENTS     : str - String to print to stderr after out of memory message** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Print an error message and leave program. Call if memory*   allocation fails.** CHANGES**   -*******************************************************************************/void Fatal_MAError(str)char *str;{  fprintf(stderr, "Out of memory. Cannot allocate %s.\n", str);  exit (1);}/******************************************************************************* FUNCTION      : Begin_Point** ARGUMENTS     : none** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Print points to stderr and initialize point counter.** CHANGES**   -*******************************************************************************/void Begin_Point(){  fprintf(stderr, "...");  Point_Counter = 0;}/******************************************************************************* FUNCTION      : Print_Point** ARGUMENTS     : Repeat - Determines after how many calls a point will be printed** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Print points to stderr.** CHANGES**   -*******************************************************************************/void Print_Point(Repeat)int Repeat;{  if ((Point_Counter % Repeat) == 0)    fprintf(stderr, ".");  Point_Counter++;}/******************************************************************************* FUNCTION      : End_Point** ARGUMENTS     : none** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Print newline to stderr.** CHANGES**   -*******************************************************************************/void End_Point(){  fprintf(stderr, "\n");}/******************************************************************************* FUNCTION      : Draw_Projection** ARGUMENTS     : Project - projection to draw*                 color   - Color to be used** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Draws a projection in the specified color.** CHANGES**   -*******************************************************************************/static void Draw_Projection(Project, color)PROJECT *Project;int color;{
  5. }
  6.  
  7. /*
  8. {  int x, y, x1, x2, y1, y2;  unsigned short int r, g, b;
  9.   switch (color)  {    case RED   : r = 255; g = b = 0; break;    case GREEN : g = 255; r = b = 0; break;    case BLUE  : b = 255; r = g = 0; break;    default    : r = g = b = 255;  }  x1 = Project->x1;  x2 = Project->x2;  y1 = Project->y1;  y2 = Project->y2;  if ((x1 <= x2) && (y1 <= y2))  {    if (x1 < 0) x1 = 0;    if (x2 < 0) x2 = 0;    if (y1 < 0) y1 = 0;    if (y2 < 0) y2 = 0;    if (x1 >= Frame.Screen_Width)  x1 = Frame.Screen_Width - 1;    if (x2 >= Frame.Screen_Width)  x2 = Frame.Screen_Width - 1;    if (y1 >= Frame.Screen_Height) y1 = Frame.Screen_Height - 1;    if (y2 >= Frame.Screen_Height) y2 = Frame.Screen_Height - 1;    for (x = x1; x <= x2; x++)    {      display_plot (x, y1, r, g, b);      display_plot (x, y2, r, g, b);    }    for (y = y1; y <= y2; y++)    {      display_plot (x1, y, r, g, b);      display_plot (x2, y, r, g, b);    }  }}*//******************************************************************************* FUNCTION      : Draw_Vista** ARGUMENTS     : Tree - current node/leaf in the vista tree** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Draws recursively all projections of subnodes in the current node.** CHANGES**   -*******************************************************************************/static void Draw_Vista(Tree)PROJECT_TREE_NODE *Tree;{/*
  10.   unsigned short i;  PROJECT_TREE_LEAF *Leaf;  if (Tree->is_leaf)  {    Leaf = (PROJECT_TREE_LEAF *)Tree;    if (Leaf->Object->Type & COMPOUND_OBJECT)    {      Draw_Projection(&Leaf->Project, BLUE);    }    else    {      Draw_Projection(&Leaf->Project, RED);    }  }  else  {    for (i = 0; i < Tree->Entries; i++)    {      Draw_Vista(Tree->Entry[i]);    }  }  /* draw bounding object's vista *//*  Draw_Projection(&Tree->Project, GREEN);*/*/
  11. }/******************************************************************************* FUNCTION      : Draw_Vista_Tree** ARGUMENTS     : none** MODIFIED ARGS : none** RETURN VALUE  : none** AUTHOR        : Dieter Bayer, May, 1994** DESCRIPTION**   Draw the vista tree.** CHANGES**   -*******************************************************************************/void Draw_Vista_Tree(){/*
  12.   if (Extended_Options & USE_VISTA_BUFFER)  {
  13. /*    Draw_Vista(Root_Vista);  */
  14.   }
  15. */}#endif