home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / graphtal / wiredevc.c < prev    next >
C/C++ Source or Header  |  1992-11-02  |  5KB  |  222 lines

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