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