home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / rayce27s / object.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-02  |  10.4 KB  |  510 lines

  1. /*
  2.  * objects.c -- standard object manipulations
  3.  * 
  4.  * (c) 1993, 1994 Han-Wen Nienhuys. <hanwen@stack.urc.tue.nl>
  5.  * 
  6.  * This program is free software; you can redistribute it and/or modify it
  7.  * under the terms of the GNU General Public License as published by the
  8.  * Free Software Foundation;
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License along
  16.  * with this program; if not, write to the Free Software Foundation, Inc.,
  17.  * 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. #include <stdlib.h>
  21. #include "ray.h"
  22. #include "proto.h"
  23. #include "extern.h"
  24.  
  25. PRIVATE
  26. boem()
  27. {
  28.     assert(FALSE);
  29. }
  30.  
  31. PRIVATE struct methods null_methods =
  32. {
  33.     boem,
  34.     boem,
  35.     boem,
  36.     boem,
  37.     boem,
  38.     boem,
  39.     boem,
  40.     boem,
  41.     boem,
  42.     boem,
  43.     boem,
  44.     "(none)",
  45. };
  46.  
  47. /*
  48.  * intersect a ray with an object.
  49.  */
  50. PUBLIC bool
  51. intersect_object(dqueue * globalq, object *o, struct ray *r, int flags)
  52. {
  53.     struct ray      transray;
  54.     bool            b;
  55.     bool            hit;
  56.     object         *op;
  57.  
  58.     global_stats.objtest++;
  59.  
  60.     /* use speed in the ray. */
  61.     transray = *r;
  62.  
  63.     svproduct(transray.pos, -Time, o->speed);
  64.     vadd(transray.pos, r->pos, transray.pos);
  65.  
  66.     /* check for bounding shapes, walk them all */
  67.     for (op = o->bound; op != NULL; op = op->next) {
  68.     dqueue         *q;
  69.  
  70.     if (op->methods->inside_method(o->bound, r->pos))
  71.         continue;
  72.  
  73.     q = get_new_queue();
  74.  
  75.     /* Check bounding shape: */
  76.     global_stats.boundtest++;
  77.  
  78.     /* don't translate bounds. */
  79.     if (!intersect_object(q, op, r, FALSE)) {
  80.         /* no intersection at all */
  81.  
  82.         free_queue(q);
  83.         return FALSE;
  84.     }
  85.     /* found one! */
  86.     if (!(flags & CHKALL) && q->t >= globalq->t) {    /* close enough? */
  87.         free_queue(q);    /* no, exit */
  88.         return FALSE;
  89.     }
  90.     free_queue(q);
  91.  
  92.     global_stats.boundhit++;/* And another bound has been succesful */
  93.     }
  94.  
  95.     if (o->clip != NULL) {
  96.  
  97.     /* do clippingshape */
  98.     dqueue         *q,
  99.                    *qp;
  100.     vector          x;
  101.  
  102.     q = get_new_queue();
  103.     o->methods->all_intersections_method(q, o, &transray, flags | CHKALL, &b);
  104.  
  105.     hit = FALSE;
  106.     for (qp = q; (qp != NULL && qp->obj != NULL) && (flags & CHKALL ||
  107.                           !hit); qp = qp->next) {
  108.         bool            inside;
  109.  
  110.         /* find intersection point */
  111.         svproduct(x, qp->t, transray.dir);
  112.         vadd(x, transray.pos, x);
  113.  
  114.         global_stats.cliptest++;
  115.  
  116.         /*
  117.          * filter out the intersections which are inside of the
  118.          * clipping shape.
  119.          */
  120.         inside = TRUE;
  121.         for (op = o->clip; op != NULL && inside; op = op->next) {
  122.         if (!op->methods->inside_method(op, x))
  123.             inside = FALSE;
  124.         }
  125.  
  126.         if (inside) {
  127.         add_to_queue(globalq, *qp);
  128.         global_stats.cliphit++;
  129.         hit = TRUE;
  130.         }
  131.     }
  132.  
  133.     free_queue(q);
  134.     } else {
  135.  
  136.     /* intersect the ray with object's shape */
  137.     hit = o->methods->all_intersections_method(globalq, o,
  138.                            &transray, flags, &b);
  139.  
  140.     }
  141.     if (hit)
  142.     global_stats.objhit++;
  143.     return hit;
  144. }
  145.  
  146. /* apply speed to one object */
  147. PUBLIC void
  148. speed_object(object *o, vector s)
  149. {
  150.     if (o->type == COMPOSITE)
  151.     speed_composite(o, s);
  152.     else
  153.     vadd(o->speed, s, o->speed);
  154. }
  155.  
  156.  
  157. /* append toadd to list starting with o. Both must have been allocated. */
  158. PUBLIC void
  159. append_to_object_list(object *o, object *toadd)
  160. {
  161.     object         *last;
  162.  
  163.     assert(o != NULL);
  164.  
  165.     for (; o != NULL; o = o->next)
  166.     last = o;
  167.     last->next = toadd;
  168. }
  169.  
  170. /* add clipping shape from boundingshapes. */
  171. PUBLIC void
  172. add_bounds_to_clip(object *o)
  173. {
  174.     object         *srcp,
  175.                    *dstp;
  176.  
  177.     if (o->bound != NULL) {    /* this object has a bound. */
  178.     o->clip = get_new_object();
  179.  
  180.     dstp = o->clip;
  181.  
  182.     for (srcp = o->bound; srcp != NULL; srcp = srcp->next) {
  183.  
  184.         copy_object(dstp, srcp);
  185.         if (srcp->next != NULL)
  186.         dstp->next = get_new_object();
  187.  
  188.         dstp = dstp->next;
  189.     }
  190.     }
  191. }
  192.  
  193.  
  194. /* apply speed to a whole bunch of objects */
  195. PUBLIC void
  196. speed_object_list(object *start, vector s)
  197. {
  198.     for (; start != NULL; start = start->next)
  199.     speed_object(start, s);
  200. }
  201.  
  202.  
  203. /* standard routine */
  204. PUBLIC void
  205. copy_object(object *dst, object *src)
  206. {
  207.     assert(dst != NULL && src != NULL);
  208.  
  209.     /* copy info */
  210.     dst->type = NOSHAPE;
  211.     dst->speed = src->speed;
  212.     dst->inverted = src->inverted;
  213.     dst->methods = src->methods;
  214.     dst->next = NULL;
  215.     dst->daddy = NULL;
  216.  
  217.     /* copy pointers */
  218.     if (src->text != NULL) {    /* check wether sources have a texture */
  219.     if (dst->text == NULL)    /* source has texture; does dest has space
  220.                  * for one? */
  221.         dst->text = get_new_texture();    /* no, so alloc space */
  222.     copy_texture(dst->text, src->text);    /* now copy stuff */
  223.     }
  224.     /* copy the shape */
  225.     src->methods->copy_method(dst, src);
  226.  
  227.     if (src->inv_trans) {
  228.     dst->inv_trans = get_new_matrix();
  229.     copy_matrix(*dst->inv_trans, *src->inv_trans);
  230.     } {
  231.     object         *srcp,
  232.                    *dstp;
  233.  
  234.     if (src->bound != NULL) {    /* this object has a bound. */
  235.         dst->bound = get_new_object();
  236.  
  237.         for (dstp = dst->bound, srcp = src->bound; srcp != NULL; srcp = srcp->next) {
  238.         copy_object(dstp, srcp);
  239.         if (srcp->next != NULL)
  240.             dstp->next = get_new_object();
  241.         dstp = dstp->next;
  242.         }
  243.     }
  244.     if (src->clip != NULL) {/* this object has a bound. */
  245.         dst->clip = get_new_object();
  246.  
  247.         for (dstp = dst->clip, srcp = src->clip; srcp != NULL; srcp = srcp->next) {
  248.         copy_object(dstp, srcp);
  249.         if (srcp->next != NULL)
  250.             dstp->next = get_new_object();
  251.         dstp = dstp->next;
  252.         }
  253.     }
  254.     }
  255.  
  256. }
  257.  
  258.  
  259. PUBLIC void
  260. precompute_object(object *o)
  261. {
  262.     object         *op;
  263.     vector          displac;
  264.  
  265.     precompute_object_list(o->bound);
  266.     precompute_object_list(o->clip);
  267.     o->methods->precompute_method(o);
  268.  
  269.     if (o->bound != NULL)
  270.     global_stats.bounds++;
  271.     if (o->clip != NULL)
  272.     global_stats.clips++;
  273.     for (op = o->bound; op != NULL; op = op->next) {
  274.     o->bmin.x = MAX(op->bmin.x, o->bmin.x);
  275.     o->bmin.y = MAX(op->bmin.y, o->bmin.y);
  276.     o->bmin.z = MAX(op->bmin.z, o->bmin.z);
  277.     o->bmax.x = MIN(op->bmax.x, o->bmax.x);
  278.     o->bmax.y = MIN(op->bmax.y, o->bmax.y);
  279.     o->bmax.z = MIN(op->bmax.z, o->bmax.z);
  280.     }
  281.  
  282.     vadd(o->bmax, o->bmax, fudge);
  283.     vsub(o->bmin, o->bmin, fudge);
  284.     global_stats.objects++;
  285. }
  286.  
  287. PUBLIC void
  288. precompute_object_list(object *o)
  289. {
  290.     for (; o != NULL; o = o->next)
  291.     precompute_object(o);
  292. }
  293.  
  294. /* initialize the object passed by p */
  295. PUBLIC void
  296. init_object(object *p)
  297. {
  298.     /* initialize movement; pointers to NULL */
  299.     setvector(p->speed, 0, 0, 0);
  300.  
  301.     /* set bmin and bmax to unity of min/max */
  302.     setvector(p->bmin, INFTY, INFTY, INFTY);
  303.     vneg(p->bmax, p->bmin);
  304.  
  305.     p->text = NULL;
  306.     p->type = NOSHAPE;
  307.     p->bound = NULL;
  308.     p->clip = NULL;
  309.     p->methods = &null_methods;
  310.     p->daddy = NULL;
  311.     p->next = NULL;
  312.     p->inv_trans = NULL;
  313.     p->inverted = FALSE;
  314. }
  315.  
  316. /* alloc and init an object */
  317. PUBLIC object  *
  318. get_new_object(void)
  319. {
  320.     object         *p;
  321.  
  322.     p = ALLOC(object);
  323.  
  324.     CHECK_MEM(p, "object");
  325.     init_object(p);
  326.     return p;
  327. }
  328.  
  329. /* std routine: rotate an object */
  330. PUBLIC void
  331. rotate_object(object *op, matrix rotmat)
  332. {
  333.     if (op->text != NULL)
  334.     rotate_texture(op->text, rotmat);
  335.  
  336.     op->methods->rotate_method(op, rotmat);
  337.  
  338.     rotate_vector(&op->speed, rotmat);
  339.  
  340.     if (op->bound != NULL)
  341.     rotate_object(op->bound, rotmat);
  342.     if (op->clip != NULL)
  343.     rotate_object(op->clip, rotmat);
  344.  
  345. }
  346.  
  347. /* translate an object */
  348. PUBLIC void
  349. translate_object(object *op, vector t)
  350. {
  351.     if (op->text != NULL)
  352.     translate_texture(op->text, t);
  353.  
  354.     op->methods->translate_method(op, t);
  355.  
  356.     if (op->bound != NULL)
  357.     translate_object(op->bound, t);
  358.     if (op->clip != NULL)
  359.     translate_object(op->clip, t);
  360. }
  361.  
  362. /* and scale it */
  363. PUBLIC void
  364. scale_object(object *op, vector s)
  365. {
  366.     op->methods->scale_method(op, s);
  367.  
  368.     if (op->text != NULL)
  369.     scale_texture(op->text, s);
  370.  
  371.     vcproduct(op->speed, op->speed, s);
  372.  
  373.     if (op->bound != NULL)
  374.     scale_object(op->bound, s);
  375.     if (op->clip != NULL)
  376.     scale_object(op->clip, s);
  377. }
  378.  
  379.  
  380. PUBLIC void
  381. generic_scale_object(object *o, vector s)
  382. {
  383.     matrix          m;
  384.  
  385.     if (o->inv_trans == NULL)
  386.     o->inv_trans = get_new_matrix();
  387.     inv_scale_matrix(m, s);
  388.     mmproduct(*o->inv_trans, *o->inv_trans, m);
  389. }
  390.  
  391. PUBLIC void
  392. generic_translate_object(object *o, vector t)
  393. {
  394.     matrix          m;
  395.  
  396.     if (o->inv_trans == NULL)
  397.     o->inv_trans = get_new_matrix();
  398.  
  399.     inv_translate_matrix(m, t);
  400.     mmproduct(*o->inv_trans, *o->inv_trans, m);
  401. }
  402.  
  403. PUBLIC void
  404. generic_rotate_object(object *o, matrix m)
  405. {
  406.     matrix          r;
  407.  
  408.     if (o->inv_trans == NULL)
  409.     o->inv_trans = get_new_matrix();
  410.     transpose_matrix(r, m);
  411.     mmproduct(*o->inv_trans, *o->inv_trans, r);
  412. }
  413.  
  414. /* give back memory used by an object */
  415. PUBLIC void
  416. free_object(object *op)
  417. {
  418.     if (op->text != NULL)
  419.     free_texture(op->text);
  420.     op->methods->free_method(op);
  421.     if (op->bound != NULL)
  422.     free_object_list(op->bound);
  423.     if (op->clip != NULL)
  424.     free_object_list(op->clip);
  425.     if (op->inv_trans != NULL)
  426.     free(op->inv_trans);
  427.  
  428.     free((void *) op);
  429. }
  430.  
  431. /* zap a list of objects */
  432. PUBLIC void
  433. free_object_list(object *p)
  434. {
  435.     object         *next;
  436.  
  437.     for (; p != NULL; p = next) {
  438.     next = p->next;
  439.     free_object(p);
  440.     }
  441. }
  442.  
  443. /* rotation */
  444. PUBLIC void
  445. rotate_object_list(object *p, matrix rotmat)
  446. {
  447.     for (; p != NULL; p = p->next)
  448.     rotate_object(p, rotmat);
  449. }
  450.  
  451. /* scaling */
  452. PUBLIC void
  453. scale_object_list(object *p, vector r)
  454. {
  455.     for (; p != NULL; p = p->next)
  456.     scale_object(p, r);
  457. }
  458.  
  459. /* translation */
  460. PUBLIC void
  461. translate_object_list(object *p, vector r)
  462. {
  463.     for (; p != NULL; p = p->next)
  464.     translate_object(p, r);
  465. }
  466.  
  467.  
  468. PUBLIC void
  469. print_object(object *obj)
  470. {
  471. #ifdef DEBUG
  472.     printf("(");
  473.     if (obj->bound != NULL) {
  474.     printf("{ BOUNDINGSHAPES:");
  475.     print_object_list(obj->bound);
  476.     printf("}");
  477.     }
  478.     printf("BBOX:\n");
  479.     print_v("  bound_min", obj->bmin);
  480.     print_v("  bound_max", obj->bmax);
  481.  
  482.     if (obj->clip != NULL) {
  483.     printf("{ CLIPPINGSHAPES:");
  484.     print_object_list(obj->clip);
  485.     printf("}");
  486.     }
  487.     if (obj->inv_trans != NULL) {
  488.     printf("Inverse Transformation\n");
  489.     print_matrix(*obj->inv_trans);
  490.     }
  491.     printf("shape type %d, %s%s\n", obj->type, (obj->inverted) ? "inverted " : "", obj->methods->name);
  492.  
  493.     obj->methods->print_method(obj);
  494.  
  495.     if (obj->text != NULL)
  496.     print_texture(obj->text);
  497.     print_v("speed", obj->speed);
  498.     printf(")\n\n");
  499. #endif
  500. }
  501.  
  502. PUBLIC void
  503. print_object_list(object *o)
  504. {
  505. #ifdef DEBUG
  506.     for (; o != NULL; o = o->next)
  507.     print_object(o);
  508. #endif
  509. }
  510.