home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume21 / rayshade / part06 < prev    next >
Encoding:
Internet Message Format  |  1990-03-21  |  49.9 KB

  1. Subject:  v21i013:  A ray tracing program, Part06/08
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Craig Kolb <craig@weedeater.math.yale.edu>
  7. Posting-number: Volume 21, Issue 13
  8. Archive-name: rayshade/part06
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 6 (of 8)."
  17. # Contents:  src/hf.c src/input_yacc.y src/raytrace.c
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'src/hf.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'src/hf.c'\"
  21. else
  22. echo shar: Extracting \"'src/hf.c'\" \(17271 characters\)
  23. sed "s/^X//" >'src/hf.c' <<'END_OF_FILE'
  24. X/*
  25. X * hf.c
  26. X *
  27. X * Copyright (C) 1989, Craig E. Kolb
  28. X *
  29. X * This software may be freely copied, modified, and redistributed,
  30. X * provided that this copyright notice is preserved on all copies.
  31. X *
  32. X * There is no warranty or other guarantee of fitness for this software,
  33. X * it is provided solely .  Bug reports or fixes may be sent
  34. X * to the author, who may or may not act on them as he desires.
  35. X *
  36. X * You may not include this software in a program or other software product
  37. X * without supplying the source, or without informing the end-user that the
  38. X * source is available for no extra charge.
  39. X *
  40. X * If you modify this software, you should include a notice giving the
  41. X * name of the person performing the modification, the date of modification,
  42. X * and the reason for such modification.
  43. X *
  44. X * $Id: hf.c,v 3.0 89/10/27 02:05:51 craig Exp $
  45. X *
  46. X * $Log:    hf.c,v $
  47. X * Revision 3.0  89/10/27  02:05:51  craig
  48. X * Baseline for first official release.
  49. X * 
  50. X */
  51. X#include <stdio.h>
  52. X#include <math.h>
  53. X#include "typedefs.h"
  54. X#include "funcdefs.h"
  55. X#include "constants.h"
  56. X
  57. X/*
  58. X * Any height values <= HF_UNSET is not considered to be part of the
  59. X * height field. Any trianges containing such a vertex will not be
  60. X * rendered.  This allows one to render non-square height fields.
  61. X */
  62. X#define HF_UNSET        (-1000.)
  63. X/*
  64. X * Number of datapoints in a single cell.  If you've got loads of memory,
  65. X * decrease this number.  The 'optimal' number is quite system-dependent,
  66. X * but something around 20 seems to work well.  For systems which don't
  67. X * have much memory, this constant should be greater than or equal to
  68. X * the largest height field which will be rendered, thus making the
  69. X * algorithm non-hierarchical.
  70. X */
  71. X#define BESTSIZE        16
  72. X/*
  73. X * Size of triangle cache.
  74. X */
  75. X#define CACHESIZE        6
  76. X/*
  77. X * Used to differentiate between the two triangles used to represent a cell:
  78. X *    a------d
  79. X *      |\     |
  80. X *      | \TRI1|    TRI1 == c-->d-->a-->c
  81. X *      |  \   |
  82. X *      |   \  |
  83. X *    |    \ |
  84. X *      |TRI2 \|    TRI2 == c-->a-->b-->d
  85. X *      b------c
  86. X */
  87. X#define TRI1            1
  88. X#define TRI2            2
  89. X
  90. Xdouble DDA2D(), CheckCell(), intHftri();
  91. Xfloat minalt(), maxalt();
  92. X
  93. Xtypedef struct {
  94. X    int stepX, stepY;
  95. X    double tDX, tDY;
  96. X    float minz, maxz;
  97. X    int outX, outY;
  98. X    Vector cp, pDX, pDY;
  99. X} Trav2D;
  100. X
  101. XhfTri *CreateHfTriangle(), *GetQueuedTri();
  102. X
  103. XObject *
  104. Xmakhf(surf, filename)
  105. Xchar *surf, *filename;
  106. X{
  107. X    Hf *hf;
  108. X    Object *newobj;
  109. X    Primitive *prim;
  110. X    FILE *fp;
  111. X    float val, *maxptr, *minptr;
  112. X    int i, j;
  113. X
  114. X    fp = fopen(filename, "r");
  115. X    if (fp == (FILE *)NULL)
  116. X        yyerror("Cannot open heightfield file");
  117. X
  118. X    prim = mallocprim();
  119. X    newobj = new_object(NULL, HF, (char *)prim, (Trans *)NULL);
  120. X    prim->type = HF;
  121. X    prim->surf = find_surface(surf);
  122. X    hf = (Hf *)Malloc(sizeof(Hf));
  123. X    prim->objpnt.p_hf = hf;
  124. X    /*
  125. X     * Make the following an option someday.
  126. X     */
  127. X    hf->BestSize = BESTSIZE;
  128. X    /*
  129. X     * Store the inverse for faster computation.
  130. X     */
  131. X    hf->iBestSize = 1. / (float)hf->BestSize;
  132. X    /*
  133. X     * Get HF size.
  134. X     */
  135. X    if (fread(&hf->size, sizeof(int), 1, fp) == 0)
  136. X        yyerror("Cannot read height field size.");
  137. X
  138. X    hf->data = (float **)share_malloc(hf->size * sizeof(float *));
  139. X    for (i = 0; i < hf->size; i++) {
  140. X        hf->data[i] = (float *)share_malloc(hf->size * sizeof(float));
  141. X        /*
  142. X         * Read in row of HF data.
  143. X         */
  144. X        if (fread(hf->data[i],sizeof(float),hf->size,fp) != hf->size)
  145. X            yyerror("Not enough heightfield data.");
  146. X        for (j = 0; j < hf->size; j++) {
  147. X            val = hf->data[i][j];
  148. X            if (val <= HF_UNSET) {
  149. X                hf->data[i][j] = HF_UNSET;
  150. X                /*
  151. X                 * Don't include the point in min/max
  152. X                 * calculations.
  153. X                 */
  154. X                continue;
  155. X            }
  156. X            if (val > hf->maxz)
  157. X                hf->maxz = val;
  158. X            if (val < hf->minz)
  159. X                hf->minz = val;
  160. X        }
  161. X    }
  162. X    fclose(fp);
  163. X    /*
  164. X     * Allocate levels of grid.  hf->levels = log base BestSize of hf->size
  165. X     */
  166. X    for (i = hf->size, hf->levels = 0; i > hf->BestSize; i /= hf->BestSize,
  167. X                hf->levels++)
  168. X            ;
  169. X    hf->levels++;
  170. X    hf->qsize = CACHESIZE;
  171. X    hf->q = (hfTri **)Calloc(hf->qsize, sizeof(hfTri *));
  172. X    hf->qtail = 0;
  173. X
  174. X    hf->lsize = (int *)share_malloc(hf->levels * sizeof(int));
  175. X    hf->spacing = (float *)share_malloc(hf->levels * sizeof(float));
  176. X    hf->boundsmax = (float ***)share_malloc(hf->levels * sizeof(float **));
  177. X    hf->boundsmin = (float ***)share_malloc(hf->levels * sizeof(float **));
  178. X
  179. X    hf->spacing[0] = hf->size -1;
  180. X    hf->lsize[0] = (int)hf->spacing[0];
  181. X    hf->boundsmax[0] = (float **)share_malloc(hf->lsize[0]*sizeof(float *));
  182. X    hf->boundsmin[0] = (float **)share_malloc(hf->lsize[0]*sizeof(float *));
  183. X    /*
  184. X     * Compute initial bounding boxes
  185. X     */
  186. X    for (i = 0; i < hf->lsize[0]; i++) {
  187. X        hf->boundsmax[0][i]=(float *)share_malloc(hf->lsize[0]*sizeof(float));
  188. X        hf->boundsmin[0][i]=(float *)share_malloc(hf->lsize[0]*sizeof(float));
  189. X        maxptr = hf->boundsmax[0][i];
  190. X        minptr = hf->boundsmin[0][i];
  191. X        for (j = 0; j < hf->lsize[0]; j++) {
  192. X            *maxptr++ = maxalt(i, j, hf->data) + EPSILON;
  193. X            *minptr++ = minalt(i, j, hf->data) - EPSILON;
  194. X        }
  195. X    }
  196. X
  197. X    for (i = 1; i < hf->levels; i++) {
  198. X        hf->spacing[i] = hf->spacing[i-1] * hf->iBestSize;
  199. X        hf->lsize[i] = (int)hf->spacing[i];
  200. X        if (hf->lsize[i-1] % hf->BestSize != 0)
  201. X            hf->lsize[i]++;
  202. X        hf->boundsmax[i]=(float **)share_malloc(hf->lsize[i]*sizeof(float *));
  203. X        hf->boundsmin[i]=(float **)share_malloc(hf->lsize[i]*sizeof(float *));
  204. X        for (j = 0; j < hf->lsize[i]; j++) {
  205. X            hf->boundsmax[i][j] = (float *)share_malloc(hf->lsize[i] *
  206. X                            sizeof(float));
  207. X            hf->boundsmin[i][j] = (float *)share_malloc(hf->lsize[i] *
  208. X                            sizeof(float));
  209. X        }
  210. X        integrate_grid(hf, i);
  211. X    }
  212. X
  213. X    hf->boundbox[LOW][X] = hf->boundbox[LOW][Y] = 0;
  214. X    hf->boundbox[HIGH][X] = hf->boundbox[HIGH][Y] = 1;
  215. X    hf->boundbox[LOW][Z] = hf->minz;
  216. X    hf->boundbox[HIGH][Z] = hf->maxz;
  217. X
  218. X    return newobj;
  219. X}
  220. X
  221. X/*
  222. X * Intersect ray with height field.
  223. X */
  224. Xdouble
  225. Xinthf(pos, ray, obj)
  226. XVector *pos, *ray;
  227. XPrimitive *obj;
  228. X{
  229. X    Hf *hf;
  230. X    Ray tmpray;
  231. X    Vector hitpos;
  232. X    double offset, dist;
  233. X    Trav2D trav;
  234. X    extern unsigned long primtests[];
  235. X
  236. X    primtests[HF]++;
  237. X    hf = obj->objpnt.p_hf;
  238. X
  239. X    /*
  240. X     * Find where we hit the hf cube.
  241. X     */
  242. X    if (OutOfBounds(pos, hf->boundbox)) {
  243. X        tmpray.pos = *pos;
  244. X        tmpray.dir = *ray;
  245. X        offset = IntBounds(&tmpray, hf->boundbox);
  246. X        if (offset <= 0.)
  247. X            /* Never hit hf. */
  248. X            return 0.;
  249. X        hitpos.x = pos->x + ray->x * offset;
  250. X        hitpos.y = pos->y + ray->y * offset;
  251. X        hitpos.z = pos->z + ray->z * offset;
  252. X    } else
  253. X        hitpos = *pos;
  254. X    /*
  255. X     * Find out which cell "hitpoint" is in.  This could be
  256. X     * causing problems!
  257. X     */
  258. X    if (equal(hitpos.x, 1.))
  259. X        hitpos.x -= EPSILON;
  260. X    if (equal(hitpos.y, 1.))
  261. X        hitpos.y -= EPSILON;
  262. X
  263. X    if (ray->x < 0.) {
  264. X        trav.stepX = trav.outX = -1;
  265. X        trav.tDX = -1. / (ray->x * hf->spacing[hf->levels -1]);
  266. X    } else if (ray->x > 0.) {
  267. X        trav.stepX = 1;
  268. X        trav.outX = hf->lsize[hf->levels -1];
  269. X        /*
  270. X         * (1./size) / ray
  271. X         */
  272. X        trav.tDX = 1. / (ray->x * hf->spacing[hf->levels -1]);
  273. X    }
  274. X
  275. X    if (ray->y < 0.) {
  276. X        trav.stepY = trav.outY = -1;
  277. X        trav.tDY = -1. / (ray->y * hf->spacing[hf->levels -1]);
  278. X    } else if (ray->y > 0.) {
  279. X        trav.stepY = 1;
  280. X        trav.outY = hf->lsize[hf->levels -1];
  281. X        trav.tDY = 1. / (ray->y * hf->spacing[hf->levels -1]);
  282. X    }
  283. X
  284. X    trav.pDX.x = ray->x * trav.tDX;
  285. X    trav.pDX.y = ray->y * trav.tDX;
  286. X    trav.pDX.z = ray->z * trav.tDX;
  287. X    trav.pDY.x = ray->x * trav.tDY;
  288. X    trav.pDY.y = ray->y * trav.tDY;
  289. X    trav.pDY.z = ray->z * trav.tDY;
  290. X
  291. X    trav.cp = hitpos;
  292. X    trav.minz = hf->minz;
  293. X    trav.maxz = hf->maxz;
  294. X    dist = DDA2D(hf, pos, ray, hf->levels -1, &trav);
  295. X    return dist;
  296. X}
  297. X
  298. X/*
  299. X * Traverse the grid using a modified DDA algorithm.  If the extent of
  300. X * the ray over a cell intersects the bounding volume defined by the
  301. X * four corners of the cell, either recurse or perform ray/surface
  302. X * intersection test.
  303. X */
  304. Xdouble
  305. XDDA2D(hf, pos, ray, level, trav)
  306. XHf *hf;
  307. XVector *pos, *ray;
  308. Xint level;
  309. XTrav2D *trav;
  310. X{
  311. X    int x, y, size, posZ;
  312. X    float **boundsmin, **boundsmax, spacing;
  313. X    double dist, tX, tY;
  314. X    Trav2D newtrav;
  315. X    Vector nxp, nyp;
  316. X
  317. X    size = hf->lsize[level];
  318. X    spacing = hf->spacing[level];
  319. X
  320. X    posZ = (ray->z > 0.);
  321. X
  322. X    x = trav->cp.x * hf->spacing[level];
  323. X    y = trav->cp.y * hf->spacing[level];
  324. X    boundsmax = hf->boundsmax[level];
  325. X    boundsmin = hf->boundsmin[level];
  326. X
  327. X    if (trav->outX > size) trav->outX = size;
  328. X    if (trav->outY > size) trav->outY = size;
  329. X    if (trav->outX < 0) trav->outX = -1;
  330. X    if (trav->outY < 0) trav->outY = -1;
  331. X
  332. X    if (ray->x < 0.) {
  333. X        tX = (x /spacing - trav->cp.x) / ray->x;
  334. X    } else if (ray->x > 0.)
  335. X        tX = ((x+1)/spacing - trav->cp.x) / ray->x;
  336. X    else
  337. X        tX = FAR_AWAY;
  338. X    if (ray->y < 0.) {
  339. X        tY = (y /spacing - trav->cp.y) / ray->y;
  340. X    } else if (ray->y > 0.)
  341. X        tY = ((y+1)/spacing - trav->cp.y) / ray->y;
  342. X    else
  343. X        tY = FAR_AWAY;
  344. X
  345. X    nxp.x = trav->cp.x + tX * ray->x;
  346. X    nxp.y = trav->cp.y + tX * ray->y;
  347. X    nxp.z = trav->cp.z + tX * ray->z;
  348. X
  349. X    nyp.x = trav->cp.x + tY * ray->x;
  350. X    nyp.y = trav->cp.y + tY * ray->y;
  351. X    nyp.z = trav->cp.z + tY * ray->z;
  352. X
  353. X    do {
  354. X        if (tX < tY) {
  355. X            if ((posZ && trav->cp.z <= boundsmax[y][x] &&
  356. X                 nxp.z >= boundsmin[y][x]) ||
  357. X                (!posZ && trav->cp.z >= boundsmin[y][x] &&
  358. X                 nxp.z <= boundsmax[y][x])) {
  359. X                if (level) {
  360. X                    /*
  361. X                     * Recurve -- compute constants
  362. X                     * needed for next level.
  363. X                     * Nicely enough, this just
  364. X                     * involves a few multiplications.
  365. X                     */
  366. X                    newtrav = *trav;
  367. X                    newtrav.tDX *= hf->iBestSize;
  368. X                    newtrav.tDY *= hf->iBestSize;
  369. X                    newtrav.maxz = boundsmax[y][x];
  370. X                    newtrav.minz = boundsmin[y][x];
  371. X                    if (ray->x < 0.)
  372. X                        newtrav.outX=hf->BestSize*x-1;
  373. X                    else
  374. X                        newtrav.outX=hf->BestSize*(x+1);
  375. X                    if (ray->y < 0.)
  376. X                        newtrav.outY=hf->BestSize*y-1;
  377. X                    else
  378. X                        newtrav.outY=hf->BestSize*(y+1);
  379. X                    newtrav.pDX.x *= hf->iBestSize;
  380. X                    newtrav.pDX.y *= hf->iBestSize;
  381. X                    newtrav.pDX.z *= hf->iBestSize;
  382. X                    newtrav.pDY.x *= hf->iBestSize;
  383. X                    newtrav.pDY.y *= hf->iBestSize;
  384. X                    newtrav.pDY.z *= hf->iBestSize;
  385. X                    dist = DDA2D(hf,pos,ray,level-1,
  386. X                        &newtrav);
  387. X                } else
  388. X                    dist = CheckCell(x,y,hf,ray,pos);
  389. X                if (dist > EPSILON)
  390. X                    return dist;
  391. X            }
  392. X            x += trav->stepX;        /* Move in X */
  393. X            if (x == trav->outX)        /* If outside, quit */
  394. X                return 0.;
  395. X            tX += trav->tDX;    /* Update position on ray */
  396. X            trav->cp = nxp;        /* cur pos gets next pos */
  397. X            nxp.x += trav->pDX.x;    /* Compute next pos */
  398. X            nxp.y += trav->pDX.y;
  399. X            nxp.z += trav->pDX.z;
  400. X        } else {
  401. X            if ((posZ && trav->cp.z <= boundsmax[y][x] &&
  402. X                 nyp.z >= boundsmin[y][x]) ||
  403. X                (!posZ && trav->cp.z >= boundsmin[y][x] &&
  404. X                 nyp.z <= boundsmax[y][x])) {
  405. X                if (level) {
  406. X                    /* Recurse */
  407. X                    newtrav = *trav;
  408. X                    newtrav.tDX *= hf->iBestSize;
  409. X                    newtrav.tDY *= hf->iBestSize;
  410. X                    newtrav.maxz = boundsmax[y][x];
  411. X                    newtrav.minz = boundsmin[y][x];
  412. X                    if (ray->x < 0.)
  413. X                        newtrav.outX=hf->BestSize*x-1;
  414. X                    else
  415. X                        newtrav.outX=hf->BestSize*(x+1);
  416. X                    if (ray->y < 0.)
  417. X                        newtrav.outY=hf->BestSize*y-1;
  418. X                    else
  419. X                        newtrav.outY=hf->BestSize*(y+1);
  420. X                    newtrav.pDX.x *= hf->iBestSize;
  421. X                    newtrav.pDX.y *= hf->iBestSize;
  422. X                    newtrav.pDX.z *= hf->iBestSize;
  423. X                    newtrav.pDY.x *= hf->iBestSize;
  424. X                    newtrav.pDY.y *= hf->iBestSize;
  425. X                    newtrav.pDY.z *= hf->iBestSize;
  426. X                    dist = DDA2D(hf,pos,ray,level-1,
  427. X                            &newtrav);
  428. X                } else
  429. X                    dist = CheckCell(x,y,hf,ray,pos);
  430. X                if (dist > EPSILON)
  431. X                    return dist;
  432. X            }
  433. X            y += trav->stepY;
  434. X            if (y == trav->outY)
  435. X                return 0.;
  436. X            tY += trav->tDY;
  437. X            trav->cp = nyp;
  438. X            nyp.x += trav->pDY.x;
  439. X            nyp.y += trav->pDY.y;
  440. X            nyp.z += trav->pDY.z;
  441. X        }
  442. X    } while ((trav->cp.x <= 1. && trav->cp.y <= 1.) &&
  443. X         ((posZ && trav->cp.z <= trav->maxz) ||
  444. X         (!posZ && trav->cp.z >= trav->minz)));
  445. X
  446. X        /*
  447. X         * while ((we're inside the horizontal bounding box)
  448. X         *        (usually caught by outX & outY, but
  449. X         *         it's possible to go "too far" due to
  450. X         *         the fact that our levels of grids do
  451. X         *         not "nest" exactly if gridsize%BestSize != 0)
  452. X         *      and
  453. X         *      ((if ray->z is positive and we haven't gone through
  454. X         *       the upper bounding plane) or
  455. X         *      (if ray->z is negative and we haven't gone through
  456. X         *       the lower bounding plane)));
  457. X         */
  458. X
  459. X    return 0.;
  460. X}
  461. X
  462. X/*
  463. X * Check for ray/cell intersection
  464. X */
  465. Xdouble
  466. XCheckCell(x, y, hf, ray, pos)
  467. Xint x, y;
  468. XHf *hf;
  469. XVector *ray, *pos;
  470. X{
  471. X    hfTri *tri1, *tri2;
  472. X    double d1, d2;
  473. X
  474. X    d1 = d2 = FAR_AWAY;
  475. X
  476. X    if (tri1 = CreateHfTriangle(hf, x, y, x+1, y, x, y+1, TRI1))
  477. X        d1 = intHftri(ray, pos, tri1);
  478. X    if (tri2 = CreateHfTriangle(hf, x+1, y, x+1, y+1, x, y+1, TRI2))
  479. X        d2 = intHftri(ray, pos, tri2);
  480. X
  481. X    if (d1 == FAR_AWAY && d2 == FAR_AWAY)
  482. X        return 0;
  483. X
  484. X    if (d1 < d2) {
  485. X        hf->hittri = *tri1;
  486. X        return d1;
  487. X    }
  488. X
  489. X    hf->hittri = *tri2;
  490. X    return d2;
  491. X}
  492. X
  493. XhfTri *
  494. XCreateHfTriangle(hf, x1, y1, x2, y2, x3, y3, which)
  495. XHf *hf;
  496. Xint x1, y1, x2, y2, x3, y3, which;
  497. X{
  498. X    hfTri *tri;
  499. X    double xid, yid;
  500. X    Vector tmp1, tmp2;
  501. X
  502. X    /*
  503. X     * Don't use triangles with "unset" vertices.
  504. X     */
  505. X    if (hf->data[y1][x1] == HF_UNSET ||
  506. X        hf->data[y2][x2] == HF_UNSET ||
  507. X        hf->data[y3][x3] == HF_UNSET)
  508. X        return (hfTri *)0;
  509. X
  510. X    xid = (double)x1 / (double)(hf->size -1);
  511. X    yid = (double)y1 / (double)(hf->size -1);
  512. X
  513. X    if ((tri = GetQueuedTri(hf, xid, yid, which)) != (hfTri *)0)
  514. X        return tri;
  515. X
  516. X    tri = (hfTri *)Malloc(sizeof(hfTri));
  517. X
  518. X    tri->type = which;
  519. X    tri->v1.x = xid;
  520. X    tri->v1.y = yid;
  521. X    tri->v1.z = hf->data[y1][x1];
  522. X    tri->v2.x = (double)x2 / (double)(hf->size-1);
  523. X    tri->v2.y = (double)y2 / (double)(hf->size-1);
  524. X    tri->v2.z = hf->data[y2][x2];
  525. X    tri->v3.x = (double)x3 / (double)(hf->size-1);
  526. X    tri->v3.y = (double)y3 / (double)(hf->size-1);
  527. X    tri->v3.z = hf->data[y3][x3];
  528. X
  529. X    tmp1.x = tri->v2.x - tri->v1.x;
  530. X    tmp1.y = tri->v2.y - tri->v1.y;
  531. X    tmp1.z = tri->v2.z - tri->v1.z;
  532. X    tmp2.x = tri->v3.x - tri->v1.x;
  533. X    tmp2.y = tri->v3.y - tri->v1.y;
  534. X    tmp2.z = tri->v3.z - tri->v1.z;
  535. X
  536. X    (void)crossp(&tri->norm, &tmp1, &tmp2);
  537. X
  538. X    tri->d = -dotp(&tri->v1, &tri->norm);
  539. X
  540. X    QueueTri(hf, tri);
  541. X    return tri;
  542. X}
  543. X
  544. X/*
  545. X * Intersect ray with right isoscoles triangle, the hypotenuse of which
  546. X * has slope of -1.
  547. X */
  548. Xdouble
  549. XintHftri(ray, pos, tri)
  550. XhfTri *tri;
  551. XVector *pos, *ray;
  552. X{
  553. X    double u, v, dist, xpos, ypos;
  554. X
  555. X    u = dotp(&tri->norm, pos) + tri->d;
  556. X    v = dotp(&tri->norm, ray);
  557. X
  558. X    if ((u <= 0. || v > -EPSILON) && (u >= 0. && v < EPSILON))
  559. X        return FAR_AWAY;
  560. X
  561. X    dist = -u / v;
  562. X
  563. X    if (dist < EPSILON)
  564. X        return FAR_AWAY;
  565. X
  566. X    xpos = pos->x + dist*ray->x;
  567. X    ypos = pos->y + dist*ray->y;
  568. X
  569. X    if (tri->type == TRI1 && xpos >= tri->v1.x && ypos >= tri->v1.y &&
  570. X        xpos + ypos <= tri->v2.x + tri->v2.y)
  571. X        return dist;
  572. X    if (tri->type == TRI2 && xpos <= tri->v2.x && ypos <= tri->v2.y &&
  573. X        xpos + ypos >= tri->v1.x + tri->v1.y)
  574. X        return dist;
  575. X    return FAR_AWAY;
  576. X}
  577. X
  578. X/*
  579. X * Compute normal to height field.
  580. X */
  581. Xnrmhf(pos, prim, nrm)
  582. XVector *pos, *nrm;
  583. XPrimitive *prim;
  584. X{
  585. X    *nrm = prim->objpnt.p_hf->hittri.norm;
  586. X}
  587. X
  588. X/*
  589. X * Compute heightfield bounding box.
  590. X */
  591. Xhfextent(obj, bounds)
  592. XPrimitive *obj;
  593. Xdouble bounds[2][3];
  594. X{
  595. X    Hf *hf = obj->objpnt.p_hf;
  596. X
  597. X    /*
  598. X     * By default, height fields are centered at (0.5, 0.5, 0.)
  599. X     */
  600. X    bounds[LOW][X] = bounds[LOW][Y] = 0;
  601. X    bounds[HIGH][X] = bounds[HIGH][Y] = 1;
  602. X    bounds[LOW][Z] = hf->minz;
  603. X    bounds[HIGH][Z] = hf->maxz;
  604. X}
  605. X
  606. X/*
  607. X * Build min/max altitude value arrays for the given grid level.
  608. X */
  609. Xintegrate_grid(hf, level)
  610. XHf *hf;
  611. Xint level;
  612. X{
  613. X    int i, j, k, l, ii, ji;
  614. X    float max_alt, min_alt;
  615. X    float **maxinto, **mininto, **frommax, **frommin, *minptr, *maxptr;
  616. X    int insize, fromsize, fact;
  617. X
  618. X    maxinto = hf->boundsmax[level];
  619. X    mininto = hf->boundsmin[level];
  620. X    insize = hf->lsize[level];
  621. X    frommax = hf->boundsmax[level-1];
  622. X    frommin = hf->boundsmin[level-1];
  623. X    fact = hf->BestSize;
  624. X    fromsize = hf->lsize[level-1];
  625. X
  626. X    ii = 0;
  627. X
  628. X    for (i = 0; i < insize; i++) {
  629. X        ji = 0;
  630. X        for (j = 0; j < insize; j++) {
  631. X            max_alt = HF_UNSET;
  632. X            min_alt = -HF_UNSET;
  633. X            for (k = 0; k <= fact; k++) {
  634. X                if (ii+k >= fromsize)
  635. X                    continue;
  636. X                maxptr = &frommax[ii+k][ji];
  637. X                minptr = &frommin[ii+k][ji];
  638. X                for (l = 0; l <= fact; l++,maxptr++,minptr++) {
  639. X                    if (ji+l >= fromsize)
  640. X                        continue;
  641. X                    if (*maxptr > max_alt)
  642. X                        max_alt = *maxptr;
  643. X                    if (*minptr < min_alt)
  644. X                        min_alt = *minptr;
  645. X                }
  646. X            }
  647. X            maxinto[i][j] = max_alt + EPSILON;
  648. X            mininto[i][j] = min_alt - EPSILON;
  649. X            ji += fact;
  650. X        }
  651. X        ii += fact;
  652. X    }
  653. X}
  654. X
  655. X/*
  656. X * Place the given triangle in the triangle cache.
  657. X */
  658. XQueueTri(hf, tri)
  659. XHf *hf;
  660. XhfTri *tri;
  661. X{
  662. X    if (hf->q[hf->qtail])        /* Free old triangle data */
  663. X        free((char *)hf->q[hf->qtail]);
  664. X    hf->q[hf->qtail] = tri;        /* Put on tail */
  665. X    hf->qtail = (hf->qtail + 1) % hf->qsize;    /* Increment tail */
  666. X}
  667. X
  668. X/*
  669. X * Search list of cached trianges to see if this triangle has been
  670. X * cached.  If so, return a pointer to it.  If not, return null pointer.
  671. X */
  672. XhfTri *
  673. XGetQueuedTri(hf, x, y, flag)
  674. XHf *hf;
  675. Xdouble x, y;
  676. Xint flag;
  677. X{
  678. X    register int i;
  679. X    register hfTri **tmp;
  680. X
  681. X    for (i = 0, tmp = hf->q; i < hf->qsize; i++, tmp++) {
  682. X        if (*tmp && (*tmp)->v1.x == x && (*tmp)->v1.y == y &&
  683. X            (*tmp)->type == flag)
  684. X            return *tmp;    /* vertices & flag match, return it */
  685. X    }
  686. X
  687. X    return (hfTri *)0;
  688. X}
  689. X
  690. X/*
  691. X * Return maximum height of cell indexed by y,x.  This could be done
  692. X * as a macro, but many C compliers will choke on it.
  693. X */
  694. Xfloat
  695. Xminalt(y,x,data)
  696. Xint x, y;
  697. Xfloat **data;
  698. X{
  699. X    float  min_alt;
  700. X
  701. X    min_alt = min(data[y][x], data[y+1][x]);
  702. X    min_alt = min(min_alt, data[y][x+1]);
  703. X    min_alt = min(min_alt, data[y+1][x+1]);
  704. X    return min_alt;
  705. X}
  706. X
  707. X/*
  708. X * Return maximum cell height, as above.
  709. X */
  710. Xfloat
  711. Xmaxalt(y,x,data)
  712. Xint x, y;
  713. Xfloat **data;
  714. X{
  715. X    float  max_alt;
  716. X
  717. X    max_alt = max(data[y][x], data[y+1][x]);
  718. X    max_alt = max(max_alt, data[y][x+1]);
  719. X    max_alt = max(max_alt, data[y+1][x+1]);
  720. X    return max_alt;
  721. X}
  722. END_OF_FILE
  723. if test 17271 -ne `wc -c <'src/hf.c'`; then
  724.     echo shar: \"'src/hf.c'\" unpacked with wrong size!
  725. fi
  726. # end of 'src/hf.c'
  727. fi
  728. if test -f 'src/input_yacc.y' -a "${1}" != "-c" ; then 
  729.   echo shar: Will not clobber existing file \"'src/input_yacc.y'\"
  730. else
  731. echo shar: Extracting \"'src/input_yacc.y'\" \(14190 characters\)
  732. sed "s/^X//" >'src/input_yacc.y' <<'END_OF_FILE'
  733. X/* input_yacc.y                                    */
  734. X/*                                        */
  735. X/* Copyright (C) 1989, Craig E. Kolb                        */
  736. X/*                                        */
  737. X/* This software may be freely copied, modified, and redistributed,        */
  738. X/* provided that this copyright notice is preserved on all copies.        */
  739. X/*                                         */
  740. X/* There is no warranty or other guarantee of fitness for this software,    */
  741. X/* it is provided solely "as is".  Bug reports or fixes may be sent        */
  742. X/* to the author, who may or may not act on them as he desires.            */
  743. X/*                                        */
  744. X/* You may not include this software in a program or other software product */
  745. X/* without supplying the source, or without informing the end-user that the */
  746. X/* source is available for no extra charge.                    */
  747. X/*                                        */
  748. X/* If you modify this software, you should include a notice giving the        */
  749. X/* name of the person performing the modification, the date of modification,*/
  750. X/* and the reason for such modification.                    */
  751. X/*                                        */
  752. X/* $Id: input_yacc.y,v 3.0 89/10/27 02:05:53 craig Exp $ */
  753. X%{
  754. X#include <stdio.h>
  755. X#include "constants.h"
  756. X#include "typedefs.h"
  757. X#include "funcdefs.h"
  758. X#include "texture.h"
  759. X
  760. Xint Npoints=0, CurXSize, CurYSize, CurZSize;
  761. XObject *LastObj = (Object *)0;
  762. XObjList *CurObj, *ListTmp;
  763. XSurface *stmp;
  764. XTexture *CurText;
  765. XTransInfo *CurTrans = (TransInfo *)0, CurITrans;
  766. XPointList *Polypoints, *Point;
  767. Xextern FILE *yyin;
  768. Xextern Object *World;
  769. Xextern int WorldXSize, WorldYSize, WorldZSize, nlight, Xres, Yres, maxlevel;
  770. Xextern int yylineno, Jittered, JitSamples, pixel_div;
  771. Xextern double hfov, vfov, RedContrast, GreenContrast, BlueContrast;
  772. Xextern double TreeCutoff;
  773. Xextern Vector eyep, lookp, up;
  774. Xextern char outfilename[];
  775. Xextern Color background;
  776. Xextern SurfaceList *Surfaces;
  777. Xextern Light light[];
  778. Xextern Fog *GlobalFog;
  779. Xextern Mist *GlobalMist;
  780. X%}
  781. X%union {
  782. X    char *c;
  783. X    int i;
  784. X    double d;
  785. X    Vector v;
  786. X    Color col;
  787. X    struct Texture *text;
  788. X}
  789. X%token <i> tINT
  790. X%token <d> tFLOAT
  791. X%token <c> tSTRING
  792. X%token tADAPTIVE tBACKGROUND tBLOTCH tBOX tBUMP tCONE tCYL tDIRECTIONAL
  793. X%token tENDDEF tEXTENDED tEYEP tFBM tFBMBUMP tFOG tFOV tGRID
  794. X%token tHEIGHTFIELD tJITTERED tLIGHT tLIST tLOOKP tMARBLE tMAXDEPTH tMIST
  795. X%token tOBJECT tOUTFILE
  796. X%token tPLANE tPOINT tPOLY tROTATE tSAMPLES
  797. X%token tSCALE tSCREEN tSPHERE tSTARTDEF tSUPERQ tSURFACE tRESOLUTION
  798. X%token tTHRESH tTRANSLATE tTRANSFORM tTRIANGLE tUP tENDFILE
  799. X%token tTEXTURE tCHECKER tWOOD tCONTRAST tCUTOFF
  800. X%type <d> Fnumber
  801. X%type <c> String
  802. X%type <v> Vector
  803. X%type <col> Color
  804. X%type <text> Texturetype
  805. X%%
  806. XItems        : /* empty */
  807. X        | Items Item
  808. X        ;
  809. XItem        : Eyep
  810. X        | Lookp
  811. X        | Up
  812. X        | Fov
  813. X        | Screen
  814. X        | Maxdepth
  815. X        | Samples
  816. X        | Jittered
  817. X        | Adaptive
  818. X        | Contrast
  819. X        | Cutoff
  820. X        | Background
  821. X        | Light
  822. X        | Primitive
  823. X        | Child
  824. X        | Surface
  825. X        | Outfile
  826. X        | List
  827. X        | Grid
  828. X        | Object
  829. X        | Fog
  830. X        | Mist
  831. X        | tENDFILE        /* For backward compatibility */
  832. X        ;
  833. XList        : tLIST
  834. X        {
  835. X            if (CurObj->data)
  836. X                CurObj->data->type = LIST;
  837. X            else
  838. X                World->type = LIST;
  839. X        }
  840. X        ;
  841. XGrid        : tGRID tINT tINT tINT
  842. X        {
  843. X            if (CurObj->data) {
  844. X                CurObj->data->type = GRID;
  845. X                CurXSize = $2;
  846. X                CurYSize = $3;
  847. X                CurZSize = $4;
  848. X            } else {
  849. X                World->type = GRID;
  850. X                WorldXSize = $2;
  851. X                WorldYSize = $3;
  852. X                WorldZSize = $4;
  853. X            }
  854. X        }
  855. X        ;
  856. XPrimitive    : Prim Textures
  857. X        {
  858. X            if (LastObj)
  859. X                /* User may have botched prim. def. */
  860. X                LastObj->texture = CurText;
  861. X            CurText = (Texture *)0;
  862. X            LastObj = (Object *)0;
  863. X        }
  864. X        ;
  865. XPrim        : Primtype Transforms
  866. X        {
  867. X            if (LastObj != (Object *)0) {
  868. X                /*
  869. X                 * Compute boundings box of primitive.
  870. X                 * if box's low X is > its high X,
  871. X                 * then the prim is unbounded.
  872. X                 */
  873. X                set_prim_bounds(LastObj);
  874. X                /*
  875. X                 * Add primitive to current object
  876. X                 * list.  When the obj. def. is complete
  877. X                 * make_list() will calculate the
  878. X                 * bounding box of the entire object.
  879. X                 */
  880. X                add_prim(LastObj, CurObj->data);
  881. X                if (CurTrans) {
  882. X                    /*
  883. X                     * Compute the bounding box of the
  884. X                     * transformed object.
  885. X                     */
  886. X                    transform_bounds(CurTrans,
  887. X                            LastObj->bounds);
  888. X                    invert_trans(&CurITrans, CurTrans);
  889. X                    LastObj->trans = new_trans(CurTrans,
  890. X                                &CurITrans);
  891. X                    free((char *)CurTrans);
  892. X                    CurTrans = (TransInfo *)0;
  893. X                }
  894. X            } else {
  895. X                /*
  896. X                 * There was something wrong with the def.
  897. X                 */
  898. X                if (CurTrans) {
  899. X                    free((char *)CurTrans);
  900. X                    CurTrans = (TransInfo *)0;
  901. X                }
  902. X            }
  903. X        }
  904. X        ;
  905. XPrimtype    : Plane
  906. X        | Sphere
  907. X        | Box
  908. X        | Triangle
  909. X        | Cylinder
  910. X        | Cone
  911. X        | Superq
  912. X        | Poly
  913. X        | HeightField
  914. X        ;
  915. XObject        : Objectdef Textures
  916. X        {
  917. X            CurObj->data->texture = CurText;
  918. X            CurText = (Texture *)0;
  919. X            free((char *)CurObj);
  920. X            CurObj = CurObj->next;
  921. X        }
  922. X        ;
  923. XObjectdef    : Startdef Objdefs tENDDEF
  924. X        {
  925. X            /*
  926. X             * Object definition.
  927. X             */
  928. X            LastObj = (Object *)NULL;
  929. X            if (CurObj->data->data == (char *)0) {
  930. X                fprintf(stderr,"Warning: null object defined");
  931. X                fprintf(stderr," (line %d)\n",yylineno);
  932. X            } else {
  933. X                if (CurObj->data->type == GRID) {
  934. X                    list2grid(CurObj->data, CurXSize,
  935. X                        CurYSize, CurZSize);
  936. X                } else {
  937. X                    /*
  938. X                      * Object is a list -- transform the
  939. X                      * linked list (ObjList) into a List.
  940. X                      */
  941. X                    make_list(CurObj->data);
  942. X                }
  943. X                /*
  944. X                  * Add this new object to the list of
  945. X                  * defined objects.
  946. X                  */
  947. X                add_to_objects(CurObj->data);
  948. X            }
  949. X        }
  950. X        ;
  951. XStartdef    : tSTARTDEF String
  952. X        /*
  953. X         * define <name>
  954. X         */
  955. X        {
  956. X            /*
  957. X             * Once we know the bounding box of this object
  958. X             * (and the user hasn't specified that this object
  959. X             * is stored in a List), then we enlist everything
  960. X             * it contains.
  961. X             * The new object's DATA field points to an ObjList
  962. X             * until the definition complete, when the ObjList
  963. X             * is then turned into either a Grid or a List.
  964. X             */
  965. X            ListTmp = (ObjList *)Malloc(sizeof(ObjList));
  966. X            ListTmp->data = new_object($2, LIST, (char *)NULL,
  967. X                        (Trans *)NULL);
  968. X            ListTmp->next = CurObj;
  969. X            CurObj = ListTmp;
  970. X        }
  971. X        ;
  972. XObjdefs        : Objdefs Objdef
  973. X        |
  974. X        ;
  975. XObjdef        : Primitive
  976. X        | Surface
  977. X        | Child
  978. X        | List
  979. X        | Grid
  980. X        | Object
  981. X        ;
  982. XTextures    : Textures Texture
  983. X        |
  984. X        ;
  985. XTexture        : tTEXTURE Texturetype Transforms
  986. X        {
  987. X            /*
  988. X             * Set transformation information.
  989. X             */
  990. X            if (CurTrans) {
  991. X                invert_trans(&CurITrans, CurTrans);
  992. X                $2->trans = new_trans(CurTrans,&CurITrans);
  993. X                free((char *)CurTrans);
  994. X                CurTrans = (TransInfo *)NULL;
  995. X            }
  996. X            /*
  997. X             * Walk to the end of list of textures and
  998. X             * append new texture.  This is done so that
  999. X             * textures are implied in the expected order.
  1000. X             */
  1001. X            {
  1002. X                Texture *tp;
  1003. X
  1004. X                $2->next = (Texture *)0;
  1005. X
  1006. X                if (CurText) {
  1007. X                    for (tp=CurText;tp->next;tp=tp->next)
  1008. X                            ;
  1009. X                    tp->next = $2;
  1010. X
  1011. X                } else {
  1012. X                    CurText = $2;
  1013. X                }
  1014. X            }
  1015. X        }
  1016. X        ;
  1017. XTexturetype    : tCHECKER String
  1018. X        {
  1019. X            $$ = NewCheckText($2);
  1020. X        }
  1021. X        | tBLOTCH Fnumber String
  1022. X        {
  1023. X            $$ = NewBlotchText($2, $3);
  1024. X        }
  1025. X        | tBUMP Fnumber
  1026. X        {
  1027. X            $$ = NewBumpText($2);
  1028. X        }
  1029. X        | tMARBLE
  1030. X        {
  1031. X            $$ = NewMarbleText((char *)NULL);
  1032. X        }
  1033. X        | tMARBLE String
  1034. X        {
  1035. X            $$ = NewMarbleText($2);
  1036. X        }
  1037. X        | tFBM Fnumber Fnumber Fnumber Fnumber tINT Fnumber
  1038. X        {
  1039. X            $$ = NewfBmText($2, $3, $4, $5, $6, $7, (char *)0);
  1040. X        }
  1041. X        | tFBM Fnumber Fnumber Fnumber Fnumber tINT Fnumber tSTRING
  1042. X        {
  1043. X            $$ = NewfBmText($2, $3, $4, $5, $6, $7, $8);
  1044. X        }
  1045. X        | tFBMBUMP Fnumber Fnumber Fnumber Fnumber tINT
  1046. X        {
  1047. X            $$ = NewfBmBumpText($2, $3, $4, $5, $6);
  1048. X        }
  1049. X        | tWOOD
  1050. X        {
  1051. X            $$ = NewWoodText();
  1052. X        }
  1053. X        ;
  1054. XChild        : Childdef Textures
  1055. X        {
  1056. X            LastObj->texture = CurText;
  1057. X            CurText = (Texture *)0;
  1058. X            LastObj = (Object *)0;
  1059. X        }
  1060. X        ;
  1061. XChilddef    : tOBJECT String Transforms
  1062. X        {
  1063. X            LastObj = add_child_named($2, CurObj->data);
  1064. X            if (CurTrans) {
  1065. X                transform_bounds(CurTrans, LastObj->bounds);
  1066. X                invert_trans(&CurITrans, CurTrans);
  1067. X                if (LastObj->trans) {
  1068. X                    mmult(&LastObj->trans->obj2world,
  1069. X                        CurTrans,
  1070. X                        &LastObj->trans->obj2world);
  1071. X                    mmult(&LastObj->trans->world2obj,
  1072. X                        &CurITrans,
  1073. X                        &LastObj->trans->world2obj);
  1074. X                } else
  1075. X                    LastObj->trans = new_trans(CurTrans,
  1076. X                                &CurITrans);
  1077. X                free((char *)CurTrans);
  1078. X                CurTrans = (TransInfo *)NULL;
  1079. X            }
  1080. X        }
  1081. X        ;
  1082. XTransforms    : Transforms Transform
  1083. X        | /* empty */
  1084. X        ;
  1085. XTransform    : tTRANSLATE Vector
  1086. X        {
  1087. X            if (CurTrans == (TransInfo *)0)
  1088. X                CurTrans = new_transinfo();
  1089. X            translate(CurTrans, &($2));
  1090. X        }
  1091. X        | tROTATE Vector Fnumber
  1092. X        {
  1093. X            if (CurTrans == (TransInfo *)0)
  1094. X                CurTrans = new_transinfo();
  1095. X
  1096. X            rotate(CurTrans, &($2), deg2rad($3));
  1097. X        }
  1098. X        | tSCALE Fnumber Fnumber Fnumber
  1099. X        {
  1100. X            if (CurTrans == (TransInfo *)0)
  1101. X                CurTrans = new_transinfo();
  1102. X            scale(CurTrans, $2, $3, $4);
  1103. X        }
  1104. X        | tTRANSFORM Fnumber Fnumber Fnumber
  1105. X                Fnumber Fnumber Fnumber
  1106. X                Fnumber Fnumber Fnumber
  1107. X        {
  1108. X            if (CurTrans == (TransInfo *)0)
  1109. X                CurTrans = new_transinfo();
  1110. X            explicit_trans(CurTrans,
  1111. X                $2, $3, $4, $5, $6, $7, $8, $9, $10,
  1112. X                0., 0., 0., CurTrans);
  1113. X        }
  1114. X        | tTRANSFORM Fnumber Fnumber Fnumber
  1115. X                Fnumber Fnumber Fnumber
  1116. X                Fnumber Fnumber Fnumber
  1117. X                Fnumber Fnumber Fnumber
  1118. X        {
  1119. X            if (CurTrans == (TransInfo *)0)
  1120. X                CurTrans = new_transinfo();
  1121. X            explicit_trans(CurTrans,
  1122. X                $2, $3, $4, $5, $6, $7, $8, $9, $10,
  1123. X                $11, $12, $13,CurTrans);
  1124. X        }
  1125. X        ;
  1126. XEyep        : tEYEP Vector Transforms
  1127. X        {
  1128. X            eyep = $2;
  1129. X            if (CurTrans) {
  1130. X                transform_point(&eyep, CurTrans);
  1131. X                free((char *)CurTrans);
  1132. X                CurTrans = (TransInfo *)0;
  1133. X            }
  1134. X        }
  1135. X        ;
  1136. XLookp        : tLOOKP Vector
  1137. X        {
  1138. X            lookp = $2;
  1139. X        }
  1140. X        ;
  1141. XUp        : tUP Vector
  1142. X        {
  1143. X            up = $2;
  1144. X        }
  1145. X        ;
  1146. XFov        : tFOV Fnumber Fnumber
  1147. X        {
  1148. X            hfov = $2; vfov = $3;
  1149. X        }
  1150. X        | tFOV Fnumber
  1151. X        {
  1152. X            hfov = $2;
  1153. X        }
  1154. X        ;
  1155. XSamples        : tSAMPLES tINT
  1156. X        {
  1157. X            if (JitSamples == UNSET)
  1158. X                JitSamples = $2;
  1159. X        }
  1160. X        ;
  1161. XAdaptive    : tADAPTIVE tINT
  1162. X        {
  1163. X            if (pixel_div == UNSET && !Jittered)
  1164. X                pixel_div = $2;
  1165. X        }
  1166. X        ;
  1167. XContrast    : tCONTRAST Fnumber Fnumber Fnumber
  1168. X        {
  1169. X            if (RedContrast == UNSET ||
  1170. X                GreenContrast == UNSET ||
  1171. X                BlueContrast == UNSET) {
  1172. X                RedContrast = $2;
  1173. X                GreenContrast = $3;
  1174. X                BlueContrast = $4;
  1175. X            }
  1176. X        }
  1177. X        ;
  1178. XCutoff        : tCUTOFF Fnumber
  1179. X        {
  1180. X            if (TreeCutoff == UNSET)
  1181. X                TreeCutoff = $2;
  1182. X        }
  1183. X        ;
  1184. XJittered    : tJITTERED
  1185. X        {
  1186. X            if (pixel_div == UNSET)
  1187. X                Jittered = TRUE;
  1188. X        }
  1189. X        ;
  1190. XScreen        : tSCREEN tINT tINT
  1191. X        {
  1192. X            if (Xres == UNSET || Yres == UNSET) {
  1193. X                Xres = $2;
  1194. X                Yres = $3;
  1195. X            }
  1196. X        }
  1197. X        | tRESOLUTION tINT tINT
  1198. X        {
  1199. X            if (Xres == UNSET || Yres == UNSET) {
  1200. X                Xres = $2;
  1201. X                Yres = $3;
  1202. X            }
  1203. X        }
  1204. X        ;
  1205. XMaxdepth    : tMAXDEPTH tINT
  1206. X        {
  1207. X            maxlevel = $2;
  1208. X        }
  1209. X        ;
  1210. XBackground    : tBACKGROUND Color
  1211. X        {
  1212. X            background = $2;
  1213. X        }
  1214. X        ;
  1215. XLight        : Lightdef tPOINT Vector
  1216. X        {
  1217. X            light[nlight].pos = $3;
  1218. X            light[nlight].type = LOCAL;
  1219. X            nlight++;
  1220. X        }
  1221. X        | Lightdef tDIRECTIONAL Vector
  1222. X        {
  1223. X            (void)normalize(&($3));
  1224. X            light[nlight].pos = $3;
  1225. X            light[nlight].type = DIRECTIONAL;
  1226. X            nlight++;
  1227. X        }
  1228. X        | Lightdef tEXTENDED Vector Fnumber
  1229. X        {
  1230. X            light[nlight].pos = $3;
  1231. X            light[nlight].radius = $4;
  1232. X            light[nlight].type = EXTENDED;
  1233. X            nlight++;
  1234. X        }
  1235. X        ;
  1236. XLightdef    : tLIGHT Fnumber
  1237. X        {
  1238. X            if (nlight == LIGHTS)
  1239. X                yyerror("Too many lights.");
  1240. X            light[nlight].color.r = $2;
  1241. X            light[nlight].color.g = $2;
  1242. X            light[nlight].color.b = $2;
  1243. X        }
  1244. X        | tLIGHT Color
  1245. X        {
  1246. X            if (nlight == LIGHTS)
  1247. X                yyerror("Too many lights.\n");
  1248. X            light[nlight].color = $2;
  1249. X        }
  1250. X        ;
  1251. XSurface        : tSURFACE String
  1252. X            Color Color Color
  1253. X            Fnumber Fnumber Fnumber Fnumber
  1254. X        {
  1255. X            /*
  1256. X             * surface name
  1257. X             *     amb
  1258. X             *     diff
  1259. X             *     spec coef reflect refract krefract
  1260. X             */
  1261. X            stmp = make_surface($2, &($3), &($4), &($5), $6, $7,
  1262. X                    $8, $9, 0., 0.);
  1263. X            Surfaces = add_surface(stmp, Surfaces);
  1264. X
  1265. X        }
  1266. X        | tSURFACE String Color Color Color
  1267. X            Fnumber Fnumber Fnumber Fnumber Fnumber Fnumber
  1268. X        {
  1269. X            /*
  1270. X             * surface name
  1271. X             *     amb
  1272. X             *     diff
  1273. X             *     spec coef reflect refract krefract
  1274. X             */
  1275. X            stmp = make_surface($2, &($3), &($4), &($5), $6, $7,
  1276. X                    $8, $9, $10, $11);
  1277. X            Surfaces = add_surface(stmp, Surfaces);
  1278. X
  1279. X        }
  1280. X        ;
  1281. XHeightField    : tHEIGHTFIELD tSTRING tSTRING
  1282. X        {
  1283. X            LastObj = makhf($2, $3);
  1284. X        }
  1285. X        ;
  1286. XPoly        : tPOLY tSTRING Polypoints
  1287. X        {
  1288. X            LastObj = makpoly($2, Polypoints, Npoints);
  1289. X            Polypoints = (PointList *)0;
  1290. X            Npoints = 0;
  1291. X        }
  1292. X        ;
  1293. XPolypoints    : /* empty */
  1294. X        | Polypoints Polypoint
  1295. X        ;
  1296. XPolypoint    : Vector
  1297. X        {
  1298. X            Point = (PointList *)Malloc(sizeof(PointList));
  1299. X            Point->vec = $1;
  1300. X            Point->next = Polypoints;
  1301. X            Polypoints = Point;
  1302. X            Npoints++;
  1303. X        }
  1304. X        ;
  1305. XCone        : tCONE tSTRING Vector Vector Fnumber Fnumber
  1306. X        {
  1307. X            CurTrans = new_transinfo();
  1308. X            LastObj = makcone($2, &($3), &($4), $5, $6, CurTrans);
  1309. X        }
  1310. X        ;
  1311. XCylinder    : tCYL tSTRING Vector Vector Fnumber
  1312. X        {
  1313. X            /*
  1314. X             * Cylinders automagically define a
  1315. X             * transformation matrix.
  1316. X             */
  1317. X            CurTrans = new_transinfo();
  1318. X            LastObj = makcyl($2, &($3), &($4), $5, CurTrans);
  1319. X        }
  1320. X        ;
  1321. XSphere        : tSPHERE tSTRING Fnumber Vector
  1322. X        {
  1323. X            LastObj = maksph($2, $3, &($4));
  1324. X        }
  1325. X        ;
  1326. XBox        : tBOX tSTRING
  1327. X            Fnumber Fnumber Fnumber
  1328. X            Fnumber Fnumber Fnumber
  1329. X        {
  1330. X            LastObj = makbox($2, $3, $4, $5, $6, $7, $8);
  1331. X        }
  1332. X        ;
  1333. XTriangle    : tTRIANGLE tSTRING Vector Vector Vector
  1334. X        {
  1335. X            LastObj = maktri(TRIANGLE, $2, &($3), &($4), &($5),
  1336. X                    (Vector *)0, (Vector *)0, (Vector *)0);
  1337. X        }
  1338. X        | tTRIANGLE tSTRING Vector Vector Vector Vector Vector Vector
  1339. X        {
  1340. X            LastObj = maktri(PHONGTRI, $2, &($3), &($5),
  1341. X                    &($7), &($4), &($6), &($8));
  1342. X        }
  1343. X        ;
  1344. XSuperq        : tSUPERQ tSTRING
  1345. X            Fnumber Fnumber Fnumber
  1346. X            Fnumber Fnumber Fnumber
  1347. X            Fnumber
  1348. X        {
  1349. X            LastObj = maksup($2, $3, $4, $5, $6, $7, $8, $9);
  1350. X        }
  1351. X        ;
  1352. XPlane        : tPLANE tSTRING Vector Vector
  1353. X        {
  1354. X            LastObj = makplane($2, &($3), &($4));
  1355. X        }
  1356. X        ;
  1357. XOutfile        : tOUTFILE String
  1358. X        {
  1359. X            if (*outfilename != (char)NULL)
  1360. X                fprintf(stderr,"Ignoring output name \"%s\"\n",
  1361. X                    $2);
  1362. X            else
  1363. X                strcpy(outfilename, $2);
  1364. X        }
  1365. X        ;
  1366. XMist        : tMIST Color Color Fnumber Fnumber
  1367. X        {
  1368. X            GlobalMist = (Mist *)Malloc(sizeof(Mist));
  1369. X            GlobalMist->color = $2;
  1370. X            GlobalMist->trans = $3;
  1371. X            GlobalMist->zero = $4;
  1372. X            GlobalMist->scale = 1. / $5;
  1373. X        }
  1374. X        ;
  1375. XFog        : tFOG Fnumber Color
  1376. X        {
  1377. X            GlobalFog = (Fog *)Malloc(sizeof(Fog));
  1378. X            GlobalFog->trans = 1./$2;
  1379. X            GlobalFog->color = $3;
  1380. X        }
  1381. X        ;
  1382. XColor        : Fnumber Fnumber Fnumber
  1383. X        {
  1384. X            $$.r = $1;
  1385. X            $$.g = $2;
  1386. X            $$.b = $3;
  1387. X        }
  1388. X        ;
  1389. XVector        : Fnumber Fnumber Fnumber
  1390. X        {
  1391. X            $$.x = $1;
  1392. X            $$.y = $2;
  1393. X            $$.z = $3;
  1394. X        }
  1395. X        ;
  1396. XFnumber        : tFLOAT
  1397. X        { $$ = $1;}
  1398. X        | tINT
  1399. X        { $$ = $1;}
  1400. X        ;
  1401. XString        : tSTRING
  1402. X        { $$ = $1;}
  1403. X%%
  1404. Xyyerror(s)
  1405. Xchar *s;
  1406. X{
  1407. X    extern char tmpname[];
  1408. X
  1409. X    fprintf(stderr,"rayshade: line %d: %s\n", yylineno, s);
  1410. X    unlink(tmpname);
  1411. X    exit(2);
  1412. X}
  1413. X
  1414. END_OF_FILE
  1415. if test 14190 -ne `wc -c <'src/input_yacc.y'`; then
  1416.     echo shar: \"'src/input_yacc.y'\" unpacked with wrong size!
  1417. fi
  1418. # end of 'src/input_yacc.y'
  1419. fi
  1420. if test -f 'src/raytrace.c' -a "${1}" != "-c" ; then 
  1421.   echo shar: Will not clobber existing file \"'src/raytrace.c'\"
  1422. else
  1423. echo shar: Extracting \"'src/raytrace.c'\" \(15323 characters\)
  1424. sed "s/^X//" >'src/raytrace.c' <<'END_OF_FILE'
  1425. X/*
  1426. X * raytrace.c
  1427. X *
  1428. X * Copyright (C) 1989, Craig E. Kolb
  1429. X *
  1430. X * This software may be freely copied, modified, and redistributed,
  1431. X * provided that this copyright notice is preserved on all copies.
  1432. X *
  1433. X * There is no warranty or other guarantee of fitness for this software,
  1434. X * it is provided solely .  Bug reports or fixes may be sent
  1435. X * to the author, who may or may not act on them as he desires.
  1436. X *
  1437. X * You may not include this software in a program or other software product
  1438. X * without supplying the source, or without informing the end-user that the
  1439. X * source is available for no extra charge.
  1440. X *
  1441. X * If you modify this software, you should include a notice giving the
  1442. X * name of the person performing the modification, the date of modification,
  1443. X * and the reason for such modification.
  1444. X *
  1445. X * $Id: raytrace.c,v 3.0 89/10/27 02:06:02 craig Exp $
  1446. X *
  1447. X * $Log:    raytrace.c,v $
  1448. X * Revision 3.0  89/10/27  02:06:02  craig
  1449. X * Baseline for first official release.
  1450. X * 
  1451. X */
  1452. X
  1453. X/*
  1454. X * This module could use some work.  In particular, a better antialiasing
  1455. X * scheme would be nice.
  1456. X */
  1457. X
  1458. X#ifdef LINDA
  1459. X/*
  1460. X * If you're using linda, be sure to *move* this file to "raytrace.cl"
  1461. X * before compiling.
  1462. X */
  1463. X#include "linda.h"
  1464. X#endif
  1465. X#include <math.h>
  1466. X#include <stdio.h>
  1467. X#include "typedefs.h"
  1468. X#include "constants.h"
  1469. X#include "funcdefs.h"
  1470. X#include "raytrace.h"
  1471. X
  1472. XColor    *pixel_buf[2], background;    /* Point buffer, background color */
  1473. XColor    *out_buf;            /* Output pixel buffer */
  1474. Xint    pixel_div = UNSET;        /* max times to subdivide pixel */
  1475. Xint    JitSamples = UNSET;        /* sqrt of # jittered samples/pixel */
  1476. Xdouble    JitterWeight;            /* 1. / (Total Samples Taken) */
  1477. Xint    Jittered;            /* Use distributed raytracing */
  1478. Xint    *SampleNumbers;
  1479. Xint    SampleNumber;
  1480. Xint    StartLine = UNSET;
  1481. Xdouble    RedContrast = UNSET, GreenContrast = UNSET, BlueContrast = UNSET;
  1482. Xdouble    SampleSpacing;
  1483. X
  1484. X#ifdef LINDA
  1485. Xextern    int Workers;
  1486. Xint adapt_worker(), dist_worker();
  1487. X#endif
  1488. X
  1489. Xextern    int Xres, Yres;
  1490. Xextern    Vector eyep, firstray;
  1491. XRay    TopRay;                /* Top-level ray. */
  1492. X
  1493. X#ifdef LINDA
  1494. X
  1495. Xreal_main(argc, argv)
  1496. Xint argc;
  1497. Xchar **argv;
  1498. X{
  1499. X    /*
  1500. X     * Linda wants all routines, including lmain(), to be in a single
  1501. X     * file.  So, we have to perform this bit of silliness.
  1502. X     */
  1503. X    return rayshade_main(argc, argv);
  1504. X}
  1505. X
  1506. X#endif
  1507. X
  1508. Xraytrace()
  1509. X{
  1510. X    /*
  1511. X     * The top-level ray TopRay always has as its origin the
  1512. X     * eye position and as its medium NULL, indicating that it
  1513. X     * is passing through a medium with index of refraction
  1514. X     * equal to DefIndex.
  1515. X     */
  1516. X    TopRay.pos = eyep;
  1517. X    TopRay.media = (SurfaceList *)0;
  1518. X    TopRay.shadow = FALSE;
  1519. X
  1520. X    out_buf = (Color *)Malloc(Xres * sizeof(Color));
  1521. X
  1522. X    if (Jittered)
  1523. X        distributed_trace();
  1524. X    else
  1525. X        adaptive_trace();
  1526. X}
  1527. X
  1528. X/*
  1529. X * Raytrace an image using "distributed" raytracing.
  1530. X */
  1531. Xdistributed_trace()
  1532. X{
  1533. X    register int y;
  1534. X    extern FILE *fstats;
  1535. X    extern unsigned long EyeRays;
  1536. X    extern int Verbose;
  1537. X
  1538. X    switch (JitSamples) {
  1539. X        case 1:
  1540. X            SampleNumbers = OneSample;
  1541. X            break;
  1542. X        case 2:
  1543. X            SampleNumbers = TwoSamples;
  1544. X            break;
  1545. X        case 3:
  1546. X            SampleNumbers = ThreeSamples;
  1547. X            break;
  1548. X        case 4:
  1549. X            SampleNumbers = FourSamples;
  1550. X            break;
  1551. X        case 5:
  1552. X            SampleNumbers = FiveSamples;
  1553. X            break;
  1554. X        default:
  1555. X            fprintf(stderr,"Sorry, %d rays/pixel not supported.\n",
  1556. X                JitSamples*JitSamples);
  1557. X            exit(2);
  1558. X    }
  1559. X
  1560. X    JitterWeight= 1. / (JitSamples * JitSamples);
  1561. X    SampleSpacing = 1. / JitSamples;
  1562. X
  1563. X#ifdef LINDA
  1564. X    /*
  1565. X     * Linda strategy:
  1566. X     * There is one tuple, named "scaninfo", which holds the number of
  1567. X     * the next line to be worked on.  A worker ins the scaninfo tuple,
  1568. X     * notes its value, and increments it before outing it again.
  1569. X     * The supervisor ins finished scanlines in order and writes them to
  1570. X     * the output file.
  1571. X     */
  1572. X    fprintf(fstats,"Using %d workers.\n",Workers);
  1573. X    out("scaninfo", StartLine);
  1574. X    for (y = 0; y < Workers; y++)
  1575. X        eval("worker", dist_worker());
  1576. X    for (y = StartLine; y >= 0 ; y--) {
  1577. X        in("result", y, ? out_buf);
  1578. X        if (Verbose)
  1579. X            fprintf(stderr,"Supervisor: inned %d\n",y);
  1580. X        if (y % 10 == 0)
  1581. X            fprintf(fstats, "Finished line %d.\n",y);
  1582. X        outline(out_buf);
  1583. X    }
  1584. X    for (y = 0; y < Workers; y++)
  1585. X        in("worker", ? int);
  1586. X#else
  1587. X    /*
  1588. X     * Trace each scanline, writing results to output file.
  1589. X     */
  1590. X    for (y = StartLine; y >= 0; y--) {
  1591. X        trace_jit_line(y, out_buf);
  1592. X        outline(out_buf);
  1593. X        if (y % 10 == 0) {
  1594. X            fprintf(fstats,"Finished line %d (%ld rays)\n",y,
  1595. X                            EyeRays);
  1596. X            fflush(fstats);
  1597. X        }
  1598. X    }
  1599. X#endif
  1600. X}
  1601. X
  1602. Xtrace_jit_line(line, buf)
  1603. Xint line;
  1604. XColor *buf;
  1605. X{
  1606. X    register int x;
  1607. X    for (x = 0; x < Xres; x++)
  1608. X        trace_jit_pixel(x, line, buf++);
  1609. X}
  1610. X
  1611. Xtrace_jit_pixel(xp, yp, color)
  1612. Xint xp, yp;
  1613. XColor *color;
  1614. X{
  1615. X    Color tmp;
  1616. X    double x, y, xpos, ypos;
  1617. X    int i, j, index;
  1618. X
  1619. X    ypos = (double)yp - 0.5;
  1620. X    color->r = color->g = color->b = 0.;
  1621. X    index = 0;
  1622. X    for (i = 0; i < JitSamples; i++, ypos += SampleSpacing) {
  1623. X        xpos = (double)xp - 0.5;
  1624. X        for (j = 0; j < JitSamples; j++, xpos += SampleSpacing) {
  1625. X            x = xpos + nrand() * SampleSpacing;
  1626. X            y = ypos + nrand() * SampleSpacing;
  1627. X            SampleNumber = SampleNumbers[index++];
  1628. X            trace_point(x, y, &tmp);
  1629. X            color->r += tmp.r;
  1630. X            color->g += tmp.g;
  1631. X            color->b += tmp.b;
  1632. X        }
  1633. X    }
  1634. X    ScaleColor(JitterWeight, *color, color);
  1635. X}
  1636. X
  1637. X/*
  1638. X * Raytrace an image using adaptive supersampling to perform antialising.
  1639. X */
  1640. Xadaptive_trace()
  1641. X{
  1642. X    register int line;
  1643. X    extern unsigned long EyeRays;
  1644. X    extern int maxlevel, Verbose;
  1645. X    extern FILE *fstats;
  1646. X
  1647. X    /*
  1648. X     * In the adaptive supersampling case, Jitter, JitterWeight,
  1649. X     * and SampleSpacing refer are used in sampling extended
  1650. X     * light sources.  JitterWeight has a -4 in the denominator
  1651. X     * due to the fact that we don't sample the corners of extended
  1652. X     * sources when performing adaptive supersampling.
  1653. X     */
  1654. X    JitterWeight = 1. / (JitSamples * JitSamples - 4);
  1655. X    SampleSpacing = 1. / JitSamples;
  1656. X
  1657. X    pixel_buf[0] = (Color *)Malloc(sizeof(Color) *
  1658. X                (unsigned)(Xres + 1));
  1659. X    pixel_buf[1] = (Color *)Malloc(sizeof(Color) *
  1660. X                (unsigned)(Xres + 1));
  1661. X    /*
  1662. X     * Minimum pixel square size.
  1663. X     */
  1664. X    Minsquare = 1./pow(2.,(double)pixel_div);
  1665. X    /*
  1666. X     * At any time, there can be a maximum of 3 * pixel_div + 1
  1667. X     * pixel squares on the stack.
  1668. X     */
  1669. X    SquareStack = (pixel_square *)Malloc((unsigned)(3 * pixel_div + 1) *
  1670. X                sizeof(pixel_square));
  1671. X    /*
  1672. X     * A pixel is treated as a square through whose corners rays
  1673. X     * are traced.  If the color values at the corners are
  1674. X     * "too different" (as measured by pixel_ok()), the square is
  1675. X     * divided into four squares (tracing 5 additional rays)
  1676. X     * and the process is repeated on the four new squares.
  1677. X     * The color assigned to a square is the average of the 4 corners.
  1678. X     * Note that this means that adjacent super-sampled pixels
  1679. X     * cause the same ray to be traced more than once.
  1680. X     * This scheme is adequate but far from wonderful.
  1681. X     */
  1682. X#ifdef LINDA
  1683. X    /*
  1684. X     * This is a bit more complicated than 'jittered' sampling,
  1685. X     * as workers must know about other scanlines.
  1686. X     *
  1687. X     * The basic idea is to have a "scanline" tuple which
  1688. X     * holds the last pixline handed out and the last scanline
  1689. X     * completed.  This should be improved by keeping a tuple
  1690. X     * containing the last completed scanline/pixline, and not
  1691. X     * just the last ones assigned.  (The problem being that a
  1692. X     * worker can try to in a pixline while another worker
  1693. X     * is still working on it.)
  1694. X     */
  1695. X    fprintf(fstats,"Using %d workers.\n",Workers);
  1696. X    out("scaninfo", StartLine+1, StartLine+2);
  1697. X    for (line = 0; line < Workers; line++)
  1698. X        eval("worker", adapt_worker());
  1699. X
  1700. X    /*
  1701. X     * in() the scanlines in order, writing to output file as we go.
  1702. X     * This loop can easily be modified to make the supervisor
  1703. X     * do some work, too.
  1704. X     */
  1705. X    for (line = StartLine; line >= 0;) {
  1706. X        if (!adapt_job(TRUE))
  1707. X            sleep(5);
  1708. X        while (inp("result", line, ? out_buf)) {
  1709. X            if (Verbose)
  1710. X                fprintf(stderr,"Supervisor: inned %d\n",line);
  1711. X            if (line % 10 == 0)
  1712. X                fprintf(fstats, "Finished line %d.\n",line);
  1713. X            outline(out_buf);
  1714. X            if (--line < 0)
  1715. X                break;
  1716. X        }
  1717. X    }
  1718. X    if (Verbose)
  1719. X        fprintf(stderr,"Finished -- inning workers.\n");
  1720. X    for (line = 0; line < Workers; line++)
  1721. X        in("worker", ? int);
  1722. X#else
  1723. X    line = StartLine + 1;
  1724. X    trace_line(line, &pixel_buf[line & 01][0]);
  1725. X    /*
  1726. X     * Work bottom-to-top, as that's the way Utah-raster wants to
  1727. X     * operate.
  1728. X     */
  1729. X    for(line--;line >= 0;line--) {
  1730. X        trace_line(line, &pixel_buf[line & 01][0]);
  1731. X        subdivide_line(line, pixel_buf[line & 01],
  1732. X                     pixel_buf[(line+1) & 01],
  1733. X                     out_buf);
  1734. X        outline(out_buf);
  1735. X        if(line % 10 == 0) {
  1736. X            fprintf(fstats,"Finished line %d (%ld rays)\n",line,
  1737. X                                EyeRays);
  1738. X            fflush(fstats);
  1739. X        }
  1740. X    }
  1741. X#endif
  1742. X}
  1743. X
  1744. X/*
  1745. X * Trace a line of sample points along "line".
  1746. X */
  1747. Xtrace_line(line, buf)
  1748. Xint line;
  1749. XColor *buf;
  1750. X{
  1751. X    register int x;
  1752. X    /*
  1753. X     * We need to trace Xres + 1 rays.
  1754. X     */
  1755. X    for(x = 0; x <= Xres;x++)
  1756. X        trace_point((double)x, (double)line, buf + x);
  1757. X}
  1758. X
  1759. X/*
  1760. X * Given the two arrays of sample points which define the upper and
  1761. X * lower edges of all the pixel squares in line "y," push each
  1762. X * square in turn on the pixelsquare stack and determine a color value
  1763. X * for the pixel by calling subdivide_square().
  1764. X */
  1765. Xsubdivide_line(y, upper, lower, buf)
  1766. Xint y;
  1767. XColor *upper, *lower, *buf;
  1768. X{
  1769. X    register int x;
  1770. X
  1771. X    /*
  1772. X     * Upper is the array of
  1773. X     * sample values which define the "upper" part (corners) of this
  1774. X     * row, while lower are the "lower" corners.  For the
  1775. X     * next (lower) row, the current "upper" becomes "lower".
  1776. X     */
  1777. X    for(x = 0; x < Xres;x++) {
  1778. X        SquareStack[0].x = (float)x;
  1779. X        SquareStack[0].y = (float)y;
  1780. X        SquareStack[0].size = 1.0;
  1781. X        SquareStack[0].ul = upper[x];
  1782. X        SquareStack[0].ur = upper[x+1];
  1783. X        SquareStack[0].ll = lower[x];
  1784. X        SquareStack[0].lr = lower[x+1];
  1785. X        subdivide_square(&buf[x]);
  1786. X    }
  1787. X}
  1788. X
  1789. X/*
  1790. X * Bleck, but it saves us a function call and keeps the code much cleaner.
  1791. X */
  1792. X#define push_square(u,v,s,a,b,c,d) {\
  1793. X            Stackp->x = u; \
  1794. X            Stackp->y = v; \
  1795. X            Stackp->size = s; \
  1796. X            Stackp->ul = a; \
  1797. X            Stackp->ur = b; \
  1798. X            Stackp->ll = c; \
  1799. X            Stackp->lr = d; \
  1800. X            Stackp++;}
  1801. X
  1802. X/*
  1803. X * Subdivide a pixel square.
  1804. X */
  1805. Xsubdivide_square(color)
  1806. XColor *color;
  1807. X{
  1808. X    register pixel_square *Stackp;
  1809. X    register float x, y;
  1810. X    float size, halfsize;
  1811. X    double avfact, xdelta, ydelta;
  1812. X    Color ul, ur, ll, lr, u, d, l, r, c;
  1813. X    extern unsigned long SuperSampled;
  1814. X
  1815. X    color->r = color->g = color->b = 0.;
  1816. X    Stackp = SquareStack + 1;
  1817. X
  1818. X    do {
  1819. X        Stackp--;
  1820. X        size = Stackp->size;
  1821. X        ul = Stackp->ul;
  1822. X        ur = Stackp->ur;
  1823. X        ll = Stackp->ll;
  1824. X        lr = Stackp->lr;
  1825. X
  1826. X        if(size <= Minsquare || pixel_ok(&ul,&ur,&ll,&lr)) {
  1827. X            /*
  1828. X             * The square is either the smallest allowed, or
  1829. X             * the four corners of the square are similar.
  1830. X             * Average the four corners (weighted by the
  1831. X             * size of the square) to get this square's
  1832. X             * contribution to the whole pixel's color.
  1833. X             */
  1834. X            avfact = (size * size) * 0.25;
  1835. X            color->r += (ul.r + ur.r + ll.r + lr.r) * avfact;
  1836. X            color->g += (ul.g + ur.g + ll.g + lr.g) * avfact;
  1837. X            color->b += (ul.b + ur.b + ll.b + lr.b) * avfact;
  1838. X            continue;
  1839. X        }
  1840. X        /*
  1841. X         * Subdivide into four squares -- trace 5 additional
  1842. X         * rays and push the appropriate squares on the pixelsquare
  1843. X         * stack.
  1844. X         */
  1845. X        x = Stackp->x;
  1846. X        y = Stackp->y;
  1847. X        halfsize = size * 0.5;
  1848. X        xdelta = (double)(x + halfsize);
  1849. X        ydelta = (double)(y + halfsize);
  1850. X        trace_point(xdelta, (double)y, &u);
  1851. X        trace_point((double)x, ydelta, &l);
  1852. X        trace_point(xdelta, ydelta, &c);
  1853. X        trace_point((double)(x + size),ydelta, &r);
  1854. X        trace_point(xdelta, (double)(y + size), &d);
  1855. X        if(size == 1.)
  1856. X            SuperSampled++;
  1857. X        push_square(x, y, halfsize, ul, u, l, c);
  1858. X        push_square((float)xdelta, y, halfsize, u, ur, c, r);
  1859. X        push_square(x, (float)ydelta, halfsize, l, c, ll, d);
  1860. X        push_square((float)xdelta, (float)ydelta, halfsize,
  1861. X                    c, r, d, lr);
  1862. X    } while (Stackp != SquareStack);
  1863. X}
  1864. X
  1865. X/*
  1866. X * Trace a ray through x, y on the screen, placing the result in "color."
  1867. X */
  1868. Xtrace_point(x, y, color)
  1869. Xdouble x, y;
  1870. XColor *color;
  1871. X{
  1872. X    double dist;
  1873. X    HitInfo hitinfo;
  1874. X    extern Vector scrnx, scrny;
  1875. X    extern unsigned long EyeRays;
  1876. X    extern double TraceRay();
  1877. X
  1878. X    /*
  1879. X     * Calculate ray direction.
  1880. X     */
  1881. X    EyeRays++;
  1882. X    TopRay.dir.x = firstray.x + x*scrnx.x - y*scrny.x;
  1883. X    TopRay.dir.y = firstray.y + x*scrnx.y - y*scrny.y;
  1884. X    TopRay.dir.z = firstray.z + x*scrnx.z - y*scrny.z;
  1885. X
  1886. X    (void)normalize(&TopRay.dir);
  1887. X
  1888. X    /*
  1889. X     * Do the actual ray trace.
  1890. X     */
  1891. X    dist = TraceRay((Primitive *)NULL, &TopRay, &hitinfo);
  1892. X    if (dist > 0.)
  1893. X        /*
  1894. X         * There was a valid intersection.
  1895. X         */
  1896. X        ShadeRay(&hitinfo, &TopRay, dist, &background, color, 1.0);
  1897. X    else
  1898. X        /* Use background color */
  1899. X        *color = background;
  1900. X}
  1901. X
  1902. X/*
  1903. X * Return TRUE if this pixel is okay and doesn't need to be supersampled,
  1904. X * FALSE otherwise.
  1905. X */
  1906. Xpixel_ok(w,x,y,z)
  1907. XColor *w, *x, *y, *z;
  1908. X{
  1909. X    double rmax, rmin, gmax, gmin, bmax, bmin;
  1910. X    double rsum, gsum, bsum;
  1911. X
  1912. X    /*
  1913. X     * Find min & max R, G, & B.
  1914. X     */
  1915. X    rmax = max(w->r, max(x->r, max(y->r, z->r)));
  1916. X    rmin = min(w->r, min(x->r, min(y->r, z->r)));
  1917. X    gmax = max(w->g, max(x->g, max(y->g, z->g)));
  1918. X    gmin = min(w->g, min(x->g, min(y->g, z->g)));
  1919. X    bmax = max(w->b, max(x->b, max(y->b, z->b)));
  1920. X    bmin = min(w->b, min(x->b, min(y->b, z->b)));
  1921. X
  1922. X    /*
  1923. X     * Contrast is defined as (Max - Min) / (Max + Min) for each
  1924. X     * of RG&B.  If any of these values is greater than the maximum
  1925. X     * allowed, we have to supersample.
  1926. X     */
  1927. X    rsum = rmax + rmin;
  1928. X    gsum = gmax + gmin;
  1929. X    bsum = bmax + bmin;
  1930. X    if ((rsum == 0. || (rmax - rmin) / rsum < RedContrast) &&
  1931. X        (gsum == 0. || (bmax - bmin) / gsum < BlueContrast) &&
  1932. X        (bsum == 0. || (gmax - gmin) / bsum < GreenContrast))
  1933. X        return TRUE;
  1934. X
  1935. X    return FALSE;
  1936. X}
  1937. X
  1938. X#ifdef LINDA
  1939. Xdist_worker()
  1940. X{
  1941. X    while (dist_job())
  1942. X        ;
  1943. X    return;
  1944. X}
  1945. X
  1946. X/*
  1947. X * Worker trained to perform distributed ray-tracing.
  1948. X */
  1949. Xdist_job()
  1950. X{
  1951. X    int y;
  1952. X    extern int Verbose;
  1953. X
  1954. X    in("scaninfo", ? y);
  1955. X    if (y < 0) {
  1956. X        out("scaninfo", y);
  1957. X        return 0;
  1958. X    }
  1959. X    if (Verbose)
  1960. X        fprintf(stderr,"Worker: inned %d\n",y);
  1961. X    out("scaninfo", y-1);
  1962. X    trace_jit_line(y, out_buf);
  1963. X    if (Verbose)
  1964. X        fprintf(stderr,"Worker: outing %d\n",y);
  1965. X    out("result", y, out_buf : Xres);
  1966. X    return 1;
  1967. X}
  1968. X
  1969. Xadapt_worker()
  1970. X{
  1971. X    while (adapt_job(FALSE))
  1972. X        ;
  1973. X    return;
  1974. X}
  1975. X
  1976. Xadapt_job(supervisor)
  1977. Xint supervisor;
  1978. X{
  1979. X    int lastpix, lastscan;
  1980. X    extern int Verbose;
  1981. X
  1982. X    in("scaninfo", ? lastpix, ? lastscan);
  1983. X    if (lastpix <= 0) {
  1984. X        out("scaninfo", lastpix, lastscan);
  1985. X        if (Verbose)
  1986. X            fprintf(stderr,"Worker:  all finished!\n");
  1987. X        return FALSE;
  1988. X    }
  1989. X
  1990. X    if (rdp("scanline", lastpix -1, ? pixel_buf[0]) &&
  1991. X        inp("scanline", lastpix, ? pixel_buf[1])) {
  1992. X        lastpix--;
  1993. X        out("scaninfo", lastpix, lastscan);
  1994. X        if (Verbose)
  1995. X            fprintf(stderr,"%s: doing pixline %d\n",
  1996. X                supervisor ? "Supervisor" : "Worker",
  1997. X                    lastpix);
  1998. X        subdivide_line(lastpix, pixel_buf[0], pixel_buf[1],
  1999. X                    out_buf);
  2000. X        out("result", lastpix, out_buf : Xres);
  2001. X    } else if (supervisor) {
  2002. X        /*
  2003. X         * Don't let the supervisor get caught up in
  2004. X         * ray-tracing a whole scanline.  It might take
  2005. X         * a long, long time, causing tuple-space to get
  2006. X         * jammed with finished pixlines, and...
  2007. X         */
  2008. X        if (Verbose)
  2009. X            fprintf(stderr,"Supervisor: nothing to do...\n");
  2010. X        out ("scaninfo", lastpix, lastscan);
  2011. X        return FALSE;
  2012. X    } else if (lastscan > 0) {
  2013. X        lastscan--;
  2014. X        out("scaninfo", lastpix, lastscan);
  2015. X        if (Verbose)
  2016. X            fprintf(stderr,"Worker: doing scan %d\n",
  2017. X                    lastscan);
  2018. X        trace_line(lastscan, pixel_buf[0]);
  2019. X        out("scanline", lastscan, pixel_buf[0] : Xres + 1);
  2020. X    } else {
  2021. X        /*
  2022. X         * Nothing to do until somebody finishes a scanline.
  2023. X         */
  2024. X        if (Verbose) {
  2025. X            fprintf(stderr,"Worker idle... ");
  2026. X            fprintf(stderr,"pix = %d, scan = %d\n",
  2027. X                    lastpix, lastscan);
  2028. X        }
  2029. X        out("scaninfo", lastpix, lastscan);
  2030. X        sleep(2);
  2031. X    }
  2032. X    return 1;
  2033. X}
  2034. X#endif
  2035. END_OF_FILE
  2036. if test 15323 -ne `wc -c <'src/raytrace.c'`; then
  2037.     echo shar: \"'src/raytrace.c'\" unpacked with wrong size!
  2038. fi
  2039. # end of 'src/raytrace.c'
  2040. fi
  2041. echo shar: End of archive 6 \(of 8\).
  2042. cp /dev/null ark6isdone
  2043. MISSING=""
  2044. for I in 1 2 3 4 5 6 7 8 ; do
  2045.     if test ! -f ark${I}isdone ; then
  2046.     MISSING="${MISSING} ${I}"
  2047.     fi
  2048. done
  2049. if test "${MISSING}" = "" ; then
  2050.     echo You have unpacked all 8 archives.
  2051.     rm -f ark[1-9]isdone
  2052. else
  2053.     echo You still need to unpack the following archives:
  2054.     echo "        " ${MISSING}
  2055. fi
  2056. ##  End of shell archive.
  2057. exit 0
  2058.  
  2059.  
  2060.