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

  1. /* Interpreter.C - methods for turtle interpreter.
  2.  *
  3.  * Copyright (C) 1991, Christoph Streit
  4.  *
  5.  * This software may be freely copied, modified, and redistributed,
  6.  * provided that this copyright notice is preserved on all copies.
  7.  *
  8.  * There is no warranty or other guarantee of fitness for this software,
  9.  * it is provided solely "as is". Bug reports or fixes may be sent
  10.  * to the author, who may or may not act on them as he desires.
  11.  *
  12.  * You may not include this software in a program or other software product
  13.  * without supplying the source, or without informing the end-user that the
  14.  * source is available for no extra charge.
  15.  *
  16.  * If you modify this software, you should include a notice giving the
  17.  * name of the person performing the modification, the date of modification,
  18.  * and the reason for such modification.
  19.  *
  20.  */
  21.  
  22. #include "Interpreter.h"
  23. #include "Options.h"
  24. #include "Polygon.h"
  25. #include "Turtle.h"
  26. #include "DeviceDriver.h"
  27. #include "Module.h"
  28. #include "Hull.h"
  29. #include "boolean.h"
  30.  
  31. #define startBranchSymbol "["
  32. #define endBranchSymbol   "]"
  33.  
  34. #ifdef OLD_STYLE_CPP
  35.  InterpreterFunctions Interpreter::FuncTable[] = {
  36. #else
  37.  Interpreter::InterpreterFunctions Interpreter::FuncTable[] = {
  38. #endif
  39.  
  40.   {"F",               &Interpreter::forward},
  41.   {"wi",              &Interpreter::width},
  42.   {"G",               &Interpreter::go},
  43.   {"f",               &Interpreter::go},
  44.   {"pt",              &Interpreter::pitch},
  45.   {"&",               &Interpreter::pitch_negativ},
  46.   {"^",               &Interpreter::pitch},
  47.   {"ro",              &Interpreter::roll},
  48.   {"\\",              &Interpreter::roll_negativ},
  49.   {"/",               &Interpreter::roll},
  50.   {"tu",              &Interpreter::turn},
  51.   {"+",               &Interpreter::turn_negativ},
  52.   {"-",               &Interpreter::turn},
  53.   {"rv",              &Interpreter::rotate_vertical},
  54.   {"$",               &Interpreter::rotate_vertical},
  55.   {"|",               &Interpreter::reverse},
  56.   {startBranchSymbol, &Interpreter::push},
  57.   {endBranchSymbol,   &Interpreter::pop},
  58.   {"{",               &Interpreter::startPolygon},
  59.   {"sv",              &Interpreter::saveVertex},
  60.   {".",               &Interpreter::saveVertex},
  61.   {"}",               &Interpreter::endPolygon},
  62.   {"t",               &Interpreter::tropism},
  63.   {"we",              &Interpreter::weight},
  64.   {"co",              &Interpreter::color},
  65.   {"sm",              &Interpreter::beginMacro},
  66.   {"em",              &Interpreter::endMacro},
  67.   {"xm",              &Interpreter::executeMacro},
  68.   {"lib",             &Interpreter::libraryObject},
  69.   {"s",               &Interpreter::sphere},
  70.   {"tri",             &Interpreter::triangle},
  71.   {"poly",            &Interpreter::polygon},
  72.   {"ah",              &Interpreter::activateHull},
  73.   {"dh",              &Interpreter::deactivateHull},
  74.   {"cb",              &Interpreter::cutBranchWhenHit},
  75.   {"%",               &Interpreter::cutBranch},
  76.   {"texture",         &Interpreter::texture},
  77.   {"LastFunc",        NULL}
  78. };
  79.  
  80. FP* Interpreter::functable = NULL;
  81. Value Interpreter::turtleX;
  82. Value Interpreter::turtleY;
  83. Value Interpreter::turtleZ;
  84.  
  85. typedef Turtle* TurtlePtr;
  86. declareList(TurtleStack, TurtlePtr)
  87. implementList(TurtleStack, TurtlePtr)
  88.  
  89. //___________________________________________________________ Interpreter
  90.  
  91. Interpreter::Interpreter(DeviceDriver* device, Options* theOptions)
  92. : d(device), options(theOptions),
  93.   t(NULL), m(NULL), ml(NULL), currentModule(-1), saveTurtle(NULL), 
  94.   polyStack(new PolygonList(100)), turtleStack(new TurtleStack(100)),
  95.   definingMacro(FALSE), reflected(FALSE), deleteBranchWhenHit(FALSE)
  96. {
  97.  
  98.   /*
  99.    * Set up function table if not already done.
  100.    */
  101.   if (functable == NULL) {
  102.  
  103.     /*
  104.      * Add all the function names to global name space.
  105.      */
  106.     for (register int i=0; FuncTable[i].function != NULL; i++) 
  107.       FuncTable[i].index = Name::addname(FuncTable[i].name);
  108.  
  109.     functable = new FP[Name::namesCount()];
  110.  
  111.     /*
  112.      * Generate and initialize hash table for function pointers.
  113.      */
  114.     for (i=0; i<Name::namesCount(); i++)
  115.       functable[i] = NULL;
  116.     for (i=0; FuncTable[i].function != NULL; i++)
  117.       functable[FuncTable[i].index] = FuncTable[i].function;
  118.   }
  119.  
  120.   /*
  121.    * Set up analytic tropism functions and hulls.
  122.    */
  123.   tropismX = options->tropismX; 
  124.   tropismY = options->tropismY; 
  125.   tropismZ = options->tropismZ; 
  126.   tropismFunction = 
  127.     (tropismX != NULL) || (tropismY != NULL) || (tropismZ != NULL);
  128.   tropismWeight = options->weight;
  129.   weightFunction = (tropismWeight != NULL);
  130.   h = options->hulls;
  131. }
  132.  
  133. Interpreter::~Interpreter()
  134. {
  135.   delete polyStack;
  136.   delete turtleStack;
  137. }
  138.  
  139. /*
  140.  * Interpret the module string modules using the given dive driver.
  141.  */
  142.  
  143. void Interpreter::interpret(ModuleList* modules)
  144. {
  145.   t = new Turtle; 
  146.   ml = modules;
  147.  
  148.   /*
  149.    * Start interpretation of module string ml.
  150.    */
  151.   if (!options->quiet)
  152.     cerr << "Start of Interpretation ...\n\n";
  153.  
  154.   d->begin();
  155.  
  156.   /*
  157.    * For each module lookup corresponding interpreter function, call it
  158.    * if not NULL.
  159.    */
  160.   for (currentModule = 0; currentModule < ml->count(); currentModule++) {
  161.     m = ml->item(currentModule);
  162.     if (functable[ml->item(currentModule)->name().index()] != NULL) {
  163.       FP currentFunc = functable[ml->item(currentModule)->name().index()];
  164.       (this->*currentFunc)();
  165.     }
  166.       
  167.     if (options->deleteModules)
  168.       delete ml->item(currentModule);
  169.  
  170.     /*
  171.      * If we hit any hull primitive and deleteBranchWhenHit option is
  172.      * set, ignore all modules up to the next end branch command ("]").
  173.      * Note that we have to skip all the subbranches also.
  174.      */
  175.     if (deleteBranchWhenHit && reflected) {
  176.       reflected = FALSE; // reset
  177.       cutBranch();
  178.     }
  179.   }
  180.  
  181.   flush();
  182.  
  183.   /*
  184.    * Visualize the definied hulls.
  185.    */
  186.   if (options->showHulls) {
  187.     PolygonList* polys;
  188.  
  189.     d->color(Color("HullColor"));
  190.     for (HullSymtab_Iterator hullItr(*h); hullItr.more(); hullItr.next()) {
  191.       polys = hullItr.cur_value()->convertToPolygonList(t->bbox());
  192.       for (register long i=0; i<polys->count(); i++)
  193.     d->polygon(polys->item(i));
  194.       delete polys;
  195.     } 
  196.   }
  197.  
  198.   if (options->verbose) {
  199.     cerr << "BoundingBox: " << t->bbox() << "\n\n";
  200.     cerr << "intersection tests: " 
  201.      << GeoObject::getIntersectionTests() <<"\n"
  202.          << "intersection hits:  " 
  203.      << GeoObject::getIntersections() << "\n\n";
  204.   }
  205.  
  206.   d->end(t->bbox());
  207.  
  208.   delete t;
  209. }
  210.  
  211. //___________________________________________________________ interpreter functions
  212.  
  213. /*
  214.  * Flush checks if there is a segment in the pipe which has't been draw yet
  215.  * (lastWidth > 0) and draws it in that case.
  216.  */
  217.  
  218. void Interpreter::flush()
  219. {
  220.   /*
  221.    * A segment left in the pipe?
  222.    */
  223.   if (t->getLastWidth() > 0) {
  224.     if (tropismFunction || weightFunction)
  225.       computeTropism();
  226.  
  227.     d->color(t->getLastColor());
  228.     d->texture(t->getLastTexture());
  229.  
  230.     if (equal(t->getLastWidth(), t->getWidth()))
  231.       d->cylinder(t->lastPos(), t->pos(), t->getWidth());
  232.     else if (!options->coneSpheres)
  233.       d->cone(t->lastPos(), t->getLastWidth(), t->pos(), t->getWidth());
  234.     else
  235.       createConeBetweenSpheres(t->lastPos(), t->getLastWidth(), 
  236.                    t->pos(), t->getWidth());      
  237.     if (options->coneSpheres)
  238.       d->sphere(t->pos(), t->getWidth());
  239.   }
  240.   t->setLastWidth(-1); // no segments left in the pipe
  241. }
  242.  
  243. /*
  244.  * Go forward and draw a line.
  245.  * lastWidth < 0: no move has been previously done
  246.  */
  247.  
  248. void Interpreter::forward()
  249.   real step;
  250.  
  251.   /*
  252.    * Is there an argument for the move?
  253.    */
  254.   if (m->argCount() <= 0 || !m->arg(0)->toReal(step)) 
  255.     step = options->defaultForward;
  256.  
  257.   /*
  258.    * Do we really have to move?
  259.    */
  260.   if (equal(step, 0)) {
  261.     Error(ERR_ADVISE, "Interpreter::forward with argument 0");
  262.     return;
  263.   }
  264.  
  265.   /*
  266.    * Recompute tropism and weight functions if any present.
  267.    */
  268.   if (tropismFunction || weightFunction)
  269.     computeTropism();
  270.  
  271.   if (t->getLastWidth() > 0) {
  272.     d->color(t->getLastColor());
  273.     d->texture(t->getLastTexture());
  274.   }
  275.  
  276.   real lastWidth    = t->getLastWidth();
  277.   real currentWidth = t->getWidth();
  278.   Vector lastPos    = t->lastPos();
  279.   Vector currentPos = t->pos();
  280.   reflected = t->forward(step);
  281.   Vector newPos     = t->pos();
  282.  
  283.   /*
  284.    * Regular line segment or cone spheres?
  285.    */
  286.   if (lastWidth > 0) {
  287.     if (equal(lastWidth, currentWidth))
  288.       d->cylinder(lastPos, currentPos, lastWidth);
  289.     else if (!options->coneSpheres)
  290.       d->cone(lastPos, lastWidth, currentPos, currentWidth);    
  291.     else 
  292.       createConeBetweenSpheres(lastPos, lastWidth, currentPos, currentWidth);
  293.     
  294.    /*
  295.     * Add sphere when there's an angle between the segments.
  296.     */
  297.     if (options->coneSpheres && !((lastPos-currentPos)*(currentPos-newPos)).zero())
  298.       d->sphere(currentPos, currentWidth);
  299.   }
  300. }
  301.  
  302. /*
  303.  * Go forward without drawing a line.
  304.  */
  305.  
  306. void Interpreter::go()
  307.   real step;
  308.  
  309.   flush();
  310.   if (tropismFunction || weightFunction)
  311.     computeTropism();
  312.  
  313.   if (m->argCount()>0 && m->arg(0)->toReal(step))
  314.     reflected = t->forward(step);
  315.   else
  316.     reflected = t->forward(options->defaultForward);
  317.  
  318.   /*
  319.    * There's no segment in the pipe left.
  320.    */
  321.   t->setLastWidth(-1);
  322. }
  323.  
  324. /*
  325.  * Set line width.
  326.  */
  327.  
  328. void Interpreter::width()
  329. {
  330.   real width;
  331.   if (m->argCount()>0 && m->arg(0)->toReal(width) && width>0) 
  332.     t->setWidth(width);
  333. }
  334.  
  335. /*
  336.  * Pitch turtle in positive direction.
  337.  */
  338.  
  339. void Interpreter::pitch()
  340.   real a;
  341.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  342.     t->pitch(dtor(a));
  343.   else
  344.     t->pitch(options->defaultPitch);
  345. }
  346.  
  347. /*
  348.  * Pitch turtle in negative direction.
  349.  */
  350.  
  351. void Interpreter::pitch_negativ()
  352.   real a;
  353.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  354.     t->pitch(-dtor(a));
  355.   else
  356.     t->pitch(-options->defaultPitch);
  357. }
  358.  
  359. /*
  360.  * Turn turtle in positive direction.
  361.  */
  362.  
  363. void Interpreter::turn()
  364.   real a;
  365.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  366.     t->turn(dtor(a));
  367.   else
  368.     t->turn(options->defaultTurn);
  369. }
  370.  
  371. /*
  372.  * Turn turtle in negative direction.
  373.  */
  374.  
  375. void Interpreter::turn_negativ()
  376.   real a;
  377.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  378.     t->turn(-dtor(a));
  379.   else
  380.     t->turn(-options->defaultTurn);
  381. }
  382.  
  383. /*
  384.  * Roll turtle in positive direction.
  385.  */
  386.  
  387. void Interpreter::roll()
  388.   real a;
  389.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  390.     t->roll(dtor(a));
  391.   else
  392.     t->roll(options->defaultRoll);
  393. }
  394.  
  395. /*
  396.  * Roll turtle in negative direction.
  397.  */
  398.  
  399. void Interpreter::roll_negativ()
  400.   real a;
  401.   if (m->argCount()>0 && m->arg(0)->toReal(a)) 
  402.     t->roll(-dtor(a));
  403.   else
  404.     t->roll(-options->defaultRoll);
  405. }
  406.  
  407. /*
  408.  * Align turtle vertical.
  409.  */
  410.  
  411. void Interpreter::rotate_vertical()
  412. {
  413.   t->rotate_vertical();
  414. }
  415.  
  416. /*
  417.  * Reverse heading of the turtle.
  418.  */
  419.  
  420. void Interpreter::reverse()
  421. {
  422.   t->reverse();
  423. }
  424.  
  425. /*
  426.  * Save current turtle state on the stack.
  427.  */
  428.  
  429. void Interpreter::push()
  430. {
  431.   turtleStack->prepend(t);
  432.   t = new Turtle(*t);
  433.   t->setLastWidth(-1);
  434. }
  435.  
  436. /*
  437.  * Restore turtle state from stack.
  438.  */
  439.  
  440. void Interpreter::pop()
  441. {
  442.   flush();
  443.  
  444.   if (turtleStack->count() > 0) {
  445.     turtleStack->item(0)->expandBBoxBy(t->bbox());
  446.     delete t;
  447.     t = turtleStack->item(0);
  448.     turtleStack->remove(0);
  449.   }
  450.   else 
  451.     Error(ERR_WARN, "Interpreter::pop stack is empty");
  452. }
  453.  
  454. /*
  455.  * Start a new polygon.
  456.  */
  457.  
  458. void Interpreter::startPolygon()
  459. {
  460.   polyStack->prepend(new Polygon);
  461. }
  462.  
  463. /*
  464.  * Add vertex to current polygon.
  465.  */
  466.  
  467. void Interpreter::saveVertex()
  468. {
  469.   if (polyStack->count() > 0)
  470.     polyStack->item(0)->addVertex(t->pos());
  471.   else
  472.     Error(ERR_WARN, "Interpreter::saveVertex polygon stack is empty");
  473. }
  474.  
  475. /*
  476.  * End of polygon definition.
  477.  */
  478.  
  479. void Interpreter::endPolygon()
  480. {
  481.   if (polyStack->count() <= 0) {
  482.     Error(ERR_WARN, "Interpreter::endPolygon polygon stack is empty");
  483.     return;
  484.   }
  485.  
  486.   Polygon* p = polyStack->item(0);
  487.  
  488.   if (p->numVertices() <= 0) {
  489.     Error(ERR_WARN, "Interpreter::endPolygon no vertex in polygon");
  490.     delete p;
  491.     polyStack->remove(0);
  492.     return;
  493.   }
  494.   
  495.   /*
  496.    * Start and endpoint should not be the same.
  497.    */
  498.   if (p->numVertices()>1 && p->vertex(0) == p->vertex(p->numVertices()-1))
  499.     p->removeVertex(p->numVertices()-1);
  500.  
  501.   /* 
  502.    * Set color and texture.
  503.    */
  504.   d->color(t->getColor());
  505.   d->texture(t->getTexture());
  506.  
  507.   d->polygon(p);
  508.  
  509.   polyStack->remove(0);
  510. }
  511.  
  512. /*
  513.  * Set tropism vector.
  514.  */
  515.  
  516. void Interpreter::tropism()
  517. {
  518.   real x, y, z, w;
  519.   if (m->argCount() >= 3  &&  
  520.       m->arg(0)->toReal(x) && m->arg(1)->toReal(y) && m->arg(2)->toReal(z)) {
  521.     t->setTropism(x,y,z);
  522.  
  523.     if (m->argCount() >= 4 && m->arg(3)->toReal(w))
  524.       t->setWeight(w);
  525.   }
  526. }
  527.  
  528. /*
  529.  * Set weight for tropism calculations.
  530.  */
  531.  
  532. void Interpreter::weight()
  533. {
  534.   real w;
  535.   if (m->argCount()>0 && m->arg(0)->toReal(w)) 
  536.     t->setWeight(w);
  537. }
  538.  
  539. /*
  540.  * Set color.
  541.  */
  542.  
  543. void Interpreter::color()
  544. {
  545.   if (m->argCount()>0) {
  546.     Color c(m->arg(0)->toString());
  547.     t->setColor(c);
  548.   }
  549. }
  550.  
  551. /* 
  552.  * Start macro definition.
  553.  */
  554.  
  555. void Interpreter::beginMacro()
  556. {
  557.   if (definingMacro) 
  558.     Error(ERR_PANIC, "Interpreter::beginMacro nested macro definition");
  559.   
  560.   if (m->argCount() <= 0) 
  561.     Error(ERR_PANIC, "Interpreter::beginMacro macro definition without a name");
  562.  
  563.   rcString macroName(m->arg(0)->toString());
  564.  
  565.   if (!d->addMacroName(macroName))
  566.     Error(ERR_PANIC, "Interpreter::beginMacro macro \"" 
  567.                      + macroName + "\" already defined");
  568.   
  569.   saveTurtle = t; 
  570.   t = new Turtle; 
  571.   definingMacro = TRUE;
  572.   d->beginMacro(macroName);
  573. }
  574.  
  575. /*
  576.  * End of macro definition.
  577.  */
  578.  
  579. void Interpreter::endMacro()
  580. {
  581.   flush();
  582.   d->endMacro();
  583.   delete t;
  584.   t = saveTurtle; saveTurtle = NULL;
  585.   definingMacro = FALSE;
  586. }
  587.  
  588. /*
  589.  * Execute a already defined macro.
  590.  */
  591.  
  592. void Interpreter::executeMacro()
  593. {
  594.   if (m->argCount() <= 0) {
  595.     Error(ERR_WARN, "Interpreter::executeMacro macro without a name");
  596.     return;
  597.   }
  598.  
  599.   TransMatrix tmat;
  600.   real scale;
  601.  
  602.   tmat(0,0) = t->vecU()[0]; tmat(0,1) = t->vecU()[1]; tmat(0,2) = t->vecU()[2]; 
  603.   tmat(1,0) = t->vecL()[0]; tmat(1,1) = t->vecL()[1]; tmat(1,2) = t->vecL()[2]; 
  604.   tmat(2,0) = t->vecH()[0]; tmat(2,1) = t->vecH()[1]; tmat(2,2) = t->vecH()[2]; 
  605.  
  606.   if (m->argCount()>1 && m->arg(1)->toReal(scale) && !equal(scale, 1))
  607.     tmat.scale(scale, scale, scale);
  608.   tmat.translate(t->pos());
  609.  
  610.   d->executeMacro(m->arg(0)->toString(), tmat);
  611. }
  612.  
  613. /*
  614.  * Include a predefined object.
  615.  */
  616.  
  617. void Interpreter::libraryObject()
  618. {
  619.   if (m->argCount() <= 0) {
  620.     Error(ERR_WARN, "Interpreter::libraryObject object without a name");
  621.     return;
  622.   }
  623.  
  624.   TransMatrix tmat;
  625.   real scale;
  626.  
  627.   rcString libName(m->arg(0)->toString());
  628.  
  629.   d->addLibraryObjectName(libName);
  630.  
  631.   tmat(0,0) = t->vecU()[0]; tmat(0,1) = t->vecU()[1]; tmat(0,2) = t->vecU()[2]; 
  632.   tmat(1,0) = t->vecL()[0]; tmat(1,1) = t->vecL()[1]; tmat(1,2) = t->vecL()[2]; 
  633.   tmat(2,0) = t->vecH()[0]; tmat(2,1) = t->vecH()[1]; tmat(2,2) = t->vecH()[2]; 
  634.  
  635.   if (m->argCount()>1 && m->arg(1)->toReal(scale) && !equal(scale, 1))
  636.     tmat.scale(scale, scale, scale);
  637.   tmat.translate(t->pos());
  638.  
  639.   d->libraryObject(libName, tmat);
  640. }
  641.  
  642. /*
  643.  * Generate sphere at turtle position with given radius.
  644.  */
  645.  
  646. void Interpreter::sphere()
  647. {
  648.   real r;
  649.  
  650.   /* 
  651.    * Set color and texture.
  652.    */
  653.   d->color(t->getColor());
  654.   d->texture(t->getTexture());
  655.  
  656.   if (m->argCount()>0 && m->arg(0)->toReal(r)) 
  657.     d->sphere(t->pos(), r);
  658.   else
  659.     d->sphere(t->pos(), 1);
  660. }
  661.  
  662. /*
  663.  * Generate triangle with given vertices.
  664.  */
  665.  
  666. void Interpreter::triangle()
  667. {
  668.   if (m->argCount() < 9)
  669.     return;
  670.  
  671.   real coords[9];
  672.   for (register int i=0; i<9; i++)
  673.     if (!m->arg(i)->toReal(coords[i]))
  674.       return;
  675.  
  676.   Vector p1(coords[0], coords[1], coords[2]); 
  677.   Vector p2(coords[3], coords[4], coords[5]); 
  678.   Vector p3(coords[6], coords[7], coords[8]); 
  679.  
  680.   BoundingBox tmpBBox;
  681.   tmpBBox.expand(p1);
  682.   tmpBBox.expand(p2);
  683.   tmpBBox.expand(p3);
  684.   t->expandBBoxBy(tmpBBox);
  685.  
  686.   /* 
  687.    * Set color and texture.
  688.    */
  689.   d->color(t->getColor());
  690.   d->texture(t->getTexture());
  691.  
  692.   d->polygon(new Polygon(p1, p2, p3));
  693. }
  694.  
  695. /*
  696.  * Generate polygon with given vertices.
  697.  */
  698.  
  699. void Interpreter::polygon()
  700. {
  701.   if (m->argCount() < 9)
  702.     return;
  703.  
  704.   real x, y, z;
  705.   Polygon* p = new Polygon(3);
  706.   BoundingBox tmpBBox;
  707.  
  708.   for (register int i=0; i<m->argCount()-2; i+=3) {
  709.     if (m->arg(i)->toReal(x)   && 
  710.     m->arg(i+1)->toReal(y) && 
  711.     m->arg(i+2)->toReal(z)) 
  712.       {
  713.     p->addVertex(Vector(x,y,z));
  714.     tmpBBox.expand(Vector(x,y,z));
  715.       }
  716.   }
  717.  
  718.   if (p->numVertices() > 2) {
  719.  
  720.     /* 
  721.      * Set color and texture.
  722.      */
  723.     d->color(t->getColor());
  724.     d->texture(t->getTexture());
  725.  
  726.     d->polygon(p);
  727.     t->expandBBoxBy(tmpBBox);
  728.   }
  729.   else
  730.     delete p;
  731. }
  732.  
  733. /*
  734.  * Activate a hull. Turtle will move with respect to the primitives
  735.  * of the hull.
  736.  */
  737.  
  738. void Interpreter::activateHull()
  739. {
  740.   if (m->argCount()<=0) {
  741.     Error(ERR_WARN, "Interpreter::activateHull no hull name");
  742.     return;
  743.   }
  744.  
  745.   rcString hullName(m->arg(0)->toString());
  746.  
  747.   Hull* hull;
  748.   if (!h->lookup(hullName, hull)) {
  749.     Error(ERR_WARN, "Interpreter::activateHull unknown hull " + hullName);
  750.     return;
  751.   }
  752.   real reflectanceFactor = 1;
  753.   if (m->argCount()>1)
  754.     m->arg(1)->toReal(reflectanceFactor);
  755.   
  756.   t->setHull(hull, reflectanceFactor);
  757. }
  758.  
  759. void Interpreter::deactivateHull()
  760. {
  761.   t->unsetHull();
  762. }
  763.  
  764. /*
  765.  * Set/Unset of delete branch when conflict with current hull.
  766.  */
  767.  
  768. void Interpreter::cutBranchWhenHit()
  769. {
  770.   real flag = TRUE;
  771.   if (m->argCount() > 0)
  772.     m->arg(0)->toReal(flag);
  773.     
  774.   if ((int)flag) {
  775.     deleteBranchWhenHit = TRUE;
  776.     t->setStopOnHit();
  777.   }
  778.   else {
  779.     deleteBranchWhenHit = FALSE;
  780.     t->unsetStopOnHit();
  781.   }
  782. }
  783.  
  784. /*
  785.  * Ignore all the modules until we find a end branch symbol (ignore
  786.  * subbranches also).
  787.  */
  788.  
  789. void Interpreter::cutBranch()
  790. {
  791.   static Name startBranch(startBranchSymbol);
  792.   static Name endBranch(endBranchSymbol);
  793.   int nested = 0;
  794.  
  795.   /*
  796.    * Ignore all modules up to the next end branch command ("]").
  797.    * Note that we have to skip all the subbranches also.
  798.    */
  799.   while (++currentModule < ml->count()) {
  800.     if (ml->item(currentModule)->name() == startBranch)
  801.       nested++;
  802.     else if (ml->item(currentModule)->name() == endBranch) {
  803.       if (nested-- == 0) {
  804.     currentModule--; 
  805.     break;
  806.       }
  807.     }
  808.     if (options->deleteModules)
  809.       delete ml->item(currentModule);
  810.   }
  811. }
  812.  
  813. /*
  814.  * Define texture for the following primitives.
  815.  */
  816. void Interpreter::texture()
  817. {
  818.   if (m->argCount()>0) {
  819.     rcString theTexture(m->arg(0)->toString());
  820.     t->setTexture(theTexture);
  821.   }
  822.   else
  823.     t->setTexture(""); // disable textures
  824. }
  825.  
  826. /*
  827.  * Generate a cone between two given spheres. 
  828.  */
  829.  
  830. void Interpreter::createConeBetweenSpheres(const Vector& p1, real r1, 
  831.                             const Vector& p2, real r2)
  832. {
  833.   real a = r1-r2;
  834.   real r = r1;
  835.   real c = p1.distance(p2);
  836.   int secondIsLarger = FALSE;
  837.  
  838.   if (c<r1 || c<r2) {
  839.     Error(ERR_ADVISE, rcString("Interpreter::createConeBetweenSpheres\n") + 
  840.                       "\tdistance between spheres is too small -> can't create cone\n");
  841.     return;
  842.   }
  843.     
  844.   if (a < 0) {
  845.     r = r2;
  846.     a = -a;
  847.     secondIsLarger = TRUE;
  848.   }
  849.   
  850.   real p  = a*a/c;
  851.   real ps = p*r/a;
  852.  
  853.   real h  = sqrt(p*(c-p));
  854.   real hs = h*r/a;
  855.  
  856.   Vector dir = p2 - p1;
  857.  
  858.   if (secondIsLarger)
  859.     d->cone(p1-dir*((ps-p)/c), hs-h, p2-dir*(ps/c), hs);
  860.   else
  861.     d->cone(p1+dir*(ps/c), hs, p2+dir*((ps-p)/c), hs-h);
  862. }
  863.  
  864. /*
  865.  * If tropism vector depends on turtle position, we recompute the
  866.  * tropism vector after each move.
  867.  */
  868.  
  869. void Interpreter::computeTropism()
  870. {
  871.   turtleX = t->pos()[0];
  872.   turtleY = t->pos()[1];
  873.   turtleZ = t->pos()[2];
  874.  
  875.   if (tropismFunction)
  876.     t->setTropism(tropismX->evaluate(),
  877.           tropismY->evaluate(),
  878.           tropismZ->evaluate());  
  879.  
  880.   if (weightFunction)
  881.     t->setWeight(tropismWeight->evaluate());
  882. }
  883.