home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume21 / rayshade / part17 < prev    next >
Text File  |  1991-07-21  |  40KB  |  1,690 lines

  1. Newsgroups: comp.sources.misc
  2. From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  3. Subject:  v21i020:  rayshade - A raytracing package for UNIX, Part17/19
  4. Message-ID: <1991Jul21.223416.3881@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: a4d125964e11af669e118c42f54e0e56
  6. Date: Sun, 21 Jul 1991 22:34:16 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  10. Posting-number: Volume 21, Issue 20
  11. Archive-name: rayshade/part17
  12. Environment: UNIX, !16BIT
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 17 (of 19)."
  21. # Contents:  libray/libobj/blob.c rayview/glmethods.c
  22. # Wrapped by kolb@woody on Wed Jul 17 17:57:00 1991
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'libray/libobj/blob.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'libray/libobj/blob.c'\"
  26. else
  27. echo shar: Extracting \"'libray/libobj/blob.c'\" \(18207 characters\)
  28. sed "s/^X//" >'libray/libobj/blob.c' <<'END_OF_FILE'
  29. X/*
  30. X * blob.c
  31. X *
  32. X * Copyright (C) 1990, 1991, Mark Podlipec, Craig E. Kolb
  33. X * All rights reserved.
  34. X *
  35. X * This software may be freely copied, modified, and redistributed
  36. X * provided that this copyright notice is preserved on all copies.
  37. X *
  38. X * You may not distribute this software, in whole or in part, as part of
  39. X * any commercial product without the express consent of the authors.
  40. X *
  41. X * There is no warranty or other guarantee of fitness of this software
  42. X * for any purpose.  It is provided solely "as is".
  43. X *
  44. X * $Id: blob.c,v 4.0 91/07/17 14:36:07 kolb Exp Locker: kolb $
  45. X *
  46. X * $Log:    blob.c,v $
  47. X * Revision 4.0  91/07/17  14:36:07  kolb
  48. X * Initial version.
  49. X * 
  50. X */
  51. X#include "geom.h"
  52. X#include "blob.h"
  53. X
  54. Xstatic Methods *iBlobMethods = NULL;
  55. Xstatic char blobName[] = "blob";
  56. X
  57. Xunsigned long BlobTests, BlobHits;
  58. X
  59. X/*
  60. X * Blob/Metaball Description
  61. X *
  62. X * In this implementation a Blob is made up of a threshold T, and a 
  63. X * group of 1 or more Metaballs.  Each metaball 'i'  is defined by 
  64. X * its position (xi,yi,zi), its radius ri, and its strength si.
  65. X * Around each Metaball is a density function di(Ri) defined by:
  66. X *
  67. X *         di(Ri) =  c4i * Ri^4  +  c2i * Ri^2  + c0i     0 <= Ri <= ri
  68. X *         di(Ri) =  0                                    ri < Ri 
  69. X *
  70. X * where
  71. X *       c4i  = si / (ri^4)
  72. X *       c2i  = -(2 * si) / (ri^2)
  73. X *       c0i  = si
  74. X *       Ri^2 is the distance from a point (x,y,z) to the center of
  75. X *            the Metaball - (xi,yi,zi).
  76. X *
  77. X * The density function looks sort of like a W (Float-u) with the 
  78. X * center hump crossing the d-axis at  si  and the two humps on the
  79. X * side being tangent to the R-axis at  -ri  and  +ri. Only the 
  80. X * range  [0,ri] is being used. 
  81. X * I chose this function so that derivative = 0  at the points  0 and +ri. 
  82. X * This keeps the surface smooth when the densities are added. I also 
  83. X * wanted no  Ri^3  and  Ri  terms, since the equations are easier to 
  84. X * solve without them. This led to the symmetry about the d-axis and
  85. X * the derivative being equal to zero at -ri as well.
  86. X *
  87. X * The surface of the Blob is defined by:
  88. X *
  89. X *
  90. X *                  N
  91. X *                 ---  
  92. X *      F(x,y,z) = \    di(Ri)  = T
  93. X *                 /
  94. X *                 ---
  95. X *                 i=0
  96. X *
  97. X * where
  98. X *
  99. X *     di(Ri)    is   given above
  100. X *     Ri^2      =    (x-xi)^2  +  (y-yi)^2  + (z-zi)^2
  101. X *      N        is   number of Metaballs in Blob
  102. X *      T        is   the threshold
  103. X *    (xi,yi,zi) is   the center of Metaball i
  104. X *
  105. X */
  106. X
  107. X/*****************************************************************************
  108. X * Create & return reference to a metaball.
  109. X */
  110. XBlob *
  111. XBlobCreate(T, mlist, npoints)
  112. XFloat T;
  113. XMetaList *mlist;
  114. Xint npoints;
  115. X{
  116. X    Blob *blob;
  117. X    int i;
  118. X    MetaList *cur;
  119. X
  120. X/* 
  121. X * There has to be at least one metaball in the blob.
  122. X * Note: if there's only one metaball, the blob 
  123. X * will be a sphere.
  124. X */
  125. X    if (npoints < 1)
  126. X    {
  127. X        RLerror(RL_WARN, "blob field not correct.\n");
  128. X        return (Blob *)NULL;
  129. X    }
  130. X
  131. X/*  
  132. X * Initialize primitive and Geom structures
  133. X */
  134. X    blob = (Blob *)Malloc(sizeof(Blob));
  135. X    blob->T = T;
  136. X    blob->list=(MetaVector *)
  137. X        Malloc( (unsigned)(npoints*sizeof(MetaVector)) );
  138. X    blob->num = npoints;
  139. X
  140. X/*
  141. X * Initialize Metaball list
  142. X */
  143. X    for(i=0;i<npoints;i++)
  144. X    {
  145. X        cur = mlist;
  146. X        if ( (cur->mvec.c0 < EPSILON) || (cur->mvec.rs < EPSILON) )
  147. X        {
  148. X            RLerror(RL_WARN,"Degenerate metaball in blob (sr).\n");
  149. X            return (Blob *)NULL;
  150. X        }
  151. X        /* store radius squared */
  152. X        blob->list[i].rs = cur->mvec.rs * cur->mvec.rs;
  153. X        /* Calculate and store coefficients for each metaball */
  154. X        blob->list[i].c0 = cur->mvec.c0;
  155. X        blob->list[i].c2 = -(2.0 * cur->mvec.c0) / blob->list[i].rs;
  156. X        blob->list[i].c4 = cur->mvec.c0 /
  157. X                (blob->list[i].rs * blob->list[i].rs);
  158. X        blob->list[i].x = cur->mvec.x;
  159. X        blob->list[i].y = cur->mvec.y;
  160. X        blob->list[i].z = cur->mvec.z;
  161. X        mlist = mlist->next;
  162. X        free((voidstar)cur);
  163. X    }
  164. X    /* 
  165. X     * Allocate room for Intersection Structures and
  166. X     * Allocate room for an array of pointers to point to
  167. X     * the Intersection Structures.
  168. X     */
  169. X    blob->ilist = (MetaInt *)Malloc( 2 * blob->num * sizeof(MetaInt));
  170. X    blob->iarr = (MetaInt **)Malloc( 2 * blob->num * sizeof(MetaInt *));
  171. X    return blob;
  172. X}
  173. X
  174. XMethods *
  175. XBlobMethods()
  176. X{
  177. X    if (iBlobMethods == (Methods *)NULL) {
  178. X        iBlobMethods = MethodsCreate();
  179. X        iBlobMethods->create = (GeomCreateFunc *)BlobCreate;
  180. X        iBlobMethods->methods = BlobMethods;
  181. X        iBlobMethods->name = BlobName;
  182. X        iBlobMethods->intersect = BlobIntersect;
  183. X        iBlobMethods->normal = BlobNormal;
  184. X        iBlobMethods->bounds = BlobBounds;
  185. X        iBlobMethods->stats = BlobStats;
  186. X        iBlobMethods->checkbounds = TRUE;
  187. X        iBlobMethods->closed = TRUE;
  188. X    }
  189. X    return iBlobMethods;
  190. X}
  191. X
  192. X/*****************************************************************************
  193. X * Function used by qsort() when sorting the Ray/Blob intersection list
  194. X */
  195. Xint
  196. XMetaCompare(A,B)
  197. Xchar *A,*B;
  198. X{
  199. X    MetaInt **AA,**BB;
  200. X
  201. X    AA = (MetaInt **) A;
  202. X    BB = (MetaInt **) B;
  203. X    if (AA[0]->bound == BB[0]->bound) return(0);
  204. X    if (AA[0]->bound <  BB[0]->bound) return(-1);
  205. X    return(1);  /* AA[0]->bound is > BB[0]->bound */
  206. X}
  207. X
  208. X/*****************************************************************************
  209. X * Ray/metaball intersection test.
  210. X */
  211. Xint
  212. XBlobIntersect(blob, ray, mindist, maxdist)
  213. XBlob *blob;
  214. XRay *ray;
  215. XFloat mindist, *maxdist;
  216. X{
  217. X    double c[5], s[4];
  218. X    Float dist;
  219. X    MetaInt *ilist,**iarr;
  220. X    register int i,j,inum;
  221. X    extern void qsort();
  222. X
  223. X    BlobTests++;
  224. X
  225. X    ilist = blob->ilist;
  226. X    iarr = blob->iarr;
  227. X
  228. X/*
  229. X * The first step in calculating the Ray/Blob intersection is to 
  230. X * divide the Ray into intervals such that only a fixed set of 
  231. X * Metaballs contribute to the density function along that interval. 
  232. X * This is done by finding the set of intersections between the Ray 
  233. X * and each Metaball's Sphere/Region of influence, which has a 
  234. X * radius  ri  and is centered at (xi,yi,zi).
  235. X * Intersection information is kept track of in the MetaInt 
  236. X * structure and consists of:
  237. X *
  238. X *   type    indicates whether this intersection is the start(R_START)
  239. X *           of a Region or the end(R_END) of one. 
  240. X *   pnt     the Metaball of this intersection
  241. X *   bound   the distance from Ray origin to this intersection
  242. X *
  243. X * This list is then sorted by  bound  and used later to find the Ray/Blob 
  244. X * intersection.
  245. X */
  246. X
  247. X    inum = 0;
  248. X    for(i=0; i < blob->num; i++)
  249. X    {
  250. X        register Float xadj, yadj, zadj;
  251. X        register Float b, t, rs;
  252. X        register Float dmin,dmax;
  253. X
  254. X        rs   = blob->list[i].rs;
  255. X        xadj = blob->list[i].x - ray->pos.x;
  256. X        yadj = blob->list[i].y - ray->pos.y;
  257. X        zadj = blob->list[i].z - ray->pos.z;
  258. X
  259. X    /*
  260. X     * Ray/Sphere of Influence intersection
  261. X     */
  262. X        b = xadj * ray->dir.x + yadj * ray->dir.y + zadj * ray->dir.z;
  263. X        t = b * b - xadj * xadj - yadj * yadj - zadj * zadj + rs;
  264. X
  265. X    /* 
  266. X     * don't except imaginary or single roots. A single root is a ray
  267. X     * tangent to the Metaball's Sphere/Region. The Metaball's
  268. X     * contribution to the overall density function at this point is
  269. X     * zero anyway.
  270. X     */
  271. X        if (t > 0.0) /* we have two roots */
  272. X        {
  273. X            t = sqrt(t);
  274. X            dmin = b - t;
  275. X    /* 
  276. X     * only interested in stuff in front of ray origin 
  277. X     */
  278. X            if (dmin < mindist) dmin = mindist;
  279. X            dmax = b + t;
  280. X            if (dmax > dmin) /* we have a valid Region */
  281. X            {
  282. X        /*
  283. X             * Initialize min/start and max/end Intersections Structures
  284. X             * for this Metaball
  285. X             */
  286. X                ilist[inum].type = R_START;
  287. X                ilist[inum].pnt = i;
  288. X                ilist[inum].bound = dmin;
  289. X                for(j=0;j<5;j++) ilist[inum].c[j] = 0.0;
  290. X                iarr[inum] = &(ilist[inum]);
  291. X                inum++;
  292. X
  293. X                ilist[inum].type = R_END;
  294. X                ilist[inum].pnt = i;
  295. X                ilist[inum].bound = dmax;
  296. X                for(j=0;j<5;j++) ilist[inum].c[j] = 0.0;
  297. X                iarr[inum] = &(ilist[inum]);
  298. X                inum++;
  299. X            } /* End of valid Region */
  300. X        } /* End of two roots */
  301. X    } /* End of loop through metaballs */
  302. X
  303. X    /*
  304. X     * If there are no Ray/Metaball intersections there will 
  305. X     * not be a Ray/Blob intersection. Exit now.
  306. X     */
  307. X    if (inum == 0)
  308. X    {
  309. X        return FALSE;
  310. X    }
  311. X
  312. X    /* 
  313. X     * Sort Intersection list. No sense using qsort if there's only
  314. X     * two intersections.
  315. X     *
  316. X     * Note: we actually aren't sorting the Intersection structures, but
  317. X     * an array of pointers to the Intersection structures. 
  318. X     * This is faster than sorting the Intersection structures themselves.
  319. X     */
  320. X    if (inum==2)
  321. X    {
  322. X        MetaInt *t;
  323. X        if (ilist[0].bound > ilist[1].bound)
  324. X        {
  325. X            t = iarr[0];
  326. X            iarr[0] = iarr[1];
  327. X            iarr[1] = t;
  328. X        }
  329. X    }
  330. X    else qsort((voidstar)(iarr), (unsigned)inum, sizeof(MetaInt *),
  331. X            MetaCompare);
  332. X
  333. X/*
  334. X* Finding the Ray/Blob Intersection
  335. X* 
  336. X* The non-zero part of the density function for each Metaball is
  337. X* 
  338. X*   di(Ri) = c4i * Ri^4  +  c2i * Ri^2  +  c0i 
  339. X*
  340. X* To find find the Ray/Blob intersection for one metaball
  341. X* substitute for distance   
  342. X*
  343. X*     Ri^2 = (x-xi)^2 + (y-yi)^2 + (z-zi)^2
  344. X* 
  345. X* and then substitute the Ray equations:
  346. X*   
  347. X*     x  = x0 + x1 * t
  348. X*     y  = y0 + y1 * t
  349. X*     z  = z0 + z1 * t
  350. X*
  351. X* to get a big mess :^). Actually, it's a Quartic in t and it's fully 
  352. X* listed farther down. Here's a short version:
  353. X*
  354. X*   c[4] * t^4  +  c[3] * t^3  +  c[2] * t^2  +  c[1] * t  +  c[0]  =  T
  355. X*
  356. X* Don't forget that the Blob is defined by the density being equal to 
  357. X* the threshold T.
  358. X* To calculate the intersection of a Ray and two or more Metaballs, 
  359. X* the coefficients are calculated for each Metaball and then added 
  360. X* together. We can do this since we're working with polynomials.
  361. X* The points of intersection are the roots of the resultant equation.
  362. X*
  363. X* The algorithm loops through the intersection list, calculating
  364. X* the coefficients if an intersection is the start of a Region and 
  365. X* adding them to all intersections in that region.
  366. X* When it detects a valid interval, it calculates the 
  367. X* roots from the starting intersection's coefficients and if any of 
  368. X* the roots are in the interval, the smallest one is returned.
  369. X*
  370. X*/
  371. X
  372. X    {
  373. X        register Float *tmpc;
  374. X        MetaInt *strt,*tmp;
  375. X        register int istrt,itmp;
  376. X        register int num,exitflag,inside;
  377. X
  378. X    /*
  379. X     * Start the algorithm outside the first interval
  380. X     */
  381. X        inside = 0;
  382. X        istrt = 0; 
  383. X        strt = iarr[istrt];
  384. X        if (strt->type != R_START)
  385. X            RLerror(RL_WARN,"MetaInt sanity check FAILED!\n");
  386. X
  387. X        /*
  388. X         * Loop through intersection. If a root is found the code
  389. X         * will return at that point.
  390. X         */
  391. X        while( istrt < inum )
  392. X        {
  393. X            /* 
  394. X             * Check for multiple intersections  at the same point.
  395. X             * This is also where the coefficients are calculated
  396. X             * and spread throughout that Metaball's sphere of
  397. X             * influence.
  398. X             */
  399. X            do
  400. X            {
  401. X                /* find out which metaball */
  402. X                i = strt->pnt;
  403. X                /* only at starting boundaries do this */
  404. X                if (strt->type == R_START)
  405. X                {
  406. X                    register MetaVector *ml;
  407. X                    register Float a1,a0;
  408. X                    register Float xd,yd,zd;
  409. X                    register Float c4,c2,c0;
  410. X
  411. X                    /* we're inside */
  412. X                    inside++;
  413. X
  414. X    /*  As promised, the full equations
  415. X     *
  416. X     *   c[4] = c4*a2*a2; 
  417. X     *   c[3] = 4.0*c4*a1*a2;
  418. X     *   c[2] = 4.0*c4*a1*a1 + 2.0*c4*a2*a0 + c2*a2;
  419. X     *   c[1] = 4.0*c4*a1*a0 + 2.0*c2*a1;
  420. X     *   c[0] = c4*a0*a0 + c2*a0 + c0;
  421. X     *
  422. X     * where
  423. X     *        a2 = (x1*x1 + y1*y1 + z1*z1) = 1.0 because the ray 
  424. X     *                                           is normalized
  425. X     *        a1 = (xd*x1 + yd*y1 + zd*z1)
  426. X     *        a0 = (xd*xd + yd*yd + zd*zd)
  427. X     *        xd = (x0 - xi)
  428. X     *        yd = (y0 - yi)
  429. X     *        zd = (z0 - zi)
  430. X     *        (xi,yi,zi) is center of Metaball
  431. X     *        (x0,y0,z0) is Ray origin
  432. X     *        (x1,y1,z1) is normalized Ray direction
  433. X     *        c4,c2,c0   are the coefficients for the
  434. X     *                       Metaball's density function
  435. X     *
  436. X     */
  437. X
  438. X                    /*
  439. X                     * Some compilers would recalculate
  440. X                     * this each time its used.
  441. X                     */
  442. X                    ml = &(blob->list[i]);
  443. X
  444. X                    xd = ray->pos.x - ml->x;
  445. X                    yd = ray->pos.y - ml->y;
  446. X                    zd = ray->pos.z - ml->z;
  447. X                    a1 = (xd * ray->dir.x + yd * ray->dir.y
  448. X                        + zd * ray->dir.z);
  449. X                    a0 = (xd * xd + yd * yd + zd * zd);
  450. X
  451. X                    c0 = ml->c0;
  452. X                    c2 = ml->c2;
  453. X                    c4 = ml->c4;
  454. X
  455. X                    c[4] = c4;
  456. X                    c[3] = 4.0*c4*a1;
  457. X                    c[2] = 2.0*c4*(2.0*a1*a1 + a0) + c2;
  458. X                    c[1] = 2.0*a1*(2.0*c4*a0 + c2);
  459. X                    c[0] = c4*a0*a0 + c2*a0 + c0;
  460. X
  461. X        /* 
  462. X         * Since we've gone through the trouble of calculating the 
  463. X         * coefficients, put them where they'll be used.
  464. X         * Starting at the current intersection(It's also the start of
  465. X         * a region), add the coefficients to each intersection until
  466. X         * we reach the end of this region.
  467. X         */
  468. X                    itmp = istrt; 
  469. X                    tmp = strt;
  470. X                    while( (tmp->pnt != i) ||
  471. X                           (tmp->type != R_END) )
  472. X                    {
  473. X                        tmpc = tmp->c;
  474. X                        for(j=0;j<5;j++)
  475. X                            *tmpc++ += c[j];
  476. X                        itmp++; 
  477. X                        tmp = iarr[itmp];
  478. X                    }
  479. X
  480. X                } /* End of start of a Region */ 
  481. X                /* 
  482. X                 * Since the intersection wasn't the start
  483. X                 * of a region, it must the end of one.
  484. X                 */
  485. X                else inside--;
  486. X
  487. X        /*
  488. X         * If we are inside a region(or regions) and the next
  489. X         * intersection is not at the same place, then we have
  490. X         * the start of an interval. Set the exitflag.
  491. X         */
  492. X                if ((inside > 0)
  493. X                    && (strt->bound != iarr[istrt+1]->bound) )
  494. X                    exitflag = 1;
  495. X                else 
  496. X                /* move to next intersection */
  497. X                {
  498. X                    istrt++; 
  499. X                    strt = iarr[istrt];
  500. X                    exitflag = 0;
  501. X                }
  502. X        /* 
  503. X         * Check to see if we're at the end. If so then exit with
  504. X         * no intersection found.
  505. X         */
  506. X                if (istrt >= inum)
  507. X                {
  508. X                    return FALSE;
  509. X                }
  510. X            } while(!exitflag);
  511. X                /* End of Search for valid interval */
  512. X
  513. X        /*
  514. X         * Find Roots along this interval
  515. X         */
  516. X
  517. X            /* get coefficients from Intersection structure */
  518. X            tmpc = strt->c;
  519. X            for(j=0;j<5;j++) c[j] = *tmpc++;
  520. X
  521. X            /* Don't forget to put in threshold */
  522. X            c[0] -= blob->T;
  523. X
  524. X            /* Use Graphic Gem's Quartic Root Finder */
  525. X            num = SolveQuartic(c,s);
  526. X
  527. X        /*
  528. X         * If there are roots, search for roots within the interval.
  529. X         */
  530. X            dist = 0.0;
  531. X            if (num>0)
  532. X            {
  533. X                for(j=0;j<num;j++)
  534. X                {
  535. X        /* 
  536. X         * Not sure if EPSILON is truly needed, but it might cause
  537. X         * small cracks between intervals in some cases. In any case 
  538. X         * I don't believe it hurts.
  539. X         */
  540. X                    if ((s[j] >= (strt->bound - EPSILON))
  541. X                        && (s[j] <= (iarr[istrt+1]->bound +
  542. X                            EPSILON) ) )
  543. X                    {
  544. X                        if (dist == 0.0)
  545. X                        /* first valid root */
  546. X                            dist = s[j];
  547. X                        else if (s[j] < dist)
  548. X                         /* else only if smaller */
  549. X                            dist = s[j];
  550. X                    }
  551. X                }
  552. X                /*
  553. X                 * Found a valid root 
  554. X                 */
  555. X                if (dist > mindist && dist < *maxdist)
  556. X                {
  557. X                    *maxdist = dist;
  558. X                    BlobHits++;
  559. X                    return TRUE;
  560. X                    /* Yeah! Return valid root */
  561. X                }
  562. X            }
  563. X
  564. X        /* 
  565. X         * Move to next intersection
  566. X         */
  567. X            istrt++;
  568. X            strt = iarr[istrt];
  569. X
  570. X        } /* End of loop through Intersection List */
  571. X    } /* End of Solving for Ray/Blob Intersection */
  572. X
  573. X    /* 
  574. X     * return negative
  575. X     */
  576. X    return FALSE;
  577. X}
  578. X
  579. X
  580. X/***********************************************
  581. X * Find the Normal of a Blob at a given point
  582. X *
  583. X * The normal of a surface at a point (x0,y0,z0) is the gradient of that
  584. X * surface at that point. The gradient is the vector 
  585. X *
  586. X *            Fx(x0,y0,z0) , Fy(x0,y0,z0) , Fz(x0,y0,z0)
  587. X *
  588. X * where Fx(),Fy(),Fz() are the partial dervitives of F() with respect
  589. X * to x,y and z respectively. Since the surface of a Blob is made up
  590. X * of the sum of one or more polynomials, the normal of a Blob at a point
  591. X * is the sum of the gradients of the individual polynomials at that point.
  592. X * The individual polynomials in this case are di(Ri) i = 0,...,num .
  593. X *
  594. X * To find the gradient of the contributing polynomials
  595. X * take di(Ri) and substitute U = Ri^2;
  596. X *
  597. X *      di(U)    = c4i * U^2  +  c2i * U  + c0i
  598. X *
  599. X *      dix(U)   = 2 * c4i * Ux * U  +  c2i * Ux
  600. X *
  601. X *        U      = (x-xi)^2 + (y-yi)^2 + (z-zi)^2 
  602. X *
  603. X *        Ux     = 2 * (x-xi) 
  604. X *
  605. X * Rearranging we get
  606. X *  
  607. X *    dix(x0,y0,z0) = 4 * c4i * xdi * disti + 2 * c2i * xdi
  608. X *    diy(x0,y0,z0) = 4 * c4i * ydi * disti + 2 * c2i * ydi
  609. X *    diz(x0,y0,z0) = 4 * c4i * zdi * disti + 2 * c2i * zdi
  610. X * 
  611. X * where
  612. X *         xdi       =   x0-xi
  613. X *         ydi       =   y0-yi
  614. X *         zdi       =   y0-yi
  615. X *        disti      =   xdi*xdi + ydi*ydi + zdi*zdi   
  616. X *       (xi,yi,zi)  is  the center of Metaball i
  617. X *       c4i,c2i,c0i are the coefficients of Metaball i's density function
  618. X */
  619. Xint
  620. XBlobNormal(blob, pos, nrm, gnrm)
  621. XBlob *blob;
  622. XVector *pos, *nrm, *gnrm;
  623. X{
  624. X    register int i;
  625. X
  626. X    /*  
  627. X     * Initialize normals to zero 
  628. X     */
  629. X    nrm->x = nrm->y = nrm->z = 0.0;
  630. X    /*
  631. X     * Loop through Metaballs. If the point is within a Metaball's
  632. X     * Sphere of influence, calculate the gradient and add it to the
  633. X     * normals
  634. X     */
  635. X    for(i=0;i < blob->num; i++)
  636. X    {
  637. X        register MetaVector *sl;
  638. X        register Float dist,xd,yd,zd;
  639. X
  640. X        sl = &(blob->list[i]);
  641. X        xd = pos->x - sl->x;
  642. X        yd = pos->y - sl->y;
  643. X        zd = pos->z - sl->z;
  644. X
  645. X        dist  = xd*xd + yd*yd + zd*zd;
  646. X        if (dist <= sl->rs )
  647. X        {
  648. X            register Float temp;
  649. X
  650. X            /* temp is negative so normal points out of blob */
  651. X            temp = -2.0 * (2.0 * sl->c4 * dist  +  sl->c2);
  652. X            nrm->x += xd * temp;
  653. X            nrm->y += yd * temp;
  654. X            nrm->z += zd * temp;
  655. X
  656. X        }
  657. X    }
  658. X    (void)VecNormalize(nrm);
  659. X    *gnrm = *nrm;
  660. X    return FALSE;
  661. X}
  662. X
  663. X
  664. X/*****************************************************************************
  665. X * Calculate the extent of the Blob
  666. X */
  667. Xvoid
  668. XBlobBounds(blob, bounds)
  669. XBlob *blob;
  670. XFloat bounds[2][3];
  671. X{
  672. X    Float r;
  673. X    Float minx,miny,minz,maxx,maxy,maxz;
  674. X    int i;
  675. X
  676. X    /*
  677. X     * Loop through Metaballs to find the minimun and maximum in each
  678. X     * direction.
  679. X     */
  680. X    for( i=0;  i< blob->num;  i++)
  681. X    {
  682. X        register Float d;
  683. X
  684. X        r = sqrt(blob->list[i].rs);
  685. X        if (i==0)
  686. X        {
  687. X            minx = blob->list[i].x - r;
  688. X            miny = blob->list[i].y - r;
  689. X            minz = blob->list[i].z - r;
  690. X            maxx = blob->list[i].x + r;
  691. X            maxy = blob->list[i].y + r;
  692. X            maxz = blob->list[i].z + r;
  693. X        }
  694. X        else
  695. X        {
  696. X            d = blob->list[i].x - r; 
  697. X            if (d<minx) minx = d;
  698. X            d = blob->list[i].y - r; 
  699. X            if (d<miny) miny = d;
  700. X            d = blob->list[i].z - r; 
  701. X            if (d<minz) minz = d;
  702. X            d = blob->list[i].x + r; 
  703. X            if (d>maxx) maxx = d;
  704. X            d = blob->list[i].y + r; 
  705. X            if (d>maxy) maxy = d;
  706. X            d = blob->list[i].z + r; 
  707. X            if (d>maxz) maxz = d;
  708. X        }
  709. X    }
  710. X    bounds[LOW][X]  = minx;
  711. X    bounds[HIGH][X] = maxx;
  712. X    bounds[LOW][Y]  = miny;
  713. X    bounds[HIGH][Y] = maxy;
  714. X    bounds[LOW][Z]  = minz;
  715. X    bounds[HIGH][Z] = maxz;
  716. X}
  717. X
  718. Xchar *
  719. XBlobName()
  720. X{
  721. X    return blobName;
  722. X}
  723. X
  724. Xvoid
  725. XBlobStats(tests, hits)
  726. Xunsigned long *tests, *hits;
  727. X{
  728. X    *tests = BlobTests;
  729. X    *hits = BlobHits;
  730. X}
  731. X
  732. Xvoid
  733. XBlobMethodRegister(meth)
  734. XUserMethodType meth;
  735. X{
  736. X    if (iBlobMethods)
  737. X        iBlobMethods->user = meth;
  738. X}
  739. END_OF_FILE
  740. if test 18207 -ne `wc -c <'libray/libobj/blob.c'`; then
  741.     echo shar: \"'libray/libobj/blob.c'\" unpacked with wrong size!
  742. fi
  743. # end of 'libray/libobj/blob.c'
  744. fi
  745. if test -f 'rayview/glmethods.c' -a "${1}" != "-c" ; then 
  746.   echo shar: Will not clobber existing file \"'rayview/glmethods.c'\"
  747. else
  748. echo shar: Extracting \"'rayview/glmethods.c'\" \(17863 characters\)
  749. sed "s/^X//" >'rayview/glmethods.c' <<'END_OF_FILE'
  750. X/*
  751. X * glmethods.c
  752. X *
  753. X * Support routines for SGI/RS6000 machines.
  754. X *
  755. X * Copyright (C) 1989, 1991, Craig E. Kolb, Allan Snyder
  756. X *
  757. X * This software may be freely copied, modified, and redistributed
  758. X * provided that this copyright notice is preserved on all copies.
  759. X *
  760. X * You may not distribute this software, in whole or in part, as part of
  761. X * any commercial product without the express consent of the authors.
  762. X * 
  763. X * There is no warranty or other guarantee of fitness of this software
  764. X * for any purpose.  It is provided solely "as is".
  765. X *
  766. X * $Id: glmethods.c,v 4.0 91/07/17 17:38:43 kolb Exp Locker: kolb $
  767. X *
  768. X * $Log:    glmethods.c,v $
  769. X * Revision 4.0  91/07/17  17:38:43  kolb
  770. X * Initial version
  771. X * 
  772. X */
  773. X#include <gl.h>
  774. X#include <device.h>
  775. X#include "rayshade.h" 
  776. X#include "options.h"
  777. X#include "viewing.h"
  778. X
  779. X#include "libsurf/surface.h"
  780. X
  781. X#include "libobj/box.h"
  782. X#include "libobj/cone.h"
  783. X#include "libobj/csg.h"
  784. X#include "libobj/cylinder.h"
  785. X#include "libobj/disc.h"
  786. X#include "libobj/grid.h"
  787. X#include "libobj/instance.h"
  788. X#include "libobj/list.h"
  789. X#include "libobj/plane.h"
  790. X#include "libobj/poly.h"
  791. X#include "libobj/sphere.h"
  792. X#include "libobj/triangle.h"
  793. X
  794. X#include "liblight/light.h"
  795. X#include "liblight/extended.h"
  796. X#include "liblight/infinite.h"
  797. X#include "liblight/point.h"
  798. X#include "liblight/spot.h"
  799. X
  800. X#define CIRCLE_SAMPLES    20    /* # of samples around circle (cone/cyl/etc) */
  801. X#define DEFAULT_NEAR    .2    /* default value for near clipping plane */
  802. X#define DEFAULT_FAR    350.    /* default far clipping plane */
  803. X#define PLANE_RAD    450.    /* radius of disc used to represent planes */
  804. X
  805. X#ifndef SPHERELIB
  806. X#define SPHERE_LEVEL    3
  807. X#endif
  808. X
  809. X/*
  810. X * Pass a normal stored in a Vector to the geometry pipeline.
  811. X */
  812. X#define GLNormal(w)    (glnrm[0] = (w)->x, glnrm[1] = (w)->y, \
  813. X             glnrm[2] = (w)->z, n3f(glnrm))
  814. X
  815. Xstatic void    GLBoxDraw(), GLConeDraw(), GLCsgDraw(), GLCylinderDraw(),
  816. X        GLDiscDraw(),
  817. X        GLGridDraw(), GLHfDraw(), GLInstanceDraw(),    
  818. X        GLListDraw(), GLPlaneDraw(), GLPolygonDraw(),
  819. X        GLSphereDraw(), GLTorusDraw(), GLTriangleDraw(),
  820. X        GLBoundsDraw(),
  821. X        GLInfiniteLight(), GLPointLight(), GLSpotLight(),
  822. X        GLExtendedLight();
  823. X
  824. Xstatic short    cursurf = 1,
  825. X        curlight = 1;
  826. X
  827. Xstatic Object    GLBoxObject,
  828. X        GLCylObject,
  829. X        GLSphereObject,
  830. X        GLBoxObjectDefine(),
  831. X        GLCylObjectDefine();
  832. X
  833. Xextern Object    GLSphereObjectDefine();
  834. X
  835. Xstatic int    Doublebuffered;
  836. X
  837. Xstatic float    Ident[4][4] =    {1., 0., 0., 0.,
  838. X                 0., 1., 0., 0.,
  839. X                 0., 0., 1., 0.,
  840. X                 0., 0., 0., 1.},
  841. X        glnrm[3];
  842. X
  843. Xstatic float **CirclePoints;
  844. X
  845. Xstatic void LightDraw(), GeomDraw(), GLMultMatrix(),
  846. X        GLPushSurface(), GLPopSurface(), LightDrawInit(),
  847. X        ObjectInit(), GLDrawFrame(), ScreenDrawInit(), DrawInit(),
  848. X        GLUnitCircle(), GLDisc(), ComputeClippingPlanes();
  849. X
  850. XFloat CurrentTime;
  851. X
  852. Xstatic unsigned long BackPack;    /* Packed background color */
  853. Xstatic long Zinit;        /* maximum Zbuffer value */
  854. X
  855. XMethodsRegister()
  856. X{
  857. X    BoxMethodRegister(GLBoxDraw);
  858. X    ConeMethodRegister(GLConeDraw);
  859. X    CsgMethodRegister(GLCsgDraw);
  860. X    CylinderMethodRegister(GLCylinderDraw);
  861. X    DiscMethodRegister(GLDiscDraw);
  862. X    GridMethodRegister(GLGridDraw);
  863. X    /*HfMethodRegister(GLHfDraw);*/
  864. X    InstanceMethodRegister(GLInstanceDraw);
  865. X    ListMethodRegister(GLListDraw);
  866. X    PlaneMethodRegister(GLPlaneDraw);
  867. X    PolygonMethodRegister(GLPolygonDraw);
  868. X    SphereMethodRegister(GLSphereDraw);
  869. X    /* Have to write sphere routine for RS6000... */
  870. X    /*TorusMethodRegister(GLTorusDraw);*/
  871. X    TriangleMethodRegister(GLTriangleDraw);
  872. X
  873. X    InfiniteMethodRegister(GLInfiniteLight);
  874. X    PointMethodRegister(GLPointLight);
  875. X    ExtendedMethodRegister(GLExtendedLight);
  876. X    SpotMethodRegister(GLSpotLight);
  877. X}
  878. X
  879. Xvoid
  880. XRender()
  881. X{
  882. X    short val;
  883. X    float tmp;
  884. X
  885. X    DrawInit();
  886. X    qdevice(ESCKEY);
  887. X    qdevice(SPACEKEY);
  888. X    qdevice(REDRAW);
  889. X
  890. X    DrawFrames();
  891. X
  892. X    while (TRUE) {
  893. X        switch (qread(&val)) {
  894. X            case ESCKEY:
  895. X                exit(0);
  896. X                break;
  897. X            case REDRAW:
  898. X                reshapeviewport();
  899. X                DrawFrames();
  900. X                break;
  901. X            case SPACEKEY:
  902. X                if (!val)
  903. X                    DrawFrames();
  904. X                break;
  905. X        }
  906. X    }
  907. X}
  908. X
  909. XDrawFrames()
  910. X{
  911. X    int i;
  912. X    for (i = 0; i < Options.totalframes; i++)
  913. X        GLDrawFrame(i);
  914. X}
  915. X
  916. Xstatic void
  917. XDrawInit()
  918. X{
  919. X    extern Surface DefaultSurface;
  920. X
  921. X    ScreenDrawInit();
  922. X    ObjectInit();
  923. X    LightDrawInit();
  924. X    /*
  925. X     * Push the default surface.
  926. X     */
  927. X    GLPushSurface(&DefaultSurface);
  928. X}
  929. X
  930. Xstatic void
  931. XScreenDrawInit()
  932. X{
  933. X    /*
  934. X     * Open window, initialize graphics, etc.
  935. X     */
  936. X#ifdef sgi
  937. X    foreground();
  938. X#endif
  939. X    prefsize(Screen.xsize, Screen.ysize);
  940. X    winopen("rayview");
  941. X    RGBmode();
  942. X    mmode(MVIEWING);
  943. X
  944. X    if (Options.totalframes > 1) {
  945. X        Doublebuffered = TRUE;
  946. X        doublebuffer();
  947. X    }
  948. X
  949. X    gconfig();
  950. X    /*
  951. X     * Initialize viewing matrix.
  952. X     */
  953. X    GLViewingInit();
  954. X
  955. X    zbuffer(TRUE);
  956. X
  957. X    BackPack = (unsigned char)(255*Screen.background.r) |
  958. X        ((unsigned char)(255*Screen.background.g) << 8) |
  959. X        ((unsigned char)(255*Screen.background.b) << 16);
  960. X    Zinit = getgdesc(GD_ZMAX);
  961. X    lsetdepth(0, Zinit);
  962. X}
  963. X
  964. X/*
  965. X * Draw the World object.
  966. X */
  967. Xstatic void
  968. XGLDrawFrame(frame)
  969. Xint frame;
  970. X{
  971. X    extern Geom *World;
  972. X
  973. X    RSStartFrame(frame);
  974. X    CurrentTime = Options.framestart;
  975. X    TimeSet(CurrentTime);
  976. X
  977. X    czclear(BackPack, Zinit);    
  978. X
  979. X    /*
  980. X     * Draw the World object
  981. X     */
  982. X    GeomDraw(World);
  983. X    if (Doublebuffered)
  984. X        swapbuffers();
  985. X}
  986. X
  987. XGLViewingInit()
  988. X{
  989. X    float near, far, aspect, dist, T[4][4];
  990. X    short ang;
  991. X    extern Geom *World;
  992. X
  993. X    ang = Camera.vfov * 10 + 0.5;
  994. X    aspect = Camera.hfov / Camera.vfov;
  995. X
  996. X    T[0][0]=Screen.scrni.x; T[0][1]=Screen.scrnj.x; T[0][2]= -Camera.dir.x;
  997. X    T[1][0]=Screen.scrni.y; T[1][1]=Screen.scrnj.y; T[1][2]= -Camera.dir.y;
  998. X    T[2][0]=Screen.scrni.z; T[2][1]=Screen.scrnj.z; T[2][2]= -Camera.dir.z;
  999. X
  1000. X    T[0][3] = T[1][3] = T[2][3] = 0.;
  1001. X
  1002. X    T[3][0] = -dotp(&Camera.lookp, &Screen.scrni);
  1003. X    T[3][1] = -dotp(&Camera.lookp, &Screen.scrnj);
  1004. X    T[3][2] = dotp(&Camera.lookp, &Camera.dir);
  1005. X    T[3][3] = 1.;
  1006. X
  1007. X    ComputeClippingPlanes(&near, &far, World->bounds);
  1008. X
  1009. X    loadmatrix(Ident);
  1010. X    perspective(ang, aspect, near, far);
  1011. X    polarview((float)Camera.lookdist, 0, 0, 0);
  1012. X    multmatrix(T);
  1013. X}
  1014. X
  1015. X
  1016. Xstatic void
  1017. XObjectInit()
  1018. X{
  1019. X    CircleDefine();
  1020. X    GLBoxObject = GLBoxObjectDefine();
  1021. X
  1022. X#ifdef SPHERELIB
  1023. X    GLSphereObject = GLSphereObjectDefine();
  1024. X#else
  1025. X    GLSphereObject = GLSphereObjectDefine(SPHERE_LEVEL);
  1026. X#endif
  1027. X
  1028. X    GLCylObject = GLCylObjectDefine();
  1029. X}
  1030. X
  1031. Xstatic void
  1032. XGeomDraw(obj)
  1033. XGeom *obj;
  1034. X{
  1035. X    Trans *ct;
  1036. X    /*
  1037. X     * If object has a surface associated with it,
  1038. X     * start using it.
  1039. X     */
  1040. X    if (obj->surf)
  1041. X        GLPushSurface(obj->surf);
  1042. X    if (obj->trans) {
  1043. X        /*
  1044. X         * Take care of any animated transformations that
  1045. X         * exist.
  1046. X         */
  1047. X        if (obj->animtrans && !equal(obj->timenow, CurrentTime)) {
  1048. X            TransResolveAssoc(obj->trans);
  1049. X            obj->timenow = CurrentTime;
  1050. X        }
  1051. X        pushmatrix();
  1052. X        /*
  1053. X          * Apply in reverse order.
  1054. X         */
  1055. X        for (ct = obj->transtail; ct; ct = ct->prev)
  1056. X            GLMultMatrix(&ct->trans);
  1057. X    }
  1058. X
  1059. X    if (obj->methods->user) {
  1060. X        /*
  1061. X          * Call proper method
  1062. X          */
  1063. X        (*obj->methods->user)(obj->obj);
  1064. X    } else {
  1065. X        /*
  1066. X         * Draw bounding box.
  1067. X         */
  1068. X        GLBoundsDraw(obj->bounds);
  1069. X    }
  1070. X
  1071. X    if (obj->surf)
  1072. X        GLPopSurface();
  1073. X    if (obj->trans)
  1074. X        popmatrix();
  1075. X}
  1076. X
  1077. Xstatic float surfprops[] =    {AMBIENT, 0, 0, 0,
  1078. X                 DIFFUSE, 0, 0, 0,
  1079. X                 SPECULAR, 0, 0, 0,
  1080. X                 SHININESS, 0,
  1081. X                 LMNULL};
  1082. Xstatic float    *amb = &surfprops[1],
  1083. X        *diff = &surfprops[5],
  1084. X        *spec = &surfprops[9],
  1085. X        *shine = &surfprops[13];
  1086. X
  1087. Xstatic void
  1088. XGLPushSurface(surf)
  1089. XSurface *surf;
  1090. X{
  1091. X    static Surface *lastsurf = NULL;
  1092. X
  1093. X    /*
  1094. X     * Start using the given surface.
  1095. X     * In the case of the use of an "applysurf",
  1096. X     * the same surface will be applied to many
  1097. X     * primitives individually.  By saving the
  1098. X     * pointer to the last surface, we keep from
  1099. X     * lmdef'ing the surface when we don't need to.
  1100. X     */
  1101. X    if (surf != lastsurf) {
  1102. X        amb[0] = surf->amb.r; amb[1] = surf->amb.g;
  1103. X            amb[2] = surf->amb.b;
  1104. X        diff[0] = surf->diff.r; diff[1] = surf->diff.g;
  1105. X            diff[2] = surf->diff.b;
  1106. X        spec[0] = surf->spec.r; spec[1] = surf->spec.g;
  1107. X            spec[2] = surf->spec.b;
  1108. X        shine[0] = surf->srexp;
  1109. X        lmdef(DEFMATERIAL, cursurf, 15, surfprops);
  1110. X        lastsurf = surf;
  1111. X    }
  1112. X    lmbind(MATERIAL, cursurf);
  1113. X    cursurf++;
  1114. X}
  1115. X
  1116. Xstatic void
  1117. XGLMultMatrix(trans)
  1118. XRSMatrix *trans;
  1119. X{
  1120. X    float newmat[4][4];
  1121. X    /*
  1122. X     * Multiply in the given transformation.
  1123. X     */
  1124. X    newmat[0][0] = trans->matrix[0][0]; newmat[0][1] = trans->matrix[0][1];
  1125. X    newmat[0][2] = trans->matrix[0][2]; newmat[0][3] = 0.;
  1126. X    newmat[1][0] = trans->matrix[1][0]; newmat[1][1] = trans->matrix[1][1];
  1127. X    newmat[1][2] = trans->matrix[1][2]; newmat[1][3] = 0.;
  1128. X    newmat[2][0] = trans->matrix[2][0]; newmat[2][1] = trans->matrix[2][1];
  1129. X    newmat[2][2] = trans->matrix[2][2]; newmat[2][3] = 0.;
  1130. X    newmat[3][0] = trans->translate.x; newmat[3][1] = trans->translate.y;
  1131. X    newmat[3][2] = trans->translate.z ; newmat[3][3] = 1.;
  1132. X    multmatrix(newmat);
  1133. X}
  1134. X
  1135. Xstatic void
  1136. XGLPopSurface()
  1137. X{
  1138. X    cursurf--;
  1139. X    lmbind(MATERIAL, cursurf-1);
  1140. X}
  1141. X
  1142. Xstatic void
  1143. XGLBoundsDraw(bounds)
  1144. XFloat bounds[2][3];
  1145. X{
  1146. X    float sx, sy, sz;
  1147. X
  1148. X    pushmatrix();
  1149. X
  1150. X    translate(bounds[LOW][X], bounds[LOW][Y], bounds[LOW][Z]);
  1151. X    scale(    bounds[HIGH][X] - bounds[LOW][X],
  1152. X        bounds[HIGH][Y] - bounds[LOW][Y],
  1153. X        bounds[HIGH][Z] - bounds[LOW][Z]);
  1154. X    pushmatrix();
  1155. X    callobj(GLBoxObject);
  1156. X    popmatrix();
  1157. X    popmatrix();
  1158. X}
  1159. X
  1160. Xstatic void
  1161. XGLBoxDraw(box)
  1162. XBox *box;
  1163. X{
  1164. X    GLBoundsDraw(box->bounds);
  1165. X}
  1166. X
  1167. X
  1168. Xstatic void
  1169. XGLConeDraw(cone)
  1170. XCone *cone;
  1171. X{
  1172. X    int i, j;
  1173. X    float norm[3], normconst, ZeroVect[3], tmpv[3];
  1174. X
  1175. X    ZeroVect[0] = ZeroVect[1] = ZeroVect[2] = 0.;
  1176. X    /*
  1177. X     * Sides.
  1178. X     * For the normal, assume we are finding the normal at
  1179. X     * (C_P[i].x, C_P[i].y, 1.) at this point, the unnormalized
  1180. X     * normal = (C_P[i].x, C_P[i].y, -tantheta^2).  When we normalize,
  1181. X     * then length of the vector is simply equal to:
  1182. X     * sqrt(CP[i].x^2 + CP[i].y^2 + tantheta^4)  ==
  1183. X     * sqrt(1. + tantheta^4)
  1184. X     * In our case, tantheta = 1., so...
  1185. X     */
  1186. X
  1187. X    normconst = 1. / sqrt(2.);
  1188. X    norm[2] = -normconst;
  1189. X
  1190. X    pushmatrix();
  1191. X    GLMultMatrix(&cone->trans.trans);
  1192. X
  1193. X    for (i = 0; i < CIRCLE_SAMPLES; i++) {
  1194. X        j = (i + 1) % CIRCLE_SAMPLES;
  1195. X        norm[0] = CirclePoints[i][0] * normconst;
  1196. X        norm[1] = CirclePoints[i][1] * normconst;
  1197. X        n3f(norm);
  1198. X        bgnpolygon();
  1199. X        if (cone->start_dist > EPSILON) {
  1200. X            tmpv[2] = cone->start_dist;
  1201. X            tmpv[0] = CirclePoints[i][0] * cone->start_dist;
  1202. X            tmpv[1] = CirclePoints[i][1] * cone->start_dist;
  1203. X            v3f(tmpv);
  1204. X            tmpv[0] = CirclePoints[j][0] * cone->start_dist;
  1205. X            tmpv[1] = CirclePoints[j][1] * cone->start_dist;
  1206. X            v3f(tmpv);
  1207. X        } else
  1208. X            v3f(ZeroVect);
  1209. X        tmpv[2] = 1.;
  1210. X        tmpv[0] = CirclePoints[j][0];
  1211. X        tmpv[1] = CirclePoints[j][1];
  1212. X        v3f(tmpv);
  1213. X        tmpv[0] = CirclePoints[i][0];
  1214. X        tmpv[1] = CirclePoints[i][1];
  1215. X        v3f(tmpv);
  1216. X        endpolygon();
  1217. X    }
  1218. X    popmatrix();
  1219. X}
  1220. X
  1221. Xstatic void
  1222. XGLCsgDraw(csg)
  1223. XCsg *csg;
  1224. X{
  1225. X    /*
  1226. X     * Punt by drawing both objects.
  1227. X     */
  1228. X    GeomDraw(csg->obj1);
  1229. X    GeomDraw(csg->obj2);
  1230. X}
  1231. X
  1232. Xstatic void
  1233. XGLCylinderDraw(cyl)
  1234. XCylinder *cyl;
  1235. X{
  1236. X    pushmatrix();
  1237. X    GLMultMatrix(&cyl->trans.trans);
  1238. X    callobj(GLCylObject);
  1239. X    popmatrix();
  1240. X}
  1241. X
  1242. Xstatic void
  1243. XGLDiscDraw(disc)
  1244. XDisc *disc;
  1245. X{
  1246. X    GLDisc((Float)sqrt(disc->radius), &disc->pos, &disc->norm);
  1247. X}
  1248. X
  1249. Xstatic void
  1250. XGLDisc(rad, pos, norm)
  1251. XFloat rad;
  1252. XVector *pos, *norm;
  1253. X{
  1254. X    RSMatrix m, tmp;
  1255. X    Vector atmp;
  1256. X
  1257. X    /*
  1258. X     * This is kinda disgusting...
  1259. X     */
  1260. X    ScaleMatrix(rad, rad, 1., &m);
  1261. X    if (fabs(norm->z) == 1.) {
  1262. X        atmp.x = 1.;
  1263. X        atmp.y = atmp.z = 0.;
  1264. X    } else {
  1265. X        atmp.x = norm->y;
  1266. X        atmp.y = -norm->x;
  1267. X        atmp.z= 0.;
  1268. X    }
  1269. X
  1270. X    RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(norm->z), &tmp);
  1271. X    MatrixMult(&m, &tmp, &m);
  1272. X    TranslationMatrix(pos->x, pos->y, pos->z, &tmp);
  1273. X    MatrixMult(&m, &tmp, &m);
  1274. X    pushmatrix();
  1275. X    GLMultMatrix(&m);
  1276. X    /*
  1277. X     * Draw unit circle.
  1278. X     */
  1279. X    GLUnitCircle(0., TRUE);
  1280. X    popmatrix();
  1281. X}
  1282. X
  1283. Xstatic void
  1284. XGLGridDraw(grid)
  1285. XGrid *grid;
  1286. X{
  1287. X    Geom *ltmp;
  1288. X
  1289. X    for (ltmp = grid->unbounded; ltmp; ltmp = ltmp->next)
  1290. X        GeomDraw(ltmp);
  1291. X    for (ltmp = grid->objects; ltmp; ltmp = ltmp->next)
  1292. X        GeomDraw(ltmp);
  1293. X}
  1294. X
  1295. Xstatic void
  1296. XGLHfDraw(){}
  1297. X
  1298. Xstatic void
  1299. XGLInstanceDraw(inst)
  1300. XInstance *inst;
  1301. X{
  1302. X    GeomDraw(inst->obj);
  1303. X}
  1304. X
  1305. Xstatic void
  1306. XGLListDraw(list)
  1307. XList *list;
  1308. X{
  1309. X    Geom *ltmp;
  1310. X
  1311. X    for (ltmp = list->unbounded; ltmp; ltmp = ltmp->next)
  1312. X        GeomDraw(ltmp);
  1313. X    for (ltmp = list->list; ltmp; ltmp = ltmp->next)
  1314. X        GeomDraw(ltmp);
  1315. X}
  1316. X
  1317. Xstatic void
  1318. XGLPlaneDraw(plane)
  1319. XPlane *plane;
  1320. X{
  1321. X    /*
  1322. X     * Draw a really big disc.
  1323. X     */
  1324. X    GLDisc((Float)PLANE_RAD, &plane->pos, &plane->norm);
  1325. X}
  1326. X
  1327. Xstatic void
  1328. XGLPolygonDraw(poly)
  1329. Xregister Polygon *poly;
  1330. X{
  1331. X    register int i;
  1332. X
  1333. X    GLNormal(&poly->norm);
  1334. X
  1335. X    bgnpolygon();
  1336. X    for (i = 0; i < poly->npoints; i++)
  1337. X        v3d(&poly->points[i]);
  1338. X    endpolygon();
  1339. X}
  1340. X
  1341. Xstatic void
  1342. XGLSphereDraw(sph)
  1343. XSphere *sph;
  1344. X{
  1345. X    pushmatrix();
  1346. X    translate(sph->x, sph->y, sph->z);
  1347. X    scale(sph->r, sph->r, sph->r);
  1348. X    callobj(GLSphereObject);
  1349. X    popmatrix();
  1350. X}
  1351. X
  1352. Xstatic void
  1353. XGLTorusDraw(){}
  1354. X
  1355. Xstatic void
  1356. XGLTriangleDraw(tri)
  1357. Xregister Triangle *tri;
  1358. X{
  1359. X    /*
  1360. X     * If Float is a double, use v3d,
  1361. X     * otherwise use v3f.
  1362. X     */
  1363. X    if (tri->type != PHONGTRI) {
  1364. X        GLNormal(&tri->nrm);    
  1365. X        bgnpolygon();
  1366. X        v3d(&tri->p[0]); v3d(&tri->p[1]); v3d(&tri->p[2]);
  1367. X        endpolygon();
  1368. X    } else {
  1369. X        bgnpolygon();
  1370. X        GLNormal(&tri->vnorm[0]);
  1371. X        v3d(&tri->p[0]);
  1372. X        GLNormal(&tri->vnorm[1]);
  1373. X        v3d(&tri->p[1]);
  1374. X        GLNormal(&tri->vnorm[2]);
  1375. X        v3d(&tri->p[2]);
  1376. X        endpolygon();
  1377. X    }
  1378. X}
  1379. X
  1380. Xfloat lightprops[] =    {POSITION, 0., 0., 0., 0.,
  1381. X             LCOLOR, 0, 0, 0,
  1382. X             LMNULL};
  1383. X
  1384. Xfloat     *lpos = &lightprops[1],
  1385. X    *lcolor = &lightprops[6];
  1386. X
  1387. Xfloat lmodel[] =    {AMBIENT, 1., 1., 1.,
  1388. X             ATTENUATION, 1., 0.,
  1389. X             LOCALVIEWER, 0.,
  1390. X#ifdef sgi
  1391. X             ATTENUATION2, 0.,
  1392. X             TWOSIDE, 1.,
  1393. X#endif
  1394. X             LMNULL};
  1395. X
  1396. Xstatic void
  1397. XLightDrawInit()
  1398. X{
  1399. X    Light *light;
  1400. X    extern Light *Lights;
  1401. X
  1402. X    for (light = Lights; light; light = light->next)
  1403. X        LightDraw(light);
  1404. X
  1405. X    switch (curlight-1) {
  1406. X        case 8:
  1407. X            lmbind(LIGHT7, 8);
  1408. X        case 7:
  1409. X            lmbind(LIGHT6, 7);
  1410. X        case 6:
  1411. X            lmbind(LIGHT5, 6);
  1412. X        case 5:
  1413. X            lmbind(LIGHT4, 5);
  1414. X        case 4:
  1415. X            lmbind(LIGHT3, 4);
  1416. X        case 3:
  1417. X            lmbind(LIGHT2, 3);
  1418. X        case 2:
  1419. X            lmbind(LIGHT1, 2);
  1420. X        case 1:
  1421. X            lmbind(LIGHT0, 1);
  1422. X    }
  1423. X
  1424. X    lmodel[1] = Options.ambient.r;
  1425. X    lmodel[2] = Options.ambient.g;
  1426. X    lmodel[3] = Options.ambient.b;
  1427. X
  1428. X#ifdef sgi
  1429. X    lmdef(DEFLMODEL, 1, 14, lmodel);
  1430. X#else
  1431. X    lmdef(DEFLMODEL, 1, 10, lmodel);
  1432. X#endif
  1433. X    lmbind(LMODEL, 1);
  1434. X}
  1435. X
  1436. Xstatic void
  1437. XLightDraw(light)
  1438. XLight *light;
  1439. X{
  1440. X    if (!light || !light->methods->user)
  1441. X        return;
  1442. X    lcolor[0] = light->color.r;
  1443. X    lcolor[1] = light->color.g;
  1444. X    lcolor[2] = light->color.b;
  1445. X    (*light->methods->user)(light->light);
  1446. X}
  1447. X
  1448. Xstatic void
  1449. XGLExtendedLight(ext)
  1450. XExtended *ext;
  1451. X{
  1452. X    lpos[0] = ext->pos.x;
  1453. X    lpos[1] = ext->pos.y;
  1454. X    lpos[2] = ext->pos.z;
  1455. X    lpos[3] = 1.;
  1456. X    lmdef(DEFLIGHT, curlight++, 10, lightprops);
  1457. X}
  1458. X
  1459. X
  1460. Xstatic void
  1461. XGLInfiniteLight(inf)
  1462. XInfinite *inf;
  1463. X{
  1464. X    lpos[0] = inf->dir.x;
  1465. X    lpos[1] = inf->dir.y;
  1466. X    lpos[2] = inf->dir.z;
  1467. X    lpos[3] = 0.;
  1468. X    lmdef(DEFLIGHT, curlight++, 10, lightprops);
  1469. X}
  1470. X
  1471. Xstatic void
  1472. XGLPointLight(pt)
  1473. XPointlight *pt;
  1474. X{
  1475. X    lpos[0] = pt->pos.x;
  1476. X    lpos[1] = pt->pos.y;
  1477. X    lpos[2] = pt->pos.z;
  1478. X    lpos[3] = 1.;
  1479. X    lmdef(DEFLIGHT, curlight++, 10, lightprops);
  1480. X}
  1481. X
  1482. Xstatic void
  1483. XGLSpotLight(spot)
  1484. XSpotlight *spot;
  1485. X{
  1486. X}
  1487. X
  1488. Xstatic float boxfaces[6][4][3] = {
  1489. X{     {1., 1., 1.},
  1490. X    {0., 1., 1.},
  1491. X    {0., 0., 1.},
  1492. X    {1., 0., 1.}    },
  1493. X{    {1., 0., 1.},
  1494. X    {0., 0., 1.},
  1495. X    {0., 0., 0.},
  1496. X    {1., 0., 0.}    },
  1497. X{    {1., 0., 0.},
  1498. X    {0., 0., 0.},
  1499. X    {0., 1., 0.},
  1500. X    {1., 1., 0.}    },
  1501. X{    {0., 1., 0.},
  1502. X    {0., 1., 1.},
  1503. X    {1., 1., 1.},
  1504. X    {1., 1., 0.}    },
  1505. X{    {1., 1., 1.},
  1506. X    {1., 0., 1.},
  1507. X    {1., 0., 0.},
  1508. X    {1., 1., 0.}    },
  1509. X{    {0., 0., 1.},
  1510. X    {0., 1., 1.},
  1511. X    {0., 1., 0.},
  1512. X    {0., 0., 0.}}};
  1513. X
  1514. Xfloat boxnorms[6][3] = {
  1515. X    {0, 0, 1},
  1516. X    {0, -1, 0},
  1517. X    {0, 0, -1},
  1518. X    {0, 1, 0},
  1519. X    {1, 0, 0,},
  1520. X    {-1, 0, 0}};
  1521. X
  1522. X/*
  1523. X * Define a unit cube centered at (0.5, 0.5, 0.5)
  1524. X */
  1525. Xstatic Object
  1526. XGLBoxObjectDefine()
  1527. X{
  1528. X    int i, box;
  1529. X
  1530. X    makeobj(box = genobj());
  1531. X    for (i = 0; i < 6; i++)    {
  1532. X        n3f(boxnorms[i]);
  1533. X        polf(4, boxfaces[i]);
  1534. X    }
  1535. X    closeobj();
  1536. X    return box;
  1537. X}
  1538. X
  1539. Xstatic void
  1540. XGLUnitCircle(z, up)
  1541. Xfloat z;
  1542. Xint up;
  1543. X{
  1544. X    int i;
  1545. X    float norm[3];
  1546. X
  1547. X    norm[0] = norm[1] = 0.;
  1548. X    bgnpolygon();
  1549. X
  1550. X    if (up) {
  1551. X        norm[2] = 1.;
  1552. X        n3f(norm);    
  1553. X        for (i = 0; i < CIRCLE_SAMPLES; i++) {
  1554. X            CirclePoints[i][2] = z;
  1555. X            v3f(CirclePoints[i]);
  1556. X        }
  1557. X    } else {
  1558. X        norm[2] = -1.;
  1559. X        n3f(norm);    
  1560. X        for (i = CIRCLE_SAMPLES -1; i; i--) {
  1561. X            CirclePoints[i][2] = z;
  1562. X            v3f(CirclePoints[i]);
  1563. X        }
  1564. X    }
  1565. X
  1566. X    endpolygon();
  1567. X}
  1568. X
  1569. Xstatic Object
  1570. XGLCylObjectDefine()
  1571. X{
  1572. X    int i, j, cyl;
  1573. X    float norm[3];
  1574. X
  1575. X    makeobj(cyl = genobj());
  1576. X    norm[2] = 0;
  1577. X    for (i = 0; i < CIRCLE_SAMPLES; i++) {
  1578. X        j = (i+1)%CIRCLE_SAMPLES;
  1579. X        norm[0] = CirclePoints[i][0];
  1580. X        norm[1] = CirclePoints[i][1];
  1581. X#ifdef sgi
  1582. X        n3f(norm);
  1583. X        bgnpolygon();
  1584. X        CirclePoints[i][2] = 0;
  1585. X        v3f(CirclePoints[i]);
  1586. X        CirclePoints[j][2] = 0;
  1587. X        v3f(CirclePoints[j]);
  1588. X        CirclePoints[j][2] = 1;
  1589. X        v3f(CirclePoints[j]);
  1590. X        CirclePoints[i][2] = 1;
  1591. X        v3f(CirclePoints[i]);
  1592. X        endpolygon();
  1593. X#else
  1594. X        n3f(norm);
  1595. X        pmv(CirclePoints[i][0], CirclePoints[i][1], 0.);
  1596. X        pdr(CirclePoints[j][0], CirclePoints[j][1], 0.);
  1597. X        pdr(CirclePoints[j][0], CirclePoints[j][1], 1.);
  1598. X        pdr(CirclePoints[i][0], CirclePoints[i][1], 1.);
  1599. X        pclos();
  1600. X#endif
  1601. X    }
  1602. X    closeobj();
  1603. X    return cyl;
  1604. X}
  1605. X
  1606. X/*
  1607. X * Fill CirclePoints[t] with X and Y values cooresponding to points
  1608. X * along the unit circle.  The size of CirclePoints is equal to
  1609. X * CIRCLE_SAMPLES.
  1610. X */
  1611. XCircleDefine()
  1612. X{
  1613. X    int i;
  1614. X    double theta, dtheta;
  1615. X
  1616. X    dtheta = 2.*M_PI / (double)CIRCLE_SAMPLES;
  1617. X    CirclePoints = (float **)malloc(CIRCLE_SAMPLES * sizeof(float *));
  1618. X    for (i = 0, theta = 0; i < CIRCLE_SAMPLES; i++, theta += dtheta) {
  1619. X        CirclePoints[i] = (float *)malloc(3 * sizeof(float));
  1620. X        CirclePoints[i][0] = cos(theta);
  1621. X        CirclePoints[i][1] = sin(theta);
  1622. X        /* Z is left unset. */    
  1623. X    }
  1624. X}
  1625. X
  1626. X/*
  1627. X * Given world bounds, determine near and far
  1628. X * clipping planes.  Only problem occurs when there are
  1629. X * unbbounded objects (planes)...
  1630. X */
  1631. Xstatic void
  1632. XComputeClippingPlanes(near, far, bounds)
  1633. Xfloat *near, *far;
  1634. XFloat bounds[2][3];
  1635. X{
  1636. X    Vector e, c;
  1637. X    double rad, d;
  1638. X
  1639. X
  1640. X    /*
  1641. X     * Compute 'radius' of scene.
  1642. X     */
  1643. X    rad = max(max((bounds[HIGH][X] - bounds[LOW][X])*0.5,
  1644. X              (bounds[HIGH][Y] - bounds[LOW][Y])*0.5),
  1645. X              (bounds[HIGH][Z] - bounds[LOW][Z])*0.5);
  1646. X
  1647. X    c.x = (bounds[LOW][X] + bounds[HIGH][X])*0.5;
  1648. X    c.y = (bounds[LOW][Y] + bounds[HIGH][Y])*0.5;
  1649. X    c.z = (bounds[LOW][Z] + bounds[HIGH][Z])*0.5;
  1650. X
  1651. X    /*
  1652. X     * Compute position of eye relative to the center of the sphere.
  1653. X     */
  1654. X    VecSub(Camera.pos, c, &e);
  1655. X    d = VecNormalize(&e);
  1656. X    if (d <= rad)
  1657. X        /*
  1658. X         * Eye is inside sphere.
  1659. X         */
  1660. X        *near = DEFAULT_NEAR;
  1661. X    else
  1662. X        *near = (d - rad)*0.2;
  1663. X    *far = (d + rad)*2.;
  1664. X}
  1665. END_OF_FILE
  1666. if test 17863 -ne `wc -c <'rayview/glmethods.c'`; then
  1667.     echo shar: \"'rayview/glmethods.c'\" unpacked with wrong size!
  1668. fi
  1669. # end of 'rayview/glmethods.c'
  1670. fi
  1671. echo shar: End of archive 17 \(of 19\).
  1672. cp /dev/null ark17isdone
  1673. MISSING=""
  1674. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1675.     if test ! -f ark${I}isdone ; then
  1676.     MISSING="${MISSING} ${I}"
  1677.     fi
  1678. done
  1679. if test "${MISSING}" = "" ; then
  1680.     echo You have unpacked all 19 archives.
  1681.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1682. else
  1683.     echo You still need to unpack the following archives:
  1684.     echo "        " ${MISSING}
  1685. fi
  1686. ##  End of shell archive.
  1687. exit 0
  1688.  
  1689. exit 0 # Just in case...
  1690.