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