home *** CD-ROM | disk | FTP | other *** search
- /*
- * plane.c -- infinite plane thingies.
- *
- * (c) 1993, 1994 by Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <stdlib.h>
- #include <math.h>
- #include "ray.h"
- #include "proto.h"
- #include "extern.h"
-
-
- extern struct methods my_methods;
-
- PRIVATE int intersect_plane(struct plane_data *p, struct ray *r, double *t);
-
- PRIVATE bool
- all_plane_intersections(dqueue * q, object *o, struct ray *r,
- int flags, bool *isinside)
- {
- dqueue q_ent;
- int no_int;
- vector sample;
-
- no_int = intersect_plane(o->data.plane, r, &q_ent.t);
-
- svproduct(sample, 2 * tolerance, r->dir);
- vadd(sample, sample, r->pos);
-
- *isinside = (vdot(sample, o->data.plane->n) < o->data.plane->mov) ^ o->inverted;
-
- if (no_int > 0) { /* found intersection? */
- q_ent.obj = o; /* store shape (so normal can be found
- * easily) */
- q_ent.entering = !*isinside;
- add_to_queue(q, q_ent);
- return TRUE;
- }
- return FALSE;
- }
-
- PRIVATE int
- intersect_plane(struct plane_data *p, struct ray *r, double *t)
- {
- double d;
-
-
- my_methods.test++;
-
- /* solve plane/ray equation: vdot(t*dir + pos, normal) = mov */
- d = vdot(p->n, r->dir);
-
- if (ISZERO(d)) /* plane is parallel with ray */
- return 0;
-
- *t = (p->mov - vdot(p->n, r->pos)) / d;
-
- if (*t < tolerance)
- return 0;
-
- my_methods.hit++;
-
- return 1;
- }
-
- PRIVATE vector
- plane_normal(struct intersect i, vector x)
- {
- return i.q_ent.obj->data.plane->n;
- }
-
- PRIVATE void
- translate_plane(object *o, vector v)
- {
- struct plane_data *d = o->data.plane;
-
- d->mov += vdot(v, d->n);
- }
-
- PRIVATE void
- rotate_plane(object *o, matrix rotmat)
- {
- struct plane_data *p = o->data.plane;
-
- rotate_vector(&p->n, rotmat);
- }
-
- PRIVATE bool
- inside_plane(object *o, vector x)
- {
- struct plane_data *p = o->data.plane;
-
- if (vdot(x, p->n) < p->mov) {
- return !o->inverted;
- } else {
- return o->inverted;
- }
- }
-
- /*
- * afgespiekt van pov source
- */
- PRIVATE void
- scale_plane(object *o, vector s)
- {
- struct plane_data *d = o->data.plane;
- double len;
-
- d->n.x = d->n.x / s.x;
- d->n.y = d->n.y / s.y;
- d->n.z = d->n.z / s.z;
-
- len = veclen(d->n);
- d->mov /= len;
-
- svproduct(d->n, 1 / len, d->n);
- }
-
- PRIVATE void
- init_plane(struct plane_data *p)
- {
- setvector(p->n, 0, 1, 0);
- p->mov = 0.0;
- }
-
- PRIVATE struct plane_data *
- get_new_plane(void)
- {
- struct plane_data *p;
- p = ALLOC(struct plane_data);
-
- CHECK_MEM(p, my_methods.name);
- init_plane(p);
-
- return p;
- }
-
- PRIVATE void
- copy_plane(object *dst, object *src)
- {
- assert(src != NULL && dst != NULL);
-
- if (dst->type != PLANE)
- dst->data.plane = get_new_plane();
- *dst->data.plane = *src->data.plane;
- dst->type = src->type;
- }
-
- PRIVATE void
- free_plane(object *o)
- {
- struct plane_data *p = o->data.plane;
-
- free((void *) p);
- }
-
- PRIVATE void
- print_plane(object *o)
- {
- #ifdef DEBUG
- struct plane_data *p = o->data.plane;
-
- print_v("normal", p->n);
- printf("translation %lf\n", p->mov);
- #endif
- }
-
- PRIVATE void
- precompute_plane(object *o)
- {
- my_methods.howmuch++;
- global_stats.prims++;
- }
-
- PRIVATE struct methods my_methods =
- {
- all_plane_intersections,
- plane_normal,
- copy_plane,
- inside_plane,
- rotate_plane,
- translate_plane,
- scale_plane,
- free_plane,
- print_plane,
-
- precompute_plane,
- "plane",
- };
-
- PUBLIC object *
- get_new_plane_object(void)
- {
- object *o;
-
- o = get_new_object();
-
- o->data.plane = get_new_plane();
- o->methods = &my_methods;
- o->type = PLANE;
-
- return o;
- }
-