home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / utils / graphtal.lzh / Graphtal.Amiga / WireDevice.C < prev    next >
C/C++ Source or Header  |  1992-11-17  |  5KB  |  223 lines

  1. /*
  2.  * WireDevice.C - wire frame device driver.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     University of Berne, Switzerland
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified, and redistributed
  9.  * provided that this copyright notice is preserved on all copies.
  10.  *
  11.  * You may not distribute this software, in whole or in part, as part of
  12.  * any commercial product without the express consent of the authors.
  13.  *
  14.  * There is no warranty or other guarantee of fitness of this software
  15.  * for any purpose.  It is provided solely "as is".
  16.  *
  17.  */
  18.  
  19. #include "WireDevice.h"
  20. #include "Polygon.h"
  21. #include "Sphere.h"
  22.  
  23. static const int defaultConeResolution = 3;
  24. static const int defaultSphereResolution = 4;
  25.  
  26. //___________________________________________________________ WireDevice
  27.  
  28. WireDevice::WireDevice(BaseWindow* window, Options* options)
  29. : DeviceDriver(options), w(window), polys(NULL)
  30. {
  31.   coneResolution = (theOptions->coneResolution <= 0) 
  32.     ? defaultConeResolution
  33.     : theOptions->coneResolution;
  34.   sphereResolution = (theOptions->sphereResolution <= 0) 
  35.     ? defaultSphereResolution
  36.     : theOptions->sphereResolution;
  37.  
  38.   /*
  39.    * Make up table for cone generation.
  40.    */
  41.   sintable = new real[coneResolution];
  42.   costable = new real[coneResolution];
  43.  
  44.   for (register int i=0; i<coneResolution; i++) {
  45.     real alpha = (2*M_PI*i)/coneResolution;
  46.  
  47.     sintable[i] = sin(alpha);
  48.     costable[i] = cos(alpha);
  49.   }
  50.   top = new Vector[coneResolution];
  51.   bottom = new Vector[coneResolution];
  52.  
  53.   /*
  54.    * Generate unit sphere.
  55.    */
  56.   unitSphere = Sphere::tesselation(Vector(0,0,0), 1, sphereResolution);
  57. }
  58.  
  59. WireDevice::~WireDevice()
  60. {
  61.   delete [] sintable;
  62.   delete [] costable;
  63.   delete [] top;
  64.   delete [] bottom;
  65.   delete w;
  66.  
  67.   for (register long i=0; i<unitSphere->count(); i++)
  68.     delete unitSphere->item(i);
  69.   delete unitSphere;
  70.  
  71.   StringTable_Iterator macroItr(macroNames);
  72.   while(macroItr.more()){
  73.     PolygonList* polys = (PolygonList*)macroItr.cur_value();
  74.     for (i = 0; i<polys->count(); i++)
  75.       delete polys->item(i);
  76.     delete polys;
  77.     macroItr.next();
  78.   } 
  79. }
  80.  
  81. void WireDevice::begin()
  82. {
  83.   if (!theOptions->autoscale) {
  84.     w->disableBuffering();
  85.     w->setView(theOptions->eye, theOptions->lookat, theOptions->up, 
  86.            theOptions->fov);
  87.   }
  88.   w->open(theOptions->resX, theOptions->resY, "L-System " + LSystemName);
  89.   if (theOptions->autoscale)
  90.     w->writeText("Please wait ...", 
  91.          theOptions->resX/2-40, theOptions->resY/2-5);
  92. }
  93.  
  94. void WireDevice::end(const BoundingBox& b)
  95. {
  96.   char key;
  97.  
  98.   if (theOptions->verbose)
  99.     cerr << "primitives: "<< primitives << '\n';
  100.   if (theOptions->autoscale) {
  101.     w->setView(b, theOptions->up, theOptions->fov);
  102.     w->clear();
  103.   }
  104.   w->flush();
  105.   do {
  106.     key = w->waitForKey();
  107.   } while(key != 'q' && key != 'Q');
  108.   w->close();
  109. }
  110.  
  111. void WireDevice::cylinder(const Vector& p1, const Vector& p2, real r)
  112. {
  113.   cone(p1, r, p2, r);
  114. }
  115.  
  116. void WireDevice::cone(const Vector& p1, real r1, const Vector& p2, real r2)
  117. {
  118.   Vector axis = p2-p1;
  119.  
  120.   /*
  121.    * Degenerated cone?
  122.    */
  123.   if (axis.normalize() == 0)
  124.     return;
  125.  
  126.   Vector u, v;
  127.   
  128.   /*
  129.    * Calculate 2 vectors normal to cone axis and to each other.
  130.    */
  131.   u[0] = -axis[1]; u[1] =  axis[0]; u[2] = 0;
  132.   if (u.normalize() == 0) {
  133.     u[0] = axis[2]; u[1] = 0;  u[2] = -axis[0];
  134.     u.normalize();
  135.   }
  136.   v = axis*u;
  137.  
  138.   Vector d;
  139.   for (register int i=0; i<coneResolution; i++) {
  140.     d = costable[i]*u + sintable[i]*v;
  141.     *(bottom+i) = p1 + d*r1;
  142.     *(top+i)    = p2 + d*r2;   
  143.   }
  144.         
  145.   for (i=0; i<coneResolution; i++) {
  146.     Polygon* p = new Polygon(*(bottom+i), *(top+i), 
  147.                  *(top+((i+1)%coneResolution)), 
  148.                  *(bottom+((i+1)%coneResolution)));
  149.     if (definingMacro)
  150.       polys->append(p);
  151.     else {
  152.       primitives++;
  153.       w->polygon(p);
  154.     }
  155.   }
  156. }
  157.  
  158. void WireDevice::polygon(Polygon* p)
  159. {
  160.   if (definingMacro) 
  161.     polys->append(p);
  162.   else {
  163.     primitives++;
  164.     w->polygon(p);
  165.   }
  166. }
  167.  
  168. void WireDevice::sphere(const Vector& pos, real r)
  169. {
  170.   /*
  171.    * Transform the unit sphere to radius r and position pos.
  172.    */
  173.   for (register long i=0; i<unitSphere->count(); i++) {
  174.     Polygon* p = unitSphere->item(i);
  175.     Polygon* transformedPoly = new Polygon(p->numVertices());
  176.     for (register long j=0; j<p->numVertices(); j++)
  177.       transformedPoly->addVertex(p->vertex(j)*r+pos); 
  178.  
  179.     if (definingMacro)
  180.       polys->append(transformedPoly);
  181.     else {
  182.       primitives++;
  183.       w->polygon(transformedPoly);
  184.     }
  185.   }
  186. }
  187.  
  188. void WireDevice::beginMacro(const rcString& macroName)
  189. {
  190.   definingMacro = 1;
  191.   currentMacroName = macroName;
  192.   polys = new PolygonList(100);
  193. }
  194.  
  195. void WireDevice::endMacro()
  196. {
  197.   definingMacro = 0;
  198.   macroNames.find_and_replace(currentMacroName, polys);
  199.   polys = NULL;
  200. }
  201.  
  202. void WireDevice::executeMacro(const rcString& macroName, 
  203.                   const TransMatrix& tmat)
  204. {
  205.   anyPtr argument;
  206.   if (!macroNames.lookup(macroName, argument))
  207.     Error(ERR_PANIC, "WireDevice::executeMacro: macro " 
  208.                  + macroName + " does not exist");
  209.  
  210.   PolygonList* polyList = (PolygonList*) argument;
  211.   for (register long i=0; i<polyList->count(); i++) {
  212.     Polygon* p = new Polygon(*polyList->item(i));
  213.     p->transform(tmat);
  214.  
  215.     if (definingMacro)
  216.       polys->append(p);
  217.     else {
  218.       primitives++;
  219.       w->polygon(p);
  220.     }
  221.   }
  222. }
  223.