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

  1. /*
  2.  * Turtle.C - definitions for 3D turtle.
  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 <stdlib.h>
  19. #include <values.h>
  20. #include "Turtle.h"
  21. #include "TransMatrix.h"
  22. #include "Error.h"
  23. #include "Ray.h"
  24.  
  25. //___________________________________________________________ Tropism
  26.  
  27. Tropism::Tropism(real x, real y, real z, real w)
  28. : F(x, y, z), weight(w), apply(0)
  29. {
  30.   if (F.zero()) 
  31.     F = Vector(0,0,-1);
  32.   F.normalize();
  33. }
  34.  
  35. //___________________________________________________________ Turtle
  36.  
  37. /* init of turtle:
  38.  *
  39.  *                   *
  40.  *            / \ H
  41.  *             |
  42.  *                   |
  43.  *          L        |
  44.  *        / _________|
  45.  *        \         /
  46.  *                 / U
  47.  *               \ /
  48.  *                *
  49.  */                                          
  50.  
  51. Turtle::Turtle()
  52. : P(0,0,0), lastP(0,0,0), H(0,0,1), L(0,-1,0), U(1,0,0),
  53.   tropism(0,0,-1,0.5),
  54.   hullActivated(0), hull(NULL), reflectanceFactor(1), stopOnHit(0)
  55. {
  56.  width = 1;
  57.  lastWidth = -1; // no move has been previously done
  58.   
  59.  b.expand(P);
  60. }
  61.  
  62. Turtle::~Turtle()
  63. {}
  64.  
  65. /*
  66.  * forward moves the turtle in the current direction according to
  67.  * the formula:
  68.  *
  69.  *     P' = P + step*H
  70.  */
  71.  
  72. int Turtle::forward(real step)
  73. {
  74.   lastWidth = width;
  75.   lastP = P;
  76.   lastColor = color;
  77.   lastTexture = texture;
  78.  
  79.   if (hullActivated)
  80.     return forwardWithRespectToHull(step);
  81.   else {
  82.     P += step*H;
  83.     applyTropism();
  84.     b.expand(P);
  85.     return 0;
  86.   }
  87. }
  88.  
  89. /*
  90.  * Moves the turtle in the current direction with respect to the
  91.  * activated hull. If the turtle hits the hull it changes direction.
  92.  * This is repeated until step == 0.
  93.  */
  94.  
  95. int Turtle::forwardWithRespectToHull(real step)
  96. {
  97.   hull->intersect(Ray(P, H), distanceToClosestObject, closestObject);
  98.  
  99.   while (step > 0) {
  100.     if (distanceToClosestObject > step) {
  101.       P += H*step;
  102.       b.expand(P);
  103.       applyTropism();
  104.       distanceToClosestObject -= step;
  105.       break;
  106.     }
  107.     else {
  108.       P += H*distanceToClosestObject;
  109.       b.expand(P);
  110.  
  111.       if (stopOnHit)
  112.     return 1;
  113.  
  114.       bounce();
  115.       applyTropism();
  116.       step -= distanceToClosestObject;
  117.       hull->intersect(Ray(P, H), distanceToClosestObject, closestObject);
  118.     }
  119.   }
  120.  
  121.   return 0;
  122. }
  123.  
  124. /*
  125.  * Reflect turtle at the current closest object -> changes H, U
  126.  */
  127.  
  128. void Turtle::bounce()
  129. {
  130.   /*
  131.    * Reflect turtle at position P. The result is a new heading (H)
  132.    * and a changed up vector (U). The left vector (L) does not change
  133.    * (a reflected ray stays in the same plane).
  134.    */
  135.  
  136.   Vector normal = closestObject->getNormal(P);
  137.  
  138.   H = H-2.*((normal^H)*normal)*reflectanceFactor; 
  139.   H.normalize();
  140.   U = H*L;
  141. }
  142.  
  143. /*
  144.  *  pitch rotates H, L, U around L according to the formula
  145.  *
  146.  *                              [  cos(a)   0   -sin(a) ]
  147.  *                              [                       ]
  148.  *    [H' L' U'] =  [ H L U ] * [     0     1       0   ]
  149.  *                              [                       ]
  150.  *                              [  sin(a)   0   cos(a)  ]
  151.  */
  152.  
  153. void Turtle::pitch(real a)
  154. {
  155.   Vector tmp(H);
  156.   real sin_a, cos_a;
  157.  
  158.   SinCos(a, sin_a, cos_a);
  159.   
  160.   H = H*cos_a + U*sin_a;  
  161.   H.normalize();
  162.   U = U*cos_a - tmp*sin_a;
  163. }
  164.  
  165. /*
  166.  * turn rotates H, L, U around U according to the formula
  167.  *
  168.  *                              [  cos(a)   sin(a)  0 ]
  169.  *                              [                     ]
  170.  *    [H' L' U'] =  [ H L U ] * [ - sin(a)  cos(a)  0 ]
  171.  *                              [                     ]
  172.  *                              [     0        0    1 ]
  173.  */  
  174.   
  175. void Turtle::turn(real a)
  176. {
  177.   Vector tmp(H);
  178.   real sin_a, cos_a;
  179.  
  180.   SinCos(a, sin_a, cos_a);
  181.   
  182.   H = H*cos_a - L*sin_a;   
  183.   H.normalize();
  184.   L = tmp*sin_a + L*cos_a;
  185. }
  186.  
  187. /*
  188.  *  roll rotates H, L, U around H according to the formula
  189.  *
  190.  *                              [  1     0       0     ]
  191.  *                              [                      ]
  192.  *    [H' L' U'] =  [ H L U ] * [  0   cos(a)  sin(a)  ]
  193.  *                              [                      ]
  194.  *                              [  0  -sin(a)  cos(a)  ]
  195.  */
  196.  
  197. void Turtle::roll(real a)
  198. {
  199.   Vector tmp(L);
  200.   real sin_a, cos_a;
  201.  
  202.   SinCos(a, sin_a, cos_a);
  203.   
  204.   L = L*cos_a - U*sin_a;
  205.   U = tmp*sin_a + U*cos_a;
  206. }
  207.  
  208. /*
  209.  *   reverse spins the turtle around 180 degrees
  210.  */
  211.  
  212. void Turtle::reverse()
  213. {
  214.   H = -H;
  215.   L = -L;
  216. }
  217.  
  218. void Turtle::rotate_vertical()
  219. {
  220.   const real tolerance = 1e-4;
  221.   static Vector gravity(0,0,-1);
  222.   Vector tmp = gravity * H;
  223.  
  224.   if (tmp.length() < tolerance)
  225.     return;
  226.  
  227.   L = tmp.normalized();
  228.   U = H*L;
  229. }
  230.   
  231. void Turtle::setWeight(real w)    
  232.   tropism.weight = w; 
  233.   if (equal(tropism.weight, 0) || tropism.F.zero())
  234.     tropism.apply = 0;
  235.   else
  236.     tropism.apply = 1;
  237. }
  238.  
  239. void Turtle::setTropism(real x, real y, real z) 
  240. {
  241.   tropism.F = Vector(x, y, z);
  242.   
  243.   if (!tropism.F.zero()) 
  244.     tropism.F.normalize();
  245.  
  246.   if (equal(tropism.weight, 0) || tropism.F.zero())
  247.     tropism.apply = 0;
  248.   else
  249.     tropism.apply = 1;
  250.  
  251. ostream& operator<<(ostream& os, const Turtle& t)
  252. {
  253.   os << "P: " << t.P << "\n"
  254.      << "H: " << t.H << "\n"
  255.      << "U: " << t.U << "\n"
  256.      << "L: " << t.L << "\n";
  257.   return os;
  258. }
  259.  
  260. /*
  261.  * Apply the given tropism vector to the turtle.
  262.  */
  263.  
  264. void Turtle::applyTropism()
  265. {
  266.   static TransMatrix rot;
  267.  
  268.   /*
  269.    * Should tropism be applied.
  270.    */
  271.   if (!tropism.apply)
  272.     return;
  273.  
  274.   Vector rotvec(H*tropism.F);
  275.   real alpha = acos(H^tropism.F)*tropism.weight*rotvec.length();
  276.  
  277.   /*
  278.    * Limit the rotation.
  279.    */
  280.   if (alpha >  M_PI/6) alpha =  M_PI/6;
  281.   if (alpha < -M_PI/6) alpha = -M_PI/6;
  282.  
  283.   if (!equal(alpha,0) && !rotvec.zero()) {
  284.     rot.setRotate(rotvec, alpha);
  285.     H = H*rot; H.normalize();
  286.     L = L*rot; L.normalize();
  287.     U = H*L;   
  288.   }
  289. }
  290.  
  291.