| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735 |
- /*****************************************************************************
- * bbcyl.c
- *
- * This file contains all functions for bounding
- * cylinders used by lathe and sor objects.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996,1999 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file.
- * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by email to team-coord@povray.org or visit us on the web at
- * http://www.povray.org. The latest version of POV-Ray may be found at this site.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
- #include "bcyl.h"
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
- static int intersect_thick_cylinder (BCYL *BCyl, BCYL_ENTRY *Entry, DBL *dist);
- static void insert_hit (BCYL_INT *Element, BCYL_INT *intervals, int *cnt);
- static void intersect_bound_elements (BCYL *BCyl, VECTOR P, VECTOR D);
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_thick_cylinder
- *
- * INPUT
- *
- * BCyl - Pointer to lathe structure
- * Entry - Segment whos bounding cylinder to intersect
- * dist - List of sorted intersection depths
- *
- * OUTPUT
- *
- * RETURNS
- *
- * int - number of intersections found
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Find all intersections of the current ray with the bounding
- * cylinder of the given segment. The intersection tests are
- * done in intersect_bound_elements() and the results stored
- * in the lathe structure are evaluated here.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
- static int intersect_thick_cylinder(BCYL *BCyl, BCYL_ENTRY *Entry, DBL *dist)
- {
- int i, j, n;
- DBL k, r, h;
- n = 0;
- /* Intersect ray with the cap-plane. */
- if (BCyl->hint[Entry->h2].n)
- {
- r = BCyl->hint[Entry->h2].w[0];
- if ((r >= BCyl->radius[Entry->r1]) &&
- (r <= BCyl->radius[Entry->r2]))
- {
- dist[n++] = BCyl->hint[Entry->h2].d[0];
- }
- }
- /* Intersect ray with the base-plane. */
- if (BCyl->hint[Entry->h1].n)
- {
- r = BCyl->hint[Entry->h1].w[0];
- if ((r >= BCyl->radius[Entry->r1]) &&
- (r <= BCyl->radius[Entry->r2]))
- {
- dist[n++] = BCyl->hint[Entry->h1].d[0];
- }
- }
- /* Intersect with inner cylinder. */
- if (BCyl->rint[Entry->r1].n)
- {
- h = BCyl->rint[Entry->r1].w[0];
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r1].d[0];
- }
- h = BCyl->rint[Entry->r1].w[1];
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r1].d[1];
- }
- }
- /* Intersect with outer cylinder. */
- if (BCyl->rint[Entry->r2].n)
- {
- h = BCyl->rint[Entry->r2].w[0];
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r2].d[0];
- }
- h = BCyl->rint[Entry->r2].w[1];
- if ((h >= BCyl->height[Entry->h1]) &&
- (h <= BCyl->height[Entry->h2]))
- {
- dist[n++] = BCyl->rint[Entry->r2].d[1];
- }
- }
- /* Sort intersections. */
- for (i = 0; i < n; i++)
- {
- for (j = 0; j < n - i - 1; j++)
- {
- if (dist[j] > dist[j+1])
- {
- k = dist[j];
- dist[j] = dist[j+1];
- dist[j+1] = k;
- }
- }
- }
- return(n);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * intersect_bound_elements
- *
- * INPUT
- *
- * BCyl - Pointer to lathe structure
- * P, D - Current ray
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Intersect all bounding discs and cylinders and store
- * the intersections found in the lathe structure.
- *
- * By intersecting all different discs and cylinders once
- * we avoid testing the same cylinders and discs more than
- * once. This happened when we tested one bounding cylinder
- * after the other.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
- static void intersect_bound_elements(BCYL *BCyl, VECTOR P, VECTOR D)
- {
- int i;
- DBL a, b, bb, b2, c, d, k;
- /* Init constants. */
- a = D[X] * D[X] + D[Z] * D[Z];
- b = P[X] * D[X] + P[Z] * D[Z];
- bb = b * b;
- b2 = 2.0 * b;
- c = P[X] * P[X] + P[Z] * P[Z];
- /* Intersect all rings. */
- if ((D[Y] < -EPSILON) || (D[Y] > EPSILON))
- {
- for (i = 0; i < BCyl->nheight; i++)
- {
- k = (BCyl->height[i] - P[Y]) / D[Y];
- BCyl->hint[i].n = 1;
- BCyl->hint[i].d[0] = k;
- BCyl->hint[i].w[0] = k * (a * k + b2) + c;
- }
- }
- else
- {
- for (i = 0; i < BCyl->nheight; i++)
- {
- BCyl->hint[i].n = 0;
- }
- }
- /* Intersect all cylinders. */
- for (i = 0; i < BCyl->nradius; i++)
- {
- BCyl->rint[i].n = 0;
- if (BCyl->radius[i] > EPSILON)
- {
- d = bb - a * (c - BCyl->radius[i]);
- if (d > 0.0)
- {
- d = sqrt(d);
- k = (-b + d) / a;
- BCyl->rint[i].n = 2;
- BCyl->rint[i].d[0] = k;
- BCyl->rint[i].w[0] = P[Y] + k * D[Y];
- k = (-b - d) / a;
- BCyl->rint[i].d[1] = k;
- BCyl->rint[i].w[1] = P[Y] + k * D[Y];
- }
- }
- }
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * insert_hit
- *
- * INPUT
- *
- * element - Intersection to insert
- * intervals - List of intervals
- * cnt - Number of elements in the list
- *
- * OUTPUT
- *
- * intervals, cnt
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Insert an intersection into the depth sorted intersection list.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
- static void insert_hit(BCYL_INT *element, BCYL_INT *intervals, int *cnt)
- {
- int k;
- intervals[*cnt] = *element;
- for (k = 0; element->d[0] > intervals[k].d[0]; k++);
- if (k < *cnt)
- {
- POV_MEMMOVE(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(BCYL_INT));
- intervals[k] = *element;
- }
- (*cnt)++;
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Intersect_All_Bounds
- *
- * INPUT
- *
- * BCyl - Pointer to lathe structure
- * P, D - Current ray
- * intervals - List of intervals
- * cnt - Number of elements in the list
- *
- * OUTPUT
- *
- * intervals, cnt
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Intersect given ray with all bounding cylinders of the given lathe
- * and return a sorted list of intersection depths and segments hit.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
- int Intersect_BCyl(BCYL *BCyl, VECTOR P, VECTOR D)
- {
- int i, cnt;
- DBL dist[8];
- BCYL_INT Inter;
- BCYL_INT *intervals;
- BCYL_ENTRY *Entry;
- cnt = 0;
- Inter.d[1] = 0.0;
- /* Intersect all cylinder and plane elements. */
- intersect_bound_elements(BCyl, P, D);
- /* Intersect all spline segments. */
- intervals = BCyl->intervals;
- for (i = 0; i < BCyl->number; i++)
- {
- Entry = &BCyl->entry[i];
- switch (intersect_thick_cylinder(BCyl, Entry, dist))
- {
- case 0:
- break;
- case 2:
- if (dist[0] > EPSILON)
- {
- Inter.d[0] = dist[0];
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[1] > EPSILON)
- {
- Inter.d[0] = 0.0;
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- }
- }
- break;
- case 4:
- if (dist[0] > EPSILON)
- {
- Inter.d[0] = dist[0];
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[1] > EPSILON)
- {
- Inter.d[0] = 0.0;
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[2] > EPSILON)
- {
- Inter.d[0] = dist[2];
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- }
- else
- {
- if (dist[3] > EPSILON)
- {
- Inter.d[0] = 0.0;
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- }
- }
- }
- }
- break;
- default:
- /*
- * We weren't able to find an even number of intersections. Thus
- * we can't tell where the ray enters and leaves the bounding
- * cylinder. To avoid problems we assume that the ray is always
- * inside the cylinder in that case.
- */
- Inter.d[0] = dist[0];
- Inter.n = i;
- insert_hit(&Inter, intervals, &cnt);
- break;
- }
- }
- return(cnt);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_BCyl
- *
- * INPUT
- *
- * number - number of cylindrical segments
- * r1, r2 - list of segment radii
- * h1, h2 - list of segment heights
- *
- * OUTPUT
- *
- * RETURNS
- *
- * BCYL * - created bounding cylinder.
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Create a bounding cylinder data structure from the given
- * radii and heights.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
- BCYL *Create_BCyl(int number, DBL *tmp_r1, DBL *tmp_r2, DBL *tmp_h1, DBL *tmp_h2)
- {
- int i, j, nr, nh;
- int *tmp_r1_index;
- int *tmp_r2_index;
- int *tmp_h1_index;
- int *tmp_h2_index;
- DBL *tmp_radius;
- DBL *tmp_height;
- BCYL *bcyl;
- /* Allocate bounding cylinder. */
- bcyl = (BCYL *)POV_MALLOC(sizeof(BCYL), "bounding cylinder");
- /* Allocate entries. */
- bcyl->number = number;
- bcyl->entry = (BCYL_ENTRY *)POV_MALLOC(bcyl->number*sizeof(BCYL_ENTRY), "bounding cylinder data");
- /* Allocate intersection lists. */
- bcyl->hint = (BCYL_INT *)POV_MALLOC(2*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
- bcyl->rint = (BCYL_INT *)POV_MALLOC(2*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
- bcyl->intervals = (BCYL_INT *)POV_MALLOC(4*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
- /* Allocate temporary lists. */
- tmp_r1_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_r2_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_h1_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_h2_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
- tmp_radius = (DBL *)POV_MALLOC(2 * bcyl->number * sizeof(DBL), "temp lathe data");
- tmp_height = (DBL *)POV_MALLOC(2 * bcyl->number * sizeof(DBL), "temp lathe data");
- /* Get different bounding radii and heights. */
- nr = 0;
- nh = 0;
- for (i = 0; i < bcyl->number; i++)
- {
- tmp_r1_index[i] = -1;
- tmp_r2_index[i] = -1;
- tmp_h1_index[i] = -1;
- tmp_h2_index[i] = -1;
- for (j = 0; j < nr; j++)
- {
- if (tmp_r1[i] == tmp_radius[j])
- {
- break;
- }
- }
- if (j == nr)
- {
- tmp_radius[nr++] = tmp_r1[i];
- }
- tmp_r1_index[i] = j;
- for (j = 0; j < nr; j++)
- {
- if (tmp_r2[i] == tmp_radius[j])
- {
- break;
- }
- }
- if (j == nr)
- {
- tmp_radius[nr++] = tmp_r2[i];
- }
- tmp_r2_index[i] = j;
- for (j = 0; j < nh; j++)
- {
- if (tmp_h1[i] == tmp_height[j])
- {
- break;
- }
- }
- if (j == nh)
- {
- tmp_height[nh++] = tmp_h1[i];
- }
- tmp_h1_index[i] = j;
- for (j = 0; j < nh; j++)
- {
- if (tmp_h2[i] == tmp_height[j])
- {
- break;
- }
- }
- if (j == nh)
- {
- tmp_height[nh++] = tmp_h2[i];
- }
- tmp_h2_index[i] = j;
- }
- /* Copy lists into the lathe. */
- bcyl->radius = (DBL *)POV_MALLOC(nr * sizeof(DBL), "bounding cylinder data");
- bcyl->height = (DBL *)POV_MALLOC(nh * sizeof(DBL), "bounding cylinder data");
- for (i = 0; i < nr; i++)
- {
- bcyl->radius[i] = Sqr(tmp_radius[i]);
- }
- for (i = 0; i < nh; i++)
- {
- bcyl->height[i] = tmp_height[i];
- }
- /* Assign height and radius indices. */
- bcyl->nradius = nr;
- bcyl->nheight = nh;
- for (i = 0; i < bcyl->number; i++)
- {
- bcyl->entry[i].r1 = tmp_r1_index[i];
- bcyl->entry[i].r2 = tmp_r2_index[i];
- bcyl->entry[i].h1 = tmp_h1_index[i];
- bcyl->entry[i].h2 = tmp_h2_index[i];
- }
- /*
- fprintf(stderr, "number of different radii = %d\n", nr);
- fprintf(stderr, "number of different heights = %d\n", nh);
- */
- /* Get rid of temp. memory. */
- POV_FREE(tmp_height);
- POV_FREE(tmp_radius);
- POV_FREE(tmp_h2_index);
- POV_FREE(tmp_h1_index);
- POV_FREE(tmp_r2_index);
- POV_FREE(tmp_r1_index);
- return(bcyl);
- }
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_BCyl
- *
- * INPUT
- *
- * BCyl - bounding cylinder
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dieter Bayer
- *
- * DESCRIPTION
- *
- * Destroy a bounding cylinder.
- *
- * CHANGES
- *
- * Oct 1996 : Creation.
- *
- ******************************************************************************/
- void Destroy_BCyl(BCYL *BCyl)
- {
- POV_FREE(BCyl->entry);
- POV_FREE(BCyl->radius);
- POV_FREE(BCyl->height);
- POV_FREE(BCyl->rint);
- POV_FREE(BCyl->hint);
- POV_FREE(BCyl->intervals);
- POV_FREE(BCyl);
- }
|