home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / PCGLOVE / GLOVE / OBJGLV.ZIP / SRC / DEMO4B / INT / SEGMENT.CPP < prev    next >
C/C++ Source or Header  |  1993-04-07  |  8KB  |  364 lines

  1. /* Routines for dealing with segmented figures */
  2.  
  3. /* Written by Bernie Roehl, March 1992 */
  4. /* Major paradigm shift: Dave Stampe, Aug. '92 */
  5.  
  6. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  7.      May be freely used to write software for release into the public domain;
  8.      all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  9.      for permission to incorporate any part of this software into their
  10.      products!
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <alloc.h>
  15. #include <string.h>
  16. #include "3dstruct.hpp"
  17. #include "intmath.h"
  18. #include "segment.hpp"
  19.  
  20. static int fix_init = 100;
  21.  
  22.  
  23. SEGMENT *new_seg(SEGMENT *parent)
  24. {
  25.  SEGMENT *s;
  26.  
  27.  if ((s = (SEGMENT *)malloc(sizeof(SEGMENT))) == NULL) return NULL;
  28.  s->parent = parent;
  29.  s->child = NULL;
  30.  if (parent)
  31.   {
  32.    s->sibling = parent->child;
  33.    parent->child = s;
  34.   }
  35.  else s->sibling = NULL;
  36.  
  37.  identity_matrix(s->jmatrix);
  38.  if(parent) memcpy(&(s->pmatrix), &(parent->pmatrix), sizeof(MATRIX));
  39.  else identity_matrix(s->pmatrix);
  40.  
  41.  s->object = NULL;
  42.  s->flags = 1;
  43.  s->name = NULL;
  44.  s->fix_count = fix_init;
  45.  fix_init = (fix_init+7)&0x7F;  /* pseudorandom to prevent clumping */
  46.  
  47.  return s;
  48. }
  49.  
  50. void seg_set_object(SEGMENT *s, OBJECT * app)
  51. {
  52.  s->object = app;
  53.  s->flags |= 1;
  54. }
  55.  
  56. void *seg_get_object(SEGMENT *s)
  57. {
  58.  return s->object;
  59. }
  60.  
  61. char *seg_getname(SEGMENT *s)
  62. {
  63.  return s->name;
  64. }
  65.  
  66. void seg_setname(SEGMENT *s, char *name)
  67. {
  68.  s->name = strdup(name);
  69. }
  70.  
  71. void seg_getposang(SEGMENT *s, long *rx, long *ry, long *rz)
  72. {
  73.  matrix_to_angle(s->pmatrix, rx, ry, rz);
  74. }
  75.  
  76. void seg_getjointang(SEGMENT *s, long *rx, long *ry, long *rz)
  77. {
  78.  matrix_to_angle(s->jmatrix, rx, ry, rz);
  79. }
  80.  
  81. void seg_getposxyz(SEGMENT *s, long *x, long *y, long *z)
  82. {
  83.  *x = s->pmatrix[3][0];
  84.  *y = s->pmatrix[3][1];
  85.  *z = s->pmatrix[3][2];
  86. }
  87.  
  88. void seg_getjointxyz(SEGMENT *s, long *x, long *y, long *z)
  89. {
  90.  *x = s->jmatrix[3][0];
  91.  *y = s->jmatrix[3][1];
  92.  *z = s->jmatrix[3][2];
  93. }
  94.  
  95.  
  96. void abs_move_segment(SEGMENT *s, long tx, long ty, long tz)
  97. {
  98.  s->jmatrix[3][0] = tx;
  99.  s->jmatrix[3][1] = ty;
  100.  s->jmatrix[3][2] = tz;
  101.  s->flags |= 1;
  102. }
  103.  
  104. void rel_move_segment(SEGMENT *s, long tx, long ty, long tz)
  105. {
  106.  s->jmatrix[3][0] += tx;
  107.  s->jmatrix[3][1] += ty;
  108.  s->jmatrix[3][2] += tz;
  109.  s->flags |= 1;
  110. }
  111.  
  112.  
  113. void abs_mat_segment(SEGMENT *s, MATRIX m)
  114. {
  115.  memcpy(s->jmatrix, m, sizeof(MATRIX));
  116.  s-> flags |= 1;
  117. }
  118.  
  119.  
  120. void rel_mat_segment(SEGMENT *s, MATRIX m)
  121. {
  122.  matrix_product(s->jmatrix, m, s->jmatrix);
  123.  s-> flags |= 1;
  124.  s->fix_count--;
  125.  if(s->fix_count==0)
  126.     {
  127.      s->fix_count = fix_init;
  128.      fix_init = (fix_init+7)&0x7F;  /* pseudorandom to prevent clumping */
  129.      fix_matrix_scale(s->jmatrix);
  130.     }
  131. }
  132.  
  133.  
  134. void abs_rotmat_segment(SEGMENT *s, MATRIX m)
  135. {
  136.  s->jmatrix[0][0] = m[0][0];
  137.  s->jmatrix[0][1] = m[0][1];
  138.  s->jmatrix[0][2] = m[0][2];
  139.  s->jmatrix[1][0] = m[1][0];
  140.  s->jmatrix[1][1] = m[1][1];
  141.  s->jmatrix[1][2] = m[1][2];
  142.  s->jmatrix[2][0] = m[2][0];
  143.  s->jmatrix[2][1] = m[2][1];
  144.  s->jmatrix[2][2] = m[2][2];
  145.  s->flags |= 1;
  146. }
  147.  
  148.  
  149. void rel_rotmat_segment(SEGMENT *s, MATRIX m)
  150. {
  151.  matrix_mult(s->jmatrix, m, s->jmatrix);
  152.  s-> flags |= 1;
  153.  s->fix_count--;
  154.  if(s->fix_count==0)
  155.     {
  156.      s->fix_count = fix_init;
  157.      fix_init = (fix_init+7)&0x7F;  /* pseudorandom to prevent clumping */
  158.      fix_matrix_scale(s->jmatrix);
  159.     }
  160. }
  161.  
  162. #define RXYZ 1        /* matrix rotation orders            */
  163. #define RYXZ 0          /* ONLY RYXZ guaranteed to be tested */
  164. #define RXZY 2
  165. #define RZYX 5
  166. #define RZXY 4
  167. #define RYZX 6
  168.  
  169. void abs_rot_segment(SEGMENT *s, long rx, long ry, long rz, int order)
  170. {
  171.  MATRIX m;
  172.  multi_matrix(m, rx, ry, rz, 0, 0, 0, order);
  173.  abs_rotmat_segment(s, m);
  174. }
  175.  
  176. void rel_rot_segment(SEGMENT *s, long rx, long ry, long rz, int order)
  177. {
  178.  MATRIX m;
  179.  multi_matrix(m, rx, ry, rz, 0, 0, 0, order);
  180.  rel_rotmat_segment(s, m);
  181. }
  182.  
  183.  
  184. void move_rep(OBJECT *obj) /* move current rep of object  */
  185. {                          /* called from renderer itself */
  186.  REP *rep = obj->current_rep;
  187.  SEGMENT *s = (SEGMENT *)obj->owner;
  188.  
  189.  matmove_rep(rep, s->pmatrix);
  190. }
  191.  
  192.  
  193. static void (*move_handler)(OBJECT *) = NULL;  /* called when object moved */
  194.  
  195. void set_move_handler(void (*move_handler_ptr)(OBJECT *))
  196. {
  197.  move_handler = move_handler_ptr;
  198. }
  199.  
  200.  
  201. void full_update_segment(SEGMENT *seg)
  202. {
  203.  SEGMENT *s;
  204.  OBJECT *obj;
  205.  
  206.  seg->flags &= ~1;
  207.  if (seg->parent)
  208.      matrix_product(seg->parent->pmatrix, seg->jmatrix, seg->pmatrix);
  209.  else
  210.      memcpy(&(seg->pmatrix), &(seg->jmatrix), sizeof(MATRIX));
  211.  
  212.  if ((obj = seg->object)!=NULL)
  213.     {
  214.      matmove_osphere(obj, seg->pmatrix);
  215.      obj->owner = seg;                     /* just to be safe...       */
  216.      if(move_handler) move_handler(obj);   /* this moves in split tree */
  217.     }
  218.  
  219.  for (s = seg->child; s; s = s->sibling) full_update_segment(s);
  220. }
  221.  
  222.  
  223. void update_segment(SEGMENT *seg) /* scan till update needed */
  224. {
  225.  SEGMENT *s;
  226.  
  227.  if (seg->flags & 1)
  228.     full_update_segment(seg);
  229.  else
  230.     for (s = seg->child; s; s = s->sibling) update_segment(s);
  231. }
  232.  
  233. SEGMENT *find_root_segment(SEGMENT *s)
  234. {
  235.  while (s->parent) s = s->parent;
  236.  return s;
  237. }
  238.  
  239. SEGMENT *parent_segment(SEGMENT *s)
  240. {
  241.  return s->parent;
  242. }
  243.  
  244. SEGMENT *child_segment(SEGMENT *s)
  245. {
  246.  return s->child;
  247. }
  248.  
  249. SEGMENT *sibling_segment(SEGMENT *s)
  250. {
  251.  return s->sibling;
  252. }
  253.  
  254. MATRIX *get_seg_jmatrix(SEGMENT *s)
  255. {
  256.  return &s->jmatrix;
  257. }
  258.  
  259. MATRIX *get_seg_pmatrix(SEGMENT *s)
  260. {
  261.  return &s->pmatrix;
  262. }
  263.  
  264.  
  265. void detach_segment(SEGMENT *s)    /* assumes segment is updated! */
  266. {
  267.  SEGMENT *p;
  268.  MATRIX n;
  269.  
  270.  if ((p = s->parent) == NULL) return;
  271.  s->parent = NULL;
  272.  memcpy(&(s->jmatrix), &(s->pmatrix), sizeof(MATRIX));
  273.  s->flags |= 1;
  274.  if (p->child == s)
  275.   {
  276.    p->child = s->sibling;
  277.    s->sibling = NULL;
  278.    return;
  279.   }
  280.  for (p = p->child; p->sibling; p = p->sibling)
  281.  if (p->sibling == s)
  282.   {
  283.    p->sibling = s->sibling;
  284.    s->sibling = NULL;
  285.    return;
  286.   }
  287.  update_segment(s);
  288. }
  289.  
  290. void attach_segment(SEGMENT *s, SEGMENT *to) /* assumes parent is updated! */
  291. {
  292.  MATRIX m,n;
  293.  
  294.  if (s->parent) detach_segment(s);
  295.  s->parent = to;
  296.  s->sibling = to->child;
  297.  to->child = s;
  298.  
  299.  inverse_matrix(to->pmatrix, m);
  300.  matrix_product(m, s->pmatrix, s->jmatrix);
  301.  s->flags &= ~1;
  302.  to->flags |= 1;
  303.  update_segment(to);
  304. }
  305.  
  306. void delete_segment(SEGMENT *s, void (*delapp_fn)(OBJECT *))
  307. {
  308.  SEGMENT *p, *q;
  309.  
  310.  detach_segment(s); /* first detach us from our parent */
  311.  p = s->child;      /* then recursively delete all our child segments */
  312.  while (p)
  313.   {
  314.    q = p->sibling;
  315.    delete_segment(p, delapp_fn);
  316.    p = q;
  317.   }
  318.  if (s->object && delapp_fn) (*delapp_fn)(s->object);
  319.  free(s);
  320. }
  321.  
  322. #ifdef NEEDS_WORK
  323.  
  324. SEGMENT *copy_segment(SEGMENT *s, long dx, long dy, long dz, void *(*copy_fn)())
  325. {
  326.  SEGMENT *n, *p;
  327.  
  328.  if ((n = new_seg(NULL)) == NULL) return NULL;
  329.  if (copy_fn && s->object)
  330.         n->object = (*copy_fn)(s->object, n);
  331.  n->tx = s->tx + dx;
  332.  n->ty = s->ty + dy;
  333.  n->tz = s->tz + dz;
  334.  n->flags |= 1;
  335.  if ((n->name = malloc(strlen(s->name)+strlen("copy of ")+2)) != NULL)
  336.         sprintf(n->name, "copy of %s", s->name);
  337.  for (p = s->child; p; p = p->sibling)   /* recursively copy children */
  338.   {
  339.    SEGMENT *q;
  340.  
  341.    q = copy_segment(p, 0L, 0L, 0L, copy_fn);
  342.    q->parent = n;
  343.    q->sibling = n->child;
  344.    n->child = q;
  345.   }
  346.  return n;
  347. }
  348.  
  349. #endif
  350.  
  351. SEGMENT *find_segment_by_name(SEGMENT *s, char *name)
  352. {
  353.     SEGMENT *p;
  354.     if (s->name) /* if this segment has a name */
  355.         if (!stricmp(s->name, name)) /* and it matches */
  356.             return s; /* then we've found the segment with that name */
  357.     /* otherwise, recursively check all of our children and their subtrees */
  358.     for (p = s->child; p; p = p->sibling)
  359.         if ((s = find_segment_by_name(p, name)) != NULL) /* found it! */
  360.             return s;
  361.     return NULL; /* neither us nor any of our descendants has that name */
  362. }
  363.  
  364.