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

  1. Newsgroups: comp.sources.misc
  2. From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  3. Subject:  v21i014:  rayshade - A raytracing package for UNIX, Part11/19
  4. Message-ID: <1991Jul21.033720.29170@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: b8ad240ecf5d0fee5bec675087c3931a
  6. Date: Sun, 21 Jul 1991 03:37:20 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 14
  11. Archive-name: rayshade/part11
  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 11 (of 19)."
  21. # Contents:  libray/liblight/shadow.c libray/libobj/poly.c
  22. #   libray/libtext/noise.c libshade/picture.c libshade/viewing.c
  23. #   raypaint/xgraphics.c
  24. # Wrapped by kolb@woody on Wed Jul 17 17:56:50 1991
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'libray/liblight/shadow.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'libray/liblight/shadow.c'\"
  28. else
  29. echo shar: Extracting \"'libray/liblight/shadow.c'\" \(7457 characters\)
  30. sed "s/^X//" >'libray/liblight/shadow.c' <<'END_OF_FILE'
  31. X/*
  32. X * shadow.c
  33. X *
  34. X * Copyright (C) 1989, 1991, Craig E. Kolb
  35. X * All rights reserved.
  36. X *
  37. X * This software may be freely copied, modified, and redistributed
  38. X * provided that this copyright notice is preserved on all copies.
  39. X *
  40. X * You may not distribute this software, in whole or in part, as part of
  41. X * any commercial product without the express consent of the authors.
  42. X *
  43. X * There is no warranty or other guarantee of fitness of this software
  44. X * for any purpose.  It is provided solely "as is".
  45. X *
  46. X * $Id: shadow.c,v 4.0 91/07/17 14:35:34 kolb Exp Locker: kolb $
  47. X *
  48. X * $Log:    shadow.c,v $
  49. X * Revision 4.0  91/07/17  14:35:34  kolb
  50. X * Initial version.
  51. X * 
  52. X */
  53. X#include "libobj/geom.h"
  54. X#include "libsurf/surface.h"
  55. X#include "light.h"
  56. X
  57. X/*
  58. X * Shadow stats.
  59. X * External functions have read access via ShadowStats().
  60. X */
  61. Xstatic unsigned long    ShadowRays, ShadowHits, CacheMisses, CacheHits;
  62. X/*
  63. X * Options controlling how shadowing information is determined.
  64. X * Set by external modules via ShadowSetOptions().
  65. X */
  66. Xstatic long        ShadowOptions;
  67. X
  68. Xvoid LightCacheHit();
  69. X
  70. X/*
  71. X * Trace ray from point of intersection to a light.  If an intersection
  72. X * occurs at a distance less than "dist" (the distance to the
  73. X * light source), then the point is in shadow, and TRUE is returned.
  74. X * Otherwise, the brightness/color of the light is computed ('result'),
  75. X * and FALSE is returned.
  76. X */
  77. Xint
  78. XShadowed(result, color, cache, ray, dist, noshadow)
  79. XColor *result, *color;    /* resultant intensity, light color */
  80. XShadowCache *cache;    /* shadow cache for light */
  81. XRay *ray;        /* ray, origin on surface, dir towards light */
  82. XFloat dist;        /* distance from pos to light source */
  83. Xint noshadow;        /* If TRUE, no shadow ray is cast. */
  84. X{
  85. X    int i, smooth, enter;
  86. X    HitList hitlist;
  87. X    Ray tmpray;
  88. X    ShadowCache *cp;
  89. X    Vector hitpos, norm, gnorm;
  90. X    Surface surf, *sptr, *prevsurf;
  91. X    Float s, totaldist, statten;
  92. X    Color res;
  93. X
  94. X    if (noshadow || NOSHADOWS(ShadowOptions)) {
  95. X        *result = *color;
  96. X        return FALSE;
  97. X    }
  98. X
  99. X    ShadowRays++;
  100. X    s = dist;
  101. X    cp = &cache[ray->depth];
  102. X    /*
  103. X     * Check shadow cache.  SHADOWCACHE() is implied.
  104. X     */
  105. X    if (cp->obj) {
  106. X        /*
  107. X         * Transform ray to the space of the cached primitive.
  108. X         */
  109. X        tmpray = *ray;
  110. X        if (cp->dotrans)
  111. X            s *= RayTransform(&tmpray, &cp->trans);
  112. X        /*
  113. X         * s = distance to light source in 'primitive space'.
  114. X         * Intersect ray with cached object.
  115. X         */
  116. X        if (cp->obj->animtrans) {
  117. X            /*
  118. X             * Geom has animated transformation --
  119. X             * call intersect so that the transformation
  120. X             * is resolved properly.
  121. X             */
  122. X            if (intersect(cp->obj, &tmpray, &hitlist,
  123. X                SHADOW_EPSILON, &s)) {
  124. X                CacheHits++;
  125. X                return TRUE;
  126. X            }
  127. X        } else if (IsAggregate(cp->obj)) {
  128. X            if ((*cp->obj->methods->intersect)(cp->obj->obj,
  129. X                &tmpray, &hitlist, SHADOW_EPSILON, &s)) {
  130. X                CacheHits++;
  131. X                return TRUE;
  132. X            }
  133. X        } else if ((*cp->obj->methods->intersect)(cp->obj->obj,
  134. X                    &tmpray, SHADOW_EPSILON, &s)) {
  135. X            /* Hit cached object. */
  136. X            CacheHits++;
  137. X            return TRUE;
  138. X        }
  139. X        /*
  140. X         * Did not hit anything -- zero out the cache.
  141. X         */
  142. X        CacheMisses++;
  143. X        /*
  144. X         * Transformed -- reset s for use below.
  145. X         */
  146. X        s = dist;
  147. X        cp->obj = (Geom *)NULL;
  148. X        cp->dotrans = FALSE;
  149. X    }
  150. X
  151. X    hitlist.nodes = 0;
  152. X    if (!TraceRay(ray, &hitlist, SHADOW_EPSILON, &s)) {
  153. X        /* Shadow ray didn't hit anything. */
  154. X        *result = *color;
  155. X        return FALSE;
  156. X    }
  157. X
  158. X    /*
  159. X     * Otherwise, we've hit something.
  160. X     */
  161. X    ShadowHits++;
  162. X
  163. X    /*
  164. X     * If we're not worrying about transparent objects...
  165. X     * This is ugly due to the fact that we have to find
  166. X     * the surface associated with the object that was hit.
  167. X     * GetShadingSurf() will always return a non-null value.
  168. X     *
  169. X     * ***NOTE**
  170. X     * The transparency of the surface is checked below without
  171. X     * applying textures, if any, to it.  This means that if
  172. X     * an object may be made trasparent by a texture, its
  173. X     * surface should have non-zero transparency *before* texturing
  174. X     * as well.
  175. X     */
  176. X    if (!SHADOWTRANSP(ShadowOptions)) {
  177. X        if (SHADOWCACHE(ShadowOptions))
  178. X            LightCacheHit(&hitlist, cp);
  179. X        return TRUE;
  180. X    }
  181. X
  182. X    /*
  183. X     * We've hit a transparent object.  Attenuate the color of the light
  184. X     * source and continue the ray until we hit background or a
  185. X     * non-transparent object.  Note that this is incorrect if DefIndex or
  186. X     * any of the indices of refraction of the surfaces differ.
  187. X     */
  188. X
  189. X    totaldist = 0.;
  190. X    prevsurf = (Surface *)NULL;
  191. X    res = *color;
  192. X
  193. X    do {
  194. X        /*
  195. X         * Get a pointer to the surface to be used
  196. X         * for shading...
  197. X         */
  198. X        sptr = GetShadingSurf(&hitlist);
  199. X        if (sptr->transp < EPSILON) {
  200. X            if (SHADOWCACHE(ShadowOptions))
  201. X                LightCacheHit(&hitlist, cp);
  202. X            return TRUE;
  203. X        }
  204. X        /*
  205. X         * Take specular transmission attenuation from
  206. X         * previous intersection into account.
  207. X         */
  208. X        if (prevsurf) {
  209. X            if (prevsurf->statten != 1.) {
  210. X                statten = pow(prevsurf->statten, s - totaldist);
  211. X                ColorScale(statten, res, &res);
  212. X            }
  213. X        }
  214. X        /*
  215. X         * Perform texturing and the like in case surface
  216. X         * transparency is modulated.
  217. X         */
  218. X        /* copy the surface to be used... */
  219. X        surf = *sptr;
  220. X        enter = ComputeSurfProps(&hitlist, ray, &hitpos,
  221. X            &norm, &gnorm, &surf, &smooth);
  222. X        if (enter)
  223. X            prevsurf = &surf;
  224. X        else
  225. X            prevsurf = (Surface *)NULL;
  226. X        /*
  227. X         * Attenuate light source by body color of surface.
  228. X         */
  229. X        ColorScale(surf.transp, res, &res);
  230. X        ColorMultiply(res, surf.body, &res);
  231. X        /*
  232. X         * Return if attenuation becomes large.
  233. X         * In this case, the light was attenuated to nothing,
  234. X         * so we can't cache anything...
  235. X         */
  236. X        if (res.r < EPSILON && res.g < EPSILON && res.b < EPSILON)
  237. X            return TRUE;
  238. X        /*
  239. X         * Min distance is previous max.
  240. X         */
  241. X        totaldist = s + EPSILON;
  242. X        /*
  243. X         * Max distance is dist to light source
  244. X         */
  245. X        s = dist;
  246. X        /*
  247. X         * Trace ray starting at new origin and in the
  248. X         * same direction.
  249. X         */
  250. X        hitlist.nodes = 0;
  251. X    } while (TraceRay(ray, &hitlist, totaldist, &s));
  252. X
  253. X    *result = res;
  254. X    return FALSE;
  255. X}
  256. X
  257. Xvoid
  258. XShadowStats(shadowrays, shadowhit, cachehit, cachemiss)
  259. Xunsigned long *shadowrays, *shadowhit, *cachehit, *cachemiss;
  260. X{
  261. X    *shadowrays = ShadowRays;
  262. X    *shadowhit = ShadowHits;
  263. X    *cachehit = CacheHits;
  264. X    *cachemiss = CacheMisses;
  265. X}
  266. X
  267. Xvoid
  268. XShadowSetOptions(options)
  269. X{
  270. X    ShadowOptions = options;
  271. X}
  272. X
  273. Xvoid
  274. XLightCacheHit(hitlist, cache)
  275. XHitList *hitlist;
  276. XShadowCache *cache;
  277. X{
  278. X    HitNode *np;
  279. X    int i, n;
  280. X    extern int ShadowOptions;
  281. X
  282. X    i = 0;
  283. X
  284. X    if (SHADOWCSG(ShadowOptions)) {
  285. X        /*
  286. X         * There's possibly a CSG object in the
  287. X         * hitlist, so we can't simply cache the
  288. X         * primitive that was hit.  Find the
  289. X         * object lowest in hit that's not part
  290. X         * of a CSG object, and cache it.
  291. X         */
  292. X        i = FirstCSGGeom(hitlist);
  293. X    }
  294. X
  295. X    if (SHADOWBLUR(ShadowOptions)) {
  296. X        /*
  297. X         * Something might be animated --
  298. X         * gotta cache the puppy.
  299. X         */
  300. X        n = FirstAnimatedGeom(hitlist);
  301. X        if (n > i)
  302. X            i = n;
  303. X    }
  304. X
  305. X    /*
  306. X     * Compute total world-->cached object
  307. X     * transformation and store in cache->trans.
  308. X     */
  309. X    /*
  310. X     * Find the first transformation...
  311. X     */
  312. X    np = &hitlist->data[i];
  313. X    cache->obj = np->obj;
  314. X    /*
  315. X     * If the cached object is animated, then we don't
  316. X     * want to include the object's transformation(s)
  317. X     * in cache->trans (it's taken care of in shadowed()
  318. X     * by calling intersect).
  319. X     */
  320. X    if (cache->obj->animtrans) {
  321. X        i++;
  322. X        np++;
  323. X    }
  324. X    cache->dotrans = FALSE;
  325. X    while (i < hitlist->nodes -1) {
  326. X        if (np->obj->trans) {
  327. X            if (cache->dotrans) {
  328. X                MatrixMult(
  329. X                    &np->obj->trans->itrans,
  330. X                    &cache->trans,
  331. X                    &cache->trans);
  332. X            } else {
  333. X                MatrixCopy(
  334. X                    &np->obj->trans->itrans,
  335. X                    &cache->trans);
  336. X                cache->dotrans = TRUE;
  337. X            }
  338. X        }
  339. X        i++;
  340. X        np++;
  341. X    }
  342. X}
  343. END_OF_FILE
  344. if test 7457 -ne `wc -c <'libray/liblight/shadow.c'`; then
  345.     echo shar: \"'libray/liblight/shadow.c'\" unpacked with wrong size!
  346. fi
  347. # end of 'libray/liblight/shadow.c'
  348. fi
  349. if test -f 'libray/libobj/poly.c' -a "${1}" != "-c" ; then 
  350.   echo shar: Will not clobber existing file \"'libray/libobj/poly.c'\"
  351. else
  352. echo shar: Extracting \"'libray/libobj/poly.c'\" \(7872 characters\)
  353. sed "s/^X//" >'libray/libobj/poly.c' <<'END_OF_FILE'
  354. X/*
  355. X * poly.c
  356. X *
  357. X * Copyright (C) 1989, 1991, Craig E. Kolb
  358. X * All rights reserved.
  359. X *
  360. X * This software may be freely copied, modified, and redistributed
  361. X * provided that this copyright notice is preserved on all copies.
  362. X *
  363. X * You may not distribute this software, in whole or in part, as part of
  364. X * any commercial product without the express consent of the authors.
  365. X *
  366. X * There is no warranty or other guarantee of fitness of this software
  367. X * for any purpose.  It is provided solely "as is".
  368. X *
  369. X * $Id: poly.c,v 4.0 91/07/17 14:39:00 kolb Exp Locker: kolb $
  370. X *
  371. X * $Log:    poly.c,v $
  372. X * Revision 4.0  91/07/17  14:39:00  kolb
  373. X * Initial version.
  374. X * 
  375. X */
  376. X#include "geom.h"
  377. X#include "poly.h"
  378. X
  379. Xstatic Methods *iPolygonMethods = NULL;
  380. Xstatic char polyName[] = "polygon";
  381. X
  382. Xunsigned long PolyTests, PolyHits;
  383. X
  384. X/*
  385. X * Create a reference to a polygon with vertices equal to those
  386. X * on the linked-list "plist."
  387. X */
  388. XPolygon *
  389. XPolygonCreate(plist, npoints, flipflag)
  390. XPointList *plist;
  391. Xint npoints, flipflag;
  392. X{
  393. X    Polygon *poly;
  394. X    Float indexval;
  395. X    Vector *prev, *cur, anorm;
  396. X    PointList *curp, *pltmp;
  397. X    int i;
  398. X
  399. X    poly = (Polygon *)share_malloc(sizeof(Polygon));
  400. X    /*
  401. X     * Allocate space for the vertices.
  402. X     */
  403. X    poly->points = (Vector *)Malloc((unsigned)(npoints*sizeof(Vector)));
  404. X    poly->npoints = npoints;
  405. X
  406. X    /*
  407. X     * Copy the vertices from the linked list to the array, freeing
  408. X     * the linked list as we go so that the caller doesn't have
  409. X     * to worry about doing so.
  410. X     */
  411. X    i = npoints -1;
  412. X    for(curp = plist; curp != (PointList *)0; curp = pltmp) {
  413. X        poly->points[i--] = curp->vec;
  414. X        pltmp = curp->next;
  415. X        free((voidstar)curp);
  416. X    }
  417. X
  418. X    /*
  419. X     * Find normal to polygon.
  420. X     */
  421. X    poly->norm.x = poly->norm.y = poly->norm.z = 0.;
  422. X    prev = &poly->points[poly->npoints -1];
  423. X    for(i = 0,cur = poly->points;i < poly->npoints;i++, prev = cur, cur++) {
  424. X        poly->norm.x += (prev->y - cur->y) * (prev->z + cur->z);
  425. X        poly->norm.y += (prev->z - cur->z) * (prev->x + cur->x);
  426. X        poly->norm.z += (prev->x - cur->x) * (prev->y + cur->y);
  427. X    }
  428. X
  429. X    if (VecNormalize(&poly->norm) == 0.) {
  430. X        /*
  431. X         * Degenerate normal --> degenerate polygon
  432. X         */
  433. X        RLerror(RL_WARN, "Degenerate polygon.\n");
  434. X        free((voidstar)poly->points);
  435. X        return (Polygon *)NULL;
  436. X    }
  437. X
  438. X    /*
  439. X     * If filflag is true, flip the normal.
  440. X     */
  441. X    if (flipflag)
  442. X        VecScale(-1, poly->norm, &poly->norm);
  443. X
  444. X    /*
  445. X     * Compute and store the plane constant.
  446. X     */
  447. X    poly->d = dotp(&poly->norm, &poly->points[0]);
  448. X
  449. X    /*
  450. X     * Find the "dominant" part of the normal vector.  This
  451. X     * is used to turn the point-in-polygon test into a 2D problem.
  452. X     */
  453. X    anorm.x = fabs(poly->norm.x);
  454. X    anorm.y = fabs(poly->norm.y);
  455. X    anorm.z = fabs(poly->norm.z);
  456. X    indexval = max(anorm.y, anorm.z);
  457. X    indexval = max(anorm.x, indexval);
  458. X
  459. X    if (indexval == anorm.x)
  460. X        poly->index = XNORMAL;
  461. X    else if (indexval == anorm.y)
  462. X        poly->index = YNORMAL;
  463. X    else
  464. X        poly->index = ZNORMAL;
  465. X
  466. X    return poly;
  467. X}
  468. X
  469. XMethods *
  470. XPolygonMethods()
  471. X{
  472. X    if (iPolygonMethods == (Methods *)NULL) {
  473. X        iPolygonMethods = MethodsCreate();
  474. X        iPolygonMethods->create = (GeomCreateFunc *)PolygonCreate;
  475. X        iPolygonMethods->methods = PolygonMethods;
  476. X        iPolygonMethods->name = PolygonName;
  477. X        iPolygonMethods->intersect = PolygonIntersect;
  478. X        iPolygonMethods->normal = PolygonNormal;
  479. X        iPolygonMethods->uv = PolygonUV;
  480. X        iPolygonMethods->bounds = PolygonBounds;
  481. X        iPolygonMethods->stats = PolygonStats;
  482. X        iPolygonMethods->checkbounds = TRUE;
  483. X        iPolygonMethods->closed = FALSE;
  484. X    }
  485. X    return iPolygonMethods;
  486. X}
  487. X
  488. X/*
  489. X * Quadrants are defined as:
  490. X *        |
  491. X *   1    |   0
  492. X *        |
  493. X * -------c--------
  494. X *        |
  495. X *   2    |   3
  496. X *        |
  497. X */
  498. X#define quadrant(p, c) ((p.u<c.u) ? ((p.v<c.v) ? 2 : 1) : ((p.v<c.v) ? 3 : 0))
  499. X
  500. X/*
  501. X * Perform ray-polygon intersection test.
  502. X */
  503. Xint
  504. XPolygonIntersect(poly, ray, mindist, maxdist)
  505. XPolygon *poly;
  506. XRay *ray;
  507. XFloat mindist, *maxdist;
  508. X{
  509. X    register int winding, i;
  510. X    Vector dir, pos;
  511. X    int quad, lastquad;
  512. X    Float dist, left, right;
  513. X    Vec2d center, cur, last;
  514. X
  515. X    PolyTests++;
  516. X    pos = ray->pos;
  517. X    dir = ray->dir;
  518. X    /*
  519. X     * First, find where ray hits polygon plane, projecting
  520. X     * along the polygon's dominant normal component.
  521. X     */
  522. X
  523. X    dist = dotp(&poly->norm, &dir);
  524. X    if(fabs(dist) < EPSILON)
  525. X        /*
  526. X          * No intersection with polygon plane.
  527. X         */
  528. X        return FALSE;
  529. X
  530. X    dist = (poly->d - dotp(&poly->norm, &pos)) / dist;
  531. X    if(dist < mindist || dist > *maxdist)
  532. X        /*
  533. X         * Intersection point behind origin or too far.
  534. X         */
  535. X        return FALSE;
  536. X
  537. X    /*
  538. X     * Compute the point of intersection, projected appropriately.
  539. X     */
  540. X    if(poly->index == XNORMAL) {
  541. X        center.u = pos.y + dist * dir.y;
  542. X        center.v = pos.z + dist * dir.z;
  543. X    } else if(poly->index == YNORMAL) {
  544. X        center.v = pos.z + dist * dir.z;
  545. X        center.u = pos.x + dist * dir.x;
  546. X    } else  {
  547. X        center.u = pos.x + dist * dir.x;
  548. X        center.v = pos.y + dist * dir.y;
  549. X    }    
  550. X
  551. X    /*
  552. X     * Is the point inside the polygon?
  553. X     *
  554. X     * Compute the winding number by finding the quadrant each
  555. X     * polygon point lies in with respect to the the point in
  556. X     * question, and computing a "delta" (winding number).  If we
  557. X     * end up going around in a complete circle around
  558. X     * the point (winding number is non-zero at the end), then
  559. X     * we're inside.  Otherwise, the point is outside.
  560. X     *
  561. X     * Note that we can turn this into a 2D problem by projecting
  562. X     * all the points along the axis defined by poly->index,
  563. X     * the "dominant" part of the polygon's normal vector.
  564. X     */
  565. X    winding = 0;
  566. X    VecProject(last, poly->points[poly->npoints -1], poly->index);
  567. X    lastquad = quadrant(last, center);
  568. X    for(i = 0; i < poly->npoints; i++, last = cur) {
  569. X        VecProject(cur, poly->points[i], poly->index);
  570. X        quad = quadrant(cur, center);
  571. X        if (quad == lastquad)
  572. X            continue;
  573. X        if(((lastquad + 1) & 3) == quad)
  574. X            winding++;
  575. X        else if(((quad + 1) & 3) == lastquad)
  576. X            winding--;
  577. X        else {
  578. X            /*
  579. X             * Find where edge crosses
  580. X             * center's X axis.
  581. X             */
  582. X            right = last.u - cur.u;
  583. X            left = (last.v - cur.v) * (center.u - last.u);
  584. X            if(left + last.v * right > right * center.v)
  585. X                winding += 2;
  586. X            else
  587. X                winding -= 2;
  588. X        }
  589. X        lastquad = quad;
  590. X    }
  591. X
  592. X    if (winding != 0) {
  593. X        *maxdist = dist;
  594. X        PolyHits++;
  595. X        return TRUE;
  596. X    }
  597. X    return FALSE;
  598. X}
  599. X
  600. X/*
  601. X * Return the normal to the polygon surface.
  602. X */
  603. X/*ARGSUSED*/
  604. Xint
  605. XPolygonNormal(poly, pos, nrm, gnrm)
  606. XPolygon *poly;
  607. XVector *pos, *nrm, *gnrm;
  608. X{
  609. X    *gnrm = *nrm = poly->norm;
  610. X    return FALSE;
  611. X}
  612. X
  613. X/*ARGSUSED*/
  614. Xvoid
  615. XPolygonUV(poly, pos, norm, uv, dpdu, dpdv)
  616. XPolygon *poly;
  617. XVector *pos, *norm, *dpdu, *dpdv;
  618. XVec2d *uv;
  619. X{
  620. X    /*
  621. X     * Since there's no nice way to do this, we wimp out and
  622. X     * do the following...
  623. X     *
  624. X     * Of course, we could force the user to specify U and V
  625. X     * axes, but forcing them to use X and Y as U and V is
  626. X     * just as arbitrary and much simpler to deal with.
  627. X     */
  628. X    uv->u = pos->x;
  629. X    uv->v = pos->y;
  630. X    if (dpdu) {
  631. X        dpdu->x = 1.;
  632. X        dpdu->y = dpdu->z = 0.;
  633. X        dpdv->x = dpdv->z = 0.;
  634. X        dpdv->y = 1.;
  635. X    }
  636. X}
  637. X
  638. X/*
  639. X * Compute the extent of a polygon
  640. X */
  641. Xvoid
  642. XPolygonBounds(poly, bounds)
  643. XPolygon *poly;
  644. XFloat bounds[2][3];
  645. X{
  646. X    register int i;
  647. X
  648. X    bounds[LOW][X] = bounds[HIGH][X] = poly->points[0].x;
  649. X    bounds[LOW][Y] = bounds[HIGH][Y] = poly->points[0].y;
  650. X    bounds[LOW][Z] = bounds[HIGH][Z] = poly->points[0].z;
  651. X
  652. X    for (i = 1 ;i < poly->npoints; i++) {
  653. X        if (poly->points[i].x < bounds[LOW][X])
  654. X            bounds[LOW][X] = poly->points[i].x;
  655. X        if (poly->points[i].x > bounds[HIGH][X])
  656. X            bounds[HIGH][X] = poly->points[i].x;
  657. X        if (poly->points[i].y < bounds[LOW][Y])
  658. X            bounds[LOW][Y] = poly->points[i].y;
  659. X        if (poly->points[i].y > bounds[HIGH][Y])
  660. X            bounds[HIGH][Y] = poly->points[i].y;
  661. X        if (poly->points[i].z < bounds[LOW][Z])
  662. X            bounds[LOW][Z] = poly->points[i].z;
  663. X        if (poly->points[i].z > bounds[HIGH][Z])
  664. X            bounds[HIGH][Z] = poly->points[i].z;
  665. X    }
  666. X}
  667. X
  668. Xchar *
  669. XPolygonName()
  670. X{
  671. X    return polyName;
  672. X}
  673. X
  674. Xvoid
  675. XPolygonStats(tests, hits)
  676. Xunsigned long *tests, *hits;
  677. X{
  678. X    *tests = PolyTests;
  679. X    *hits = PolyHits;
  680. X}
  681. X
  682. Xvoid
  683. XPolygonMethodRegister(meth)
  684. XUserMethodType meth;
  685. X{
  686. X    if (iPolygonMethods)
  687. X        iPolygonMethods->user = meth;
  688. X}
  689. END_OF_FILE
  690. if test 7872 -ne `wc -c <'libray/libobj/poly.c'`; then
  691.     echo shar: \"'libray/libobj/poly.c'\" unpacked with wrong size!
  692. fi
  693. # end of 'libray/libobj/poly.c'
  694. fi
  695. if test -f 'libray/libtext/noise.c' -a "${1}" != "-c" ; then 
  696.   echo shar: Will not clobber existing file \"'libray/libtext/noise.c'\"
  697. else
  698. echo shar: Extracting \"'libray/libtext/noise.c'\" \(7883 characters\)
  699. sed "s/^X//" >'libray/libtext/noise.c' <<'END_OF_FILE'
  700. X/*
  701. X * noise.c
  702. X *
  703. X * Copyright (C) 1989, 1991, Robert Skinner, Craig E. Kolb
  704. X * All rights reserved.
  705. X *
  706. X * This software may be freely copied, modified, and redistributed
  707. X * provided that this copyright notice is preserved on all copies.
  708. X *
  709. X * You may not distribute this software, in whole or in part, as part of
  710. X * any commercial product without the express consent of the authors.
  711. X *
  712. X * There is no warranty or other guarantee of fitness of this software
  713. X * for any purpose.  It is provided solely "as is".
  714. X *
  715. X * $Id: noise.c,v 4.0 91/07/17 14:43:38 kolb Exp Locker: kolb $
  716. X *
  717. X * $Log:    noise.c,v $
  718. X * Revision 4.0  91/07/17  14:43:38  kolb
  719. X * Initial version.
  720. X * 
  721. X */
  722. X#include "libcommon/common.h"
  723. X
  724. X#define MINX        -1000000
  725. X#define MINY        MINX
  726. X#define MINZ        MINX
  727. X
  728. X#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
  729. X#define REALSCALE ( 2.0 / 65536.0 )
  730. X#define NREALSCALE ( 2.0 / 4096.0 )
  731. X#define Hash3d(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
  732. X#define Hash(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
  733. X
  734. X#define INCRSUM(m,s,x,y,z)    ((s)*(RTable[m]*0.5        \
  735. X                    + RTable[m+1]*(x)    \
  736. X                    + RTable[m+2]*(y)    \
  737. X                    + RTable[m+3]*(z)))    \
  738. X
  739. X
  740. X#define MAXSIZE 267
  741. X
  742. XFloat        RTable[MAXSIZE];
  743. Xstatic short    *hashTable;
  744. Xstatic int    R(), Crc16();
  745. X
  746. Xstatic unsigned short xtab[256] =
  747. X{
  748. X   0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  749. X   0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  750. X   0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  751. X   0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  752. X   0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  753. X   0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  754. X   0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  755. X   0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  756. X   0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  757. X   0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  758. X   0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  759. X   0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  760. X   0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  761. X   0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  762. X   0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  763. X   0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  764. X   0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  765. X   0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  766. X   0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  767. X   0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  768. X   0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  769. X   0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  770. X   0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  771. X   0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  772. X   0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  773. X   0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  774. X   0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  775. X   0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  776. X   0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  777. X   0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  778. X   0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  779. X   0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  780. X};
  781. X
  782. XFloat Chaos(), Marble();
  783. X
  784. Xvoid
  785. XInitTextureTable()
  786. X{
  787. X    int i, j, temp;
  788. X
  789. X    seednrand(1);
  790. X    hashTable = (short *) Malloc(4096*sizeof(short int));
  791. X    for (i = 0; i < 4096; i++)
  792. X        hashTable[i] = i;
  793. X    for (i = 4095; i > 0; i--) {
  794. X        j = (int)(nrand() * 4096);
  795. X        temp = hashTable[i];
  796. X        hashTable[i] = hashTable[j];
  797. X        hashTable[j] = temp;
  798. X    }
  799. X}
  800. X
  801. Xvoid
  802. XNoiseInit()
  803. X{
  804. X    int i;
  805. X    Vector rp;
  806. X
  807. X    InitTextureTable();
  808. X
  809. X    for (i = 0; i < MAXSIZE; i++) {
  810. X           rp.x = rp.y = rp.z = (Float)i;
  811. X           RTable[i] = R(&rp)*REALSCALE - 1.0;
  812. X     }
  813. X}
  814. X
  815. Xstatic int
  816. XR(v)
  817. XVector *v;
  818. X{
  819. X    v->x *= .12345;
  820. X    v->y *= .12345;
  821. X    v->z *= .12345;
  822. X
  823. X    return Crc16(v, sizeof(Vector));
  824. X}
  825. X
  826. X/*
  827. X * Note that passing a Float to Crc16 and interpreting it as
  828. X * an array of chars means that machines with different floating-point
  829. X * representation schemes will evaluate Noise(point) differently.
  830. X */
  831. Xstatic int
  832. XCrc16(buf, count)
  833. Xregister char *buf;
  834. Xregister int  count;
  835. X{
  836. X    register unsigned int crc = 0;
  837. X
  838. X    while (count--)
  839. X        crc = (crc >> 8) ^ xtab[ (unsigned char) (crc ^ *buf++) ];
  840. X
  841. X    return crc;
  842. X}
  843. X
  844. X
  845. X/*
  846. X * Robert Skinner's Perlin-style "Noise" function
  847. X */
  848. XFloat
  849. XNoise3(point)
  850. XVector *point;
  851. X{
  852. X    register int    ix, iy, iz, jx, jy, jz;
  853. X    Float        x, y, z;
  854. X    Float    sx, sy, sz, tx, ty, tz;
  855. X    Float    sum;
  856. X    short    m;
  857. X
  858. X
  859. X    /* ensures the values are positive. */
  860. X    x = point->x - MINX; y = point->y - MINY; z = point->z - MINZ;
  861. X
  862. X    /* its equivalent integer lattice point. */
  863. X    ix = (int)x; iy = (int)y; iz = (int)z;
  864. X    jx = ix+1; jy = iy + 1; jz = iz + 1;
  865. X
  866. X    sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
  867. X
  868. X    /* the complement values of sx,sy,sz */
  869. X    tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
  870. X
  871. X    /*
  872. X     *  interpolate!
  873. X     */
  874. X    m = Hash3d( ix, iy, iz ) & 0xFF;
  875. X    sum = INCRSUM(m,(tx*ty*tz),(x-ix),(y-iy),(z-iz));
  876. X
  877. X    m = Hash3d( jx, iy, iz ) & 0xFF;
  878. X    sum += INCRSUM(m,(sx*ty*tz),(x-jx),(y-iy),(z-iz));
  879. X
  880. X    m = Hash3d( ix, jy, iz ) & 0xFF;
  881. X    sum += INCRSUM(m,(tx*sy*tz),(x-ix),(y-jy),(z-iz));
  882. X
  883. X    m = Hash3d( jx, jy, iz ) & 0xFF;
  884. X    sum += INCRSUM(m,(sx*sy*tz),(x-jx),(y-jy),(z-iz));
  885. X
  886. X    m = Hash3d( ix, iy, jz ) & 0xFF;
  887. X    sum += INCRSUM(m,(tx*ty*sz),(x-ix),(y-iy),(z-jz));
  888. X
  889. X    m = Hash3d( jx, iy, jz ) & 0xFF;
  890. X    sum += INCRSUM(m,(sx*ty*sz),(x-jx),(y-iy),(z-jz));
  891. X
  892. X    m = Hash3d( ix, jy, jz ) & 0xFF;
  893. X    sum += INCRSUM(m,(tx*sy*sz),(x-ix),(y-jy),(z-jz));
  894. X
  895. X    m = Hash3d( jx, jy, jz ) & 0xFF;
  896. X    sum += INCRSUM(m,(sx*sy*sz),(x-jx),(y-jy),(z-jz));
  897. X
  898. X    return sum;
  899. X
  900. X}
  901. X
  902. X/*
  903. X * Vector-valued "Noise"
  904. X */
  905. Xvoid
  906. XDNoise3(point, result)
  907. XVector *point, *result;
  908. X{
  909. X    register int    ix, iy, iz, jx, jy, jz;
  910. X    Float        x, y, z;
  911. X    Float px, py, pz, s;
  912. X    Float    sx, sy, sz, tx, ty, tz;
  913. X    short    m;
  914. X
  915. X    /* ensures the values are positive. */
  916. X    x = point->x - MINX; y = point->y - MINY; z = point->z - MINZ;
  917. X
  918. X    /* its equivalent integer lattice point. */
  919. X    ix = (int)x; iy = (int)y; iz = (int)z;
  920. X    jx = ix+1; jy = iy + 1; jz = iz + 1;
  921. X
  922. X    sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
  923. X
  924. X    /* the complement values of sx,sy,sz */
  925. X    tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
  926. X
  927. X    /*
  928. X     *  interpolate!
  929. X     */
  930. X    m = Hash3d( ix, iy, iz ) & 0xFF;
  931. X    px = x-ix;  py = y-iy;  pz = z-iz;
  932. X    s = tx*ty*tz;
  933. X    result->x = INCRSUM(m,s,px,py,pz);
  934. X    result->y = INCRSUM(m+4,s,px,py,pz);
  935. X    result->z = INCRSUM(m+8,s,px,py,pz);
  936. X
  937. X    m = Hash3d( jx, iy, iz ) & 0xFF;
  938. X    px = x-jx;
  939. X    s = sx*ty*tz;
  940. X    result->x += INCRSUM(m,s,px,py,pz);
  941. X    result->y += INCRSUM(m+4,s,px,py,pz);
  942. X    result->z += INCRSUM(m+8,s,px,py,pz);
  943. X
  944. X    m = Hash3d( jx, jy, iz ) & 0xFF;
  945. X    py = y-jy;
  946. X    s = sx*sy*tz;
  947. X    result->x += INCRSUM(m,s,px,py,pz);
  948. X    result->y += INCRSUM(m+4,s,px,py,pz);
  949. X    result->z += INCRSUM(m+8,s,px,py,pz);
  950. X
  951. X    m = Hash3d( ix, jy, iz ) & 0xFF;
  952. X    px = x-ix;
  953. X    s = tx*sy*tz;
  954. X    result->x += INCRSUM(m,s,px,py,pz);
  955. X    result->y += INCRSUM(m+4,s,px,py,pz);
  956. X    result->z += INCRSUM(m+8,s,px,py,pz);
  957. X
  958. X    m = Hash3d( ix, jy, jz ) & 0xFF;
  959. X    pz = z-jz;
  960. X    s = tx*sy*sz;
  961. X    result->x += INCRSUM(m,s,px,py,pz);
  962. X    result->y += INCRSUM(m+4,s,px,py,pz);
  963. X    result->z += INCRSUM(m+8,s,px,py,pz);
  964. X
  965. X    m = Hash3d( jx, jy, jz ) & 0xFF;
  966. X    px = x-jx;
  967. X    s = sx*sy*sz;
  968. X    result->x += INCRSUM(m,s,px,py,pz);
  969. X    result->y += INCRSUM(m+4,s,px,py,pz);
  970. X    result->z += INCRSUM(m+8,s,px,py,pz);
  971. X
  972. X    m = Hash3d( jx, iy, jz ) & 0xFF;
  973. X    py = y-iy;
  974. X    s = sx*ty*sz;
  975. X    result->x += INCRSUM(m,s,px,py,pz);
  976. X    result->y += INCRSUM(m+4,s,px,py,pz);
  977. X    result->z += INCRSUM(m+8,s,px,py,pz);
  978. X
  979. X    m = Hash3d( ix, iy, jz ) & 0xFF;
  980. X    px = x-ix;
  981. X    s = tx*ty*sz;
  982. X    result->x += INCRSUM(m,s,px,py,pz);
  983. X    result->y += INCRSUM(m+4,s,px,py,pz);
  984. X    result->z += INCRSUM(m+8,s,px,py,pz);
  985. X}
  986. END_OF_FILE
  987. if test 7883 -ne `wc -c <'libray/libtext/noise.c'`; then
  988.     echo shar: \"'libray/libtext/noise.c'\" unpacked with wrong size!
  989. fi
  990. # end of 'libray/libtext/noise.c'
  991. fi
  992. if test -f 'libshade/picture.c' -a "${1}" != "-c" ; then 
  993.   echo shar: Will not clobber existing file \"'libshade/picture.c'\"
  994. else
  995. echo shar: Extracting \"'libshade/picture.c'\" \(7560 characters\)
  996. sed "s/^X//" >'libshade/picture.c' <<'END_OF_FILE'
  997. X/*
  998. X * picture.c
  999. X *
  1000. X * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
  1001. X * All rights reserved.
  1002. X *
  1003. X * This software may be freely copied, modified, and redistributed
  1004. X * provided that this copyright notice is preserved on all copies.
  1005. X *
  1006. X * You may not distribute this software, in whole or in part, as part of
  1007. X * any commercial product without the express consent of the authors.
  1008. X *
  1009. X * There is no warranty or other guarantee of fitness of this software
  1010. X * for any purpose.  It is provided solely "as is".
  1011. X *
  1012. X * $Id: picture.c,v 4.0 91/07/17 14:47:00 kolb Exp Locker: kolb $
  1013. X *
  1014. X * $Log:    picture.c,v $
  1015. X * Revision 4.0  91/07/17  14:47:00  kolb
  1016. X * Initial version.
  1017. X * 
  1018. X */
  1019. X#include "rayshade.h"
  1020. X#include "picture.h"
  1021. X#include "viewing.h"
  1022. X#include "options.h"
  1023. X#include "stats.h"
  1024. X
  1025. X#ifdef URT
  1026. Xunsigned char **outptr;        /* Output buffer */
  1027. Xstatic int count_rle_rows();
  1028. X#endif
  1029. X
  1030. X/*
  1031. X * Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
  1032. X * correction.
  1033. X */
  1034. Xunsigned char
  1035. Xcorrect(x)
  1036. XFloat x;
  1037. X{
  1038. X    /*
  1039. X     * Truncate values < 0 or > 1.
  1040. X     */
  1041. X    if (x < 0)
  1042. X        return 0;
  1043. X    if (x > 1.)
  1044. X        return 255;
  1045. X    return (unsigned char)(x * 255.);
  1046. X}
  1047. X
  1048. X#ifdef URT
  1049. X/*
  1050. X * Open image file and write RLE header.
  1051. X */
  1052. Xvoid
  1053. XPictureStart(argv)
  1054. Xchar **argv;
  1055. X{
  1056. X    char gammacom[40];
  1057. X
  1058. X    if (Options.framenum != Options.startframe) {
  1059. X        /*
  1060. X         * We've been here before;
  1061. X         * write a new header and return.
  1062. X         */
  1063. X        rle_put_setup(&rle_dflt_hdr);
  1064. X        return;
  1065. X    }
  1066. X    /*
  1067. X     * If Appending, then we know that outfile is valid, 'cause
  1068. X     * we've already read its header.
  1069. X     */
  1070. X    if (Options.appending) {
  1071. X        Options.pictfile = fopen(Options.imgname, "a");
  1072. X        if (Options.pictfile == (FILE *)0)
  1073. X            RLerror(RL_PANIC, "Cannot append to %s?!\n",
  1074. X                    Options.imgname);
  1075. X        rle_dflt_hdr.rle_file = Options.pictfile;
  1076. X        rle_put_init(&rle_dflt_hdr);
  1077. X    } else {
  1078. X        /*
  1079. X         * Starting image from scatch.
  1080. X         */
  1081. X        if (Options.imgname) {
  1082. X            Options.pictfile = fopen(Options.imgname, "w");
  1083. X            if (Options.pictfile == (FILE *)NULL)
  1084. X                RLerror(RL_PANIC,"Cannot open %s for writing.",
  1085. X                    Options.imgname);
  1086. X        } else
  1087. X            Options.pictfile = stdout;
  1088. X
  1089. X        rle_dflt_hdr.xmax = Screen.maxx;
  1090. X        rle_dflt_hdr.ymax = Screen.maxy;
  1091. X        rle_dflt_hdr.xmin = Screen.minx;
  1092. X        rle_dflt_hdr.ymin = Screen.miny;
  1093. X        rle_dflt_hdr.alpha = Options.alpha;
  1094. X        if (Options.alpha)
  1095. X            RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
  1096. X        if (Options.exp_output) {
  1097. X            RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
  1098. X            rle_dflt_hdr.ncolors = 4;
  1099. X            rle_putcom("exponential_data", &rle_dflt_hdr);
  1100. X        }
  1101. X        else
  1102. X            rle_dflt_hdr.ncolors = 3;
  1103. X        /*
  1104. X          * Document image gamma in RLE comment area.
  1105. X         * Options.gamma has been inverted.
  1106. X          */
  1107. X        (void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
  1108. X        rle_putcom(gammacom, &rle_dflt_hdr);
  1109. X        /*
  1110. X          * Document command line in RLE history.
  1111. X          */
  1112. X        rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
  1113. X        rle_dflt_hdr.rle_file = Options.pictfile;
  1114. X        rle_put_setup(&rle_dflt_hdr);
  1115. X        /*
  1116. X          * Flush the header.  If we don't, and LINDA forks off
  1117. X          * a bunch of workers, strange things will happen (they'll
  1118. X          * all flush the buffer when they die, and you end up with
  1119. X          * lots of headers at the end of the file).
  1120. X          */
  1121. X        (void)fflush(rle_dflt_hdr.rle_file);
  1122. X    }
  1123. X
  1124. X    if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
  1125. X        RLerror(RL_PANIC, "Unable to allocate image memory.\n");
  1126. X}
  1127. X
  1128. X/*
  1129. X * Read RLE header to which we are appending in order determine
  1130. X * old resolution, window location, and the like.
  1131. X */
  1132. Xvoid
  1133. XPictureSetWindow()
  1134. X{
  1135. X    if (Options.imgname == (char *)NULL)
  1136. X        RLerror(RL_PANIC,
  1137. X            "No partially-completed image file specified.\n");
  1138. X
  1139. X    /*
  1140. X     * Open image and read RLE header.
  1141. X     */
  1142. X    Options.pictfile = fopen(Options.imgname, "r");
  1143. X    rle_dflt_hdr.rle_file = Options.pictfile;
  1144. X    rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
  1145. X
  1146. X    /*
  1147. X     * If user specified a window that does not match what's in
  1148. X     * the header, complain.
  1149. X    if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
  1150. X        Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
  1151. X        Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
  1152. X        Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
  1153. X        RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
  1154. X            rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
  1155. X            rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
  1156. X     */
  1157. X    /*
  1158. X     * Set window.
  1159. X     */
  1160. X    Screen.minx = rle_dflt_hdr.xmin;
  1161. X    Screen.miny = rle_dflt_hdr.ymin;
  1162. X    Screen.maxx = rle_dflt_hdr.xmax;
  1163. X    Screen.maxy = rle_dflt_hdr.ymax;
  1164. X
  1165. X    /*
  1166. X     * Set alpha.  Warn the user if the alpha option doesn't reflect
  1167. X     * what's already been rendered.
  1168. X     */
  1169. X    if (Options.alpha != rle_dflt_hdr.alpha)
  1170. X        RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
  1171. X            Options.imgname,
  1172. X            rle_dflt_hdr.alpha ? "has" : "does not have");
  1173. X
  1174. X    Options.alpha = rle_dflt_hdr.alpha;
  1175. X
  1176. X    /*
  1177. X     * Determine number of scanlines written to file.
  1178. X     */
  1179. X    Screen.miny += count_rle_rows(&rle_dflt_hdr);
  1180. X    if (Screen.miny >= Screen.maxy) {
  1181. X        fprintf(stderr, "\"%s\" is a complete image.\n",
  1182. X            Options.imgname);
  1183. X        exit(0);
  1184. X    }
  1185. X    fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
  1186. X        Options.imgname, Screen.miny);
  1187. X    (void)fclose(Options.pictfile);
  1188. X}
  1189. X
  1190. Xstatic int
  1191. Xcount_rle_rows( hdr )
  1192. Xrle_hdr *hdr;
  1193. X{
  1194. X    rle_op **raw;
  1195. X    int **nraw, y, ynext;
  1196. X
  1197. X    if (rle_raw_alloc( hdr, &raw, &nraw ) < 0)  {
  1198. X        RLerror(RL_PANIC,
  1199. X            "Unable to allocate memory in count_rle_rows.\n");
  1200. X    }
  1201. X
  1202. X    y = hdr->ymin;
  1203. X    while ((ynext = rle_getraw( hdr, raw, nraw )) != 32768) {
  1204. X        y = ynext+1;
  1205. X        rle_freeraw( hdr, raw, nraw );
  1206. X    }
  1207. X
  1208. X    /* Free memory. */
  1209. X    rle_raw_free( hdr, raw, nraw );
  1210. X
  1211. X    return y - hdr->ymin;
  1212. X}
  1213. X
  1214. X/*
  1215. X * Write a scanline of output.
  1216. X * "buf" is an array of Color structures of size Screen.xsize.  Each color
  1217. X * component is normalized to [0, 1.].
  1218. X */
  1219. Xvoid
  1220. XPictureWriteLine(buf)
  1221. XPixel *buf;
  1222. X{
  1223. X    register int i, chan;
  1224. X    float floats[3];
  1225. X    rle_pixel pixels[4];
  1226. X
  1227. X    for(i = 0; i < Screen.xsize; i++) {
  1228. X        if (!Options.exp_output) {
  1229. X            /*
  1230. X             * Scale colors to fit unsigned char and check for
  1231. X             * over/underflow.
  1232. X             */
  1233. X            outptr[0][i] = CORRECT(buf[i].r);
  1234. X            outptr[1][i] = CORRECT(buf[i].g);
  1235. X            outptr[2][i] = CORRECT(buf[i].b);
  1236. X        } else {
  1237. X            /*
  1238. X             * Convert 3 floats to 4 unsigned chars for
  1239. X             * 'exponential_data' RLE file.
  1240. X             */
  1241. X            floats[0] = GAMMACORRECT(buf[i].r);
  1242. X            floats[1] = GAMMACORRECT(buf[i].g);
  1243. X            floats[2] = GAMMACORRECT(buf[i].b);
  1244. X            float_to_exp( 3, floats, pixels );
  1245. X            for (chan = 0; chan <= 3; chan++)
  1246. X                outptr[chan][i] = pixels[chan];
  1247. X        }
  1248. X        if (Options.alpha)
  1249. X            /*
  1250. X             * Don't gamma correct alpha channel.
  1251. X             */
  1252. X            outptr[-1][i] = correct(buf[i].alpha);
  1253. X    }
  1254. X    rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
  1255. X}
  1256. X
  1257. X/*
  1258. X * End the frame.
  1259. X */
  1260. Xvoid
  1261. XPictureFrameEnd()
  1262. X{
  1263. X    rle_puteof(&rle_dflt_hdr);
  1264. X}
  1265. X
  1266. X/*
  1267. X * Close image file.
  1268. X */
  1269. Xvoid
  1270. XPictureEnd()
  1271. X{
  1272. X    (void)fclose(Options.pictfile);
  1273. X}
  1274. X
  1275. X#else /* !URT */
  1276. Xvoid
  1277. XPictureStart(argv)
  1278. Xchar **argv;
  1279. X{
  1280. X    if (Options.imgname) {
  1281. X        Options.pictfile = fopen(Options.imgname, "w");
  1282. X        if (Options.pictfile == (FILE *)NULL)
  1283. X            RLerror(RL_PANIC, "Cannot open %s for writing.",
  1284. X                Options.imgname);
  1285. X    } else
  1286. X        Options.pictfile = stdout;
  1287. X
  1288. X    fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
  1289. X
  1290. X    (void)fflush(Options.pictfile);
  1291. X}
  1292. X
  1293. Xvoid
  1294. XPictureWriteLine(buf)
  1295. XPixel *buf;
  1296. X{
  1297. X    register int i;
  1298. X
  1299. X    for (i = 0; i < Screen.xsize; i++) {
  1300. X        (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
  1301. X        (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
  1302. X        (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
  1303. X    }
  1304. X    (void)fflush(Options.pictfile);
  1305. X}
  1306. X
  1307. Xvoid
  1308. XPictureFrameEnd()
  1309. X{
  1310. X    /*
  1311. X     * Don't do anything -- generic format has no end-of-image marker.
  1312. X     */
  1313. X}
  1314. X
  1315. Xvoid
  1316. XPictureEnd()
  1317. X{
  1318. X    (void)fclose(Options.pictfile);
  1319. X}
  1320. X
  1321. X#endif /* URT */
  1322. END_OF_FILE
  1323. if test 7560 -ne `wc -c <'libshade/picture.c'`; then
  1324.     echo shar: \"'libshade/picture.c'\" unpacked with wrong size!
  1325. fi
  1326. # end of 'libshade/picture.c'
  1327. fi
  1328. if test -f 'libshade/viewing.c' -a "${1}" != "-c" ; then 
  1329.   echo shar: Will not clobber existing file \"'libshade/viewing.c'\"
  1330. else
  1331. echo shar: Extracting \"'libshade/viewing.c'\" \(7193 characters\)
  1332. sed "s/^X//" >'libshade/viewing.c' <<'END_OF_FILE'
  1333. X/*
  1334. X * viewing.c
  1335. X *
  1336. X * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
  1337. X * All rights reserved.
  1338. X *
  1339. X * This software may be freely copied, modified, and redistributed
  1340. X * provided that this copyright notice is preserved on all copies.
  1341. X *
  1342. X * You may not distribute this software, in whole or in part, as part of
  1343. X * any commercial product without the express consent of the authors.
  1344. X *
  1345. X * There is no warranty or other guarantee of fitness of this software
  1346. X * for any purpose.  It is provided solely "as is".
  1347. X *
  1348. X * $Id: viewing.c,v 4.0 91/07/17 14:48:18 kolb Exp Locker: kolb $
  1349. X *
  1350. X * $Log:    viewing.c,v $
  1351. X * Revision 4.0  91/07/17  14:48:18  kolb
  1352. X * Initial version.
  1353. X * 
  1354. X */
  1355. X#include "rayshade.h"
  1356. X#include "viewing.h"
  1357. X#include "libcommon/sampling.h"
  1358. X#include "options.h"
  1359. X#include "defaults.h"
  1360. X#include "picture.h"
  1361. X#include "stats.h"
  1362. X
  1363. XRSCamera    Camera;
  1364. XRSScreen    Screen;
  1365. X
  1366. Xvoid SampleScreen(), SampleScreenFiltered();
  1367. X
  1368. Xvoid
  1369. XRSViewing()
  1370. X{
  1371. X    Float magnitude;
  1372. X
  1373. X    VecSub(Camera.lookp, Camera.pos, &Camera.dir);
  1374. X    Screen.firstray = Camera.dir;
  1375. X
  1376. X    Camera.lookdist = VecNormalize(&Camera.dir);
  1377. X    if (VecNormCross(&Camera.dir, &Camera.up, &Screen.scrni) == 0.)
  1378. X        RLerror(RL_PANIC,
  1379. X            "The view and up directions are identical?\n");
  1380. X    (void)VecNormCross(&Screen.scrni, &Camera.dir, &Screen.scrnj);
  1381. X
  1382. X    /*
  1383. X     * Add stereo separation if desired.
  1384. X     */
  1385. X    if (Options.stereo) {
  1386. X        if (Options.stereo == LEFT)
  1387. X            magnitude = -.5 * Options.eyesep;
  1388. X        else
  1389. X            magnitude =  .5 * Options.eyesep;
  1390. X        Camera.pos.x += magnitude * Screen.scrni.x;
  1391. X        Camera.pos.y += magnitude * Screen.scrni.y;
  1392. X        Camera.pos.z += magnitude * Screen.scrni.z;
  1393. X        VecSub(Camera.lookp, Camera.pos, &Screen.firstray);
  1394. X        Camera.dir = Screen.firstray;
  1395. X        Camera.lookdist = VecNormalize(&Camera.dir);
  1396. X        (void)VecNormCross(&Camera.dir, &Camera.up, &Screen.scrni);
  1397. X        (void)VecNormCross(&Screen.scrni, &Camera.dir, &Screen.scrnj);
  1398. X    }
  1399. X
  1400. X    magnitude = 2.*Camera.lookdist * tan(deg2rad(0.5*Camera.hfov)) /
  1401. X                Screen.xres;
  1402. X
  1403. X    VecScale(magnitude, Screen.scrni, &Screen.scrnx);
  1404. X    magnitude = 2.*Camera.lookdist * tan(deg2rad(0.5*Camera.vfov)) /
  1405. X                Screen.yres;
  1406. X    VecScale(magnitude, Screen.scrnj, &Screen.scrny);
  1407. X
  1408. X    Screen.firstray.x -= 0.5*Screen.yres*Screen.scrny.x +
  1409. X                 0.5*Screen.xres*Screen.scrnx.x;
  1410. X    Screen.firstray.y -= 0.5*Screen.yres*Screen.scrny.y +
  1411. X                 0.5*Screen.xres*Screen.scrnx.y;
  1412. X    Screen.firstray.z -= 0.5*Screen.yres*Screen.scrny.z +
  1413. X                 0.5*Screen.xres*Screen.scrnx.z;
  1414. X
  1415. X    if (Camera.focaldist == UNSET)
  1416. X        Camera.focaldist = Camera.lookdist;
  1417. X}
  1418. X
  1419. X/*
  1420. X * Adjust the initial ray to account for an aperture and a focal
  1421. X * distance.  The ray argument is assumed to be an initial ray, and
  1422. X * always reset to the eye point.  It is assumed to be unit length.
  1423. X */
  1424. Xvoid
  1425. Xfocus_blur_ray(ray)
  1426. XRay *ray;
  1427. X{
  1428. X    Vector circle_point, aperture_inc;
  1429. X    extern void UnitCirclePoint();
  1430. X    /*
  1431. X     * Find a point on a unit circle and scale by aperture size.
  1432. X     * This simulates rays passing thru different parts of the aperture.
  1433. X     * Treat the point as a vector and rotate it so the circle lies
  1434. X     * in the plane of the screen.  Add the aperture increment to the
  1435. X     * starting position of the ray.  Stretch the ray to be focaldist 
  1436. X     * in length.  Subtract the aperture increment from the end of the
  1437. X     * long ray.  This insures that the ray heads toward a point at
  1438. X     * the specified focus distance, so that point will be in focus.
  1439. X     * Normalize the ray, and that's it.  Really.
  1440. X     */
  1441. X    UnitCirclePoint(&circle_point, ray->sample);
  1442. X    VecComb(Camera.aperture * circle_point.x, Screen.scrni,
  1443. X            Camera.aperture * circle_point.y, Screen.scrnj,
  1444. X            &aperture_inc);
  1445. X    VecAdd(aperture_inc, Camera.pos, &(ray->pos));
  1446. X    VecScale(Camera.focaldist, ray->dir, &(ray->dir));
  1447. X    VecSub(ray->dir, aperture_inc, &(ray->dir));
  1448. X    (void)VecNormalize(&ray->dir);
  1449. X}
  1450. X
  1451. Xvoid
  1452. XViewingSetup()
  1453. X{
  1454. X    if (Options.stereo && Options.eyesep == UNSET)
  1455. X        RLerror(RL_PANIC,
  1456. X            "No eye separation specified for stereo rendering.\n");
  1457. X    /*
  1458. X     * Because we want the user to be able to override the input file
  1459. X     * through the command line, we have to initialize some variables to
  1460. X     * bogus values so that when the file is being parsed, it is
  1461. X     * possible to tell if a given variable has been set on the
  1462. X     * command line.
  1463. X     *
  1464. X     * If such variables are not set to legal values on the command
  1465. X     * line or in the input file, we must do it here.
  1466. X     */
  1467. X    if (Screen.xres == UNSET)
  1468. X        Screen.xres = XRESOLUTION;
  1469. X    if (Screen.yres == UNSET)
  1470. X        Screen.yres = YRESOLUTION;
  1471. X
  1472. X#ifdef URT
  1473. X    /*
  1474. X     * If using the URT, we can use the RLE file header to
  1475. X     * determine window size.  Screen size (Screen.xres, Screen.yres)
  1476. X     * is determined as usual (from command line or input file).
  1477. X     */
  1478. X    if (Options.appending) {
  1479. X        /*
  1480. X         * Read image header to determine window size.
  1481. X         */
  1482. X        PictureSetWindow();
  1483. X    } else {
  1484. X#endif
  1485. X    if (Options.xmin < 0.) Options.xmin = 0.;
  1486. X    if (Options.ymin < 0.) Options.ymin = 0.;
  1487. X    if (Options.xmax > 1.) Options.xmax = 1.;
  1488. X    if (Options.xmax > 1.) Options.xmax = 1.;
  1489. X
  1490. X    Screen.minx = (int)(Options.xmin * Screen.xres);
  1491. X    Screen.maxx = (int)(Options.xmax * Screen.xres -1);
  1492. X    Screen.miny = (int)(Options.ymin * Screen.yres);
  1493. X    Screen.maxy = (int)(Options.ymax * Screen.yres -1);
  1494. X#ifdef URT
  1495. X    }
  1496. X#endif
  1497. X
  1498. X    Screen.xsize = Screen.maxx - Screen.minx + 1;
  1499. X    Screen.ysize = Screen.maxy - Screen.miny + 1;
  1500. X
  1501. X    /*
  1502. X     * Sanity check.
  1503. X     */
  1504. X    if (Screen.minx < 0 || Screen.miny < 0 ||
  1505. X        Screen.maxx >= Screen.xres || Screen.maxy >= Screen.yres)
  1506. X        RLerror(RL_PANIC, "Invalid window specification.\n");
  1507. X
  1508. X    /*
  1509. X     * If not defined in the input file, calculate VFOV
  1510. X     * by hand.  This assumes that pixels are square, which is
  1511. X     * probably a bad idea.  ("aspect" option?)
  1512. X     */
  1513. X    if (Camera.vfov == UNSET)
  1514. X        Camera.vfov = Camera.hfov * Screen.yres / Screen.xres;
  1515. X}
  1516. X
  1517. Xvoid
  1518. XSampleScreenFiltered(x, y, u, v, ray, color, sample)
  1519. XFloat x, y;
  1520. XRay *ray;
  1521. XPixel *color;
  1522. Xint sample, u, v;
  1523. X{
  1524. X    SampleScreen(x, y, ray, color, sample);
  1525. X    color->r *= Sampling.filter[u][v];
  1526. X    color->g *= Sampling.filter[u][v];
  1527. X    color->b *= Sampling.filter[u][v];
  1528. X    color->alpha *= Sampling.filter[u][v];
  1529. X}    
  1530. X
  1531. Xvoid
  1532. XSampleScreen(x, y, ray, color, sample)
  1533. XFloat x, y;        /* Screen position to sample */
  1534. XRay *ray;        /* ray, with origin and medium properly set */
  1535. XPixel *color;        /* resulting color */
  1536. Xint sample;        /* sample number */
  1537. X{
  1538. X    Float dist;
  1539. X    HitList hitlist;
  1540. X    Color ctmp, fullintens;
  1541. X    extern void focus_blur_ray(), ShadeRay();
  1542. X
  1543. X    /*
  1544. X     * Calculate ray direction.
  1545. X     */
  1546. X    Stats.EyeRays++;
  1547. X    ray->dir.x = Screen.firstray.x + x*Screen.scrnx.x + y*Screen.scrny.x;
  1548. X    ray->dir.y = Screen.firstray.y + x*Screen.scrnx.y + y*Screen.scrny.y;
  1549. X    ray->dir.z = Screen.firstray.z + x*Screen.scrnx.z + y*Screen.scrny.z;
  1550. X
  1551. X    (void)VecNormalize(&ray->dir);
  1552. X
  1553. X    ray->sample = sample;
  1554. X
  1555. X    if (Camera.aperture > 0.0) {
  1556. X        /*
  1557. X         * If the aperture is open, adjust the initial ray
  1558. X         * to account for depth of field.  
  1559. X         */
  1560. X        focus_blur_ray(ray);
  1561. X    }
  1562. X
  1563. X    /*
  1564. X     * Do the actual ray trace.
  1565. X     */
  1566. X    fullintens.r = fullintens.g = fullintens.b = 1.;
  1567. X    dist = FAR_AWAY;
  1568. X    hitlist.nodes = 0;
  1569. X    (void)TraceRay(ray, &hitlist, EPSILON, &dist);
  1570. X    ShadeRay(&hitlist, ray, dist, &Screen.background, &ctmp, &fullintens);
  1571. X    color->r = ctmp.r;
  1572. X    color->g = ctmp.g;
  1573. X    color->b = ctmp.b;
  1574. X    if (hitlist.nodes != 0) {
  1575. X        color->alpha = 1.;
  1576. X    } else {
  1577. X        color->alpha = 0.;
  1578. X    }
  1579. X}
  1580. END_OF_FILE
  1581. if test 7193 -ne `wc -c <'libshade/viewing.c'`; then
  1582.     echo shar: \"'libshade/viewing.c'\" unpacked with wrong size!
  1583. fi
  1584. # end of 'libshade/viewing.c'
  1585. fi
  1586. if test -f 'raypaint/xgraphics.c' -a "${1}" != "-c" ; then 
  1587.   echo shar: Will not clobber existing file \"'raypaint/xgraphics.c'\"
  1588. else
  1589. echo shar: Extracting \"'raypaint/xgraphics.c'\" \(7806 characters\)
  1590. sed "s/^X//" >'raypaint/xgraphics.c' <<'END_OF_FILE'
  1591. X/*
  1592. X * xgraphics.c
  1593. X *
  1594. X * Copyright (C) 1989, 1991 Craig E. Kolb, Rod G. Bogart
  1595. X *
  1596. X * This software may be freely copied, modified, and redistributed
  1597. X * provided that this copyright notice is preserved on all copies.
  1598. X *
  1599. X * You may not distribute this software, in whole or in part, as part of
  1600. X * any commercial product without the express consent of the authors.
  1601. X * 
  1602. X * There is no warranty or other guarantee of fitness of this software
  1603. X * for any purpose.  It is provided solely "as is".
  1604. X *
  1605. X * $Id: xgraphics.c,v 4.0 91/07/17 17:37:32 kolb Exp Locker: kolb $
  1606. X *
  1607. X * $Log:    xgraphics.c,v $
  1608. X * Revision 4.0  91/07/17  17:37:32  kolb
  1609. X * Initial version.
  1610. X * 
  1611. X */
  1612. X
  1613. X#include <stdio.h>
  1614. X#include <math.h>
  1615. X#include <X11/Xlib.h>
  1616. X#include <X11/Xutil.h>
  1617. X
  1618. Xchar *display_name = NULL;
  1619. XDisplay *dpy = NULL;
  1620. XScreen *scrn;
  1621. XVisual *vis;
  1622. XColormap cmap;
  1623. XGC gc;
  1624. XWindow win;
  1625. Xint screen_height;
  1626. X
  1627. Xunsigned long graymap[256];
  1628. Xint max_colors;
  1629. Xdouble one_over_gamma = 0.4;
  1630. X
  1631. X/*****************************************************************
  1632. X * Sets the gray color map for the device.  A 2.5 gamma map is used
  1633. X * by default.
  1634. X */
  1635. Xsetup_gray_gamma_map()
  1636. X{
  1637. X    int cc, col;
  1638. X    int gamma_color;
  1639. X
  1640. X    XColor xcolor;
  1641. X
  1642. X    /* Use the default colormap if possible. */
  1643. X    if ( vis == DefaultVisualOfScreen( scrn ) )
  1644. X        cmap = DefaultColormapOfScreen( scrn );
  1645. X    else
  1646. X        cmap = XCreateColormap( dpy, RootWindowOfScreen( scrn ),
  1647. X                               vis, AllocNone );
  1648. X
  1649. X    /* try to share with current colormap */
  1650. X    for (max_colors = 256; max_colors >= 16; max_colors = max_colors >> 1) {
  1651. X        xcolor.flags= DoRed | DoGreen | DoBlue;
  1652. X        for(col=0; col < max_colors; col++) {
  1653. X            gamma_color = (pow((float) col / (float) max_colors,
  1654. X                               one_over_gamma) * 65536);
  1655. X            xcolor.red= gamma_color;
  1656. X            xcolor.green= gamma_color;
  1657. X            xcolor.blue= gamma_color;
  1658. X            if (!XAllocColor(dpy, cmap, &xcolor)) {
  1659. X                for (cc=0; cc < col; cc++)
  1660. X                    XFreeColors(dpy, cmap, &graymap[cc], 1, 0);
  1661. X                col = 0;
  1662. X                break;
  1663. X            }
  1664. X            graymap[col] = xcolor.pixel;
  1665. X        }
  1666. X        if (col)
  1667. X            return;
  1668. X    }
  1669. X
  1670. X    /* use new map */
  1671. X    cmap = XCreateColormap( dpy, RootWindowOfScreen( scrn ),
  1672. X                           vis, AllocNone );
  1673. X    if (cmap == NULL)  {
  1674. X        fprintf(stderr, "Could not create color map for visual\n");
  1675. X        exit(-2);
  1676. X    }
  1677. X    for(cc=0; cc < 256; cc++)
  1678. X        if (!XAllocColorCells(dpy, cmap, False, NULL, 0, &graymap[cc], 1))
  1679. X            break;
  1680. X    max_colors = cc;
  1681. X
  1682. X    xcolor.flags= DoRed | DoGreen | DoBlue;
  1683. X    for(col=0; col < max_colors; col++) {
  1684. X        xcolor.pixel= graymap[col];
  1685. X        gamma_color = (pow((float) col / (float) max_colors,
  1686. X                           one_over_gamma) * 65536);
  1687. X        xcolor.red= gamma_color;
  1688. X        xcolor.green= gamma_color;
  1689. X        xcolor.blue= gamma_color;
  1690. X        XStoreColor(dpy, cmap, &xcolor);
  1691. X    }
  1692. X}
  1693. X
  1694. XGraphicsInit(xsize, ysize, name)
  1695. Xint xsize, ysize;
  1696. Xchar *name;
  1697. X{
  1698. X    int win_size;
  1699. X    XSetWindowAttributes attrs;
  1700. X    XSizeHints sh;
  1701. X
  1702. X    /* Open the display. */
  1703. X    if ( ! dpy )
  1704. X    {
  1705. X        XVisualInfo vis_temp, *vis_list, *max_vis;
  1706. X        int n_ret, i;
  1707. X
  1708. X        dpy = XOpenDisplay( display_name );
  1709. X        if ( ! dpy )
  1710. X        {
  1711. X            fprintf( stderr, "rayview: Can't open display %s\n",
  1712. X                     XDisplayName( display_name ) );
  1713. X            exit(1);
  1714. X        }
  1715. X
  1716. X        /* Get a PseudoColor visual that has the maximum number of planes. */
  1717. X        vis_temp.class = PseudoColor;
  1718. X        vis_list = XGetVisualInfo( dpy, VisualClassMask, &vis_temp, &n_ret );
  1719. X        if ( n_ret == 0 )
  1720. X        {
  1721. X            fprintf(stderr,
  1722. X                    "Can't find any PseudoColor visual from display %s.\n",
  1723. X                    XDisplayName( display_name ));
  1724. X            exit(1);
  1725. X        }
  1726. X        max_vis = &vis_list[0];
  1727. X        for ( i = 1; i < n_ret; i++ )
  1728. X        {
  1729. X            if ( max_vis->depth < vis_list[i].depth )
  1730. X                max_vis = &vis_list[i];
  1731. X        }
  1732. X        vis = max_vis->visual;
  1733. X        scrn = ScreenOfDisplay( dpy, max_vis->screen );
  1734. X        gc = DefaultGCOfScreen( scrn );
  1735. X
  1736. X        setup_gray_gamma_map();
  1737. X
  1738. X        XFree( (char *)vis_list );
  1739. X    }
  1740. X
  1741. X    screen_height = ysize;
  1742. X
  1743. X    attrs.backing_store = Always;
  1744. X    attrs.colormap = cmap;
  1745. X    attrs.event_mask = ExposureMask;
  1746. X    attrs.background_pixel = BlackPixelOfScreen(scrn);
  1747. X    attrs.border_pixel = WhitePixelOfScreen(scrn);
  1748. X
  1749. X    win = XCreateWindow( dpy, RootWindowOfScreen( scrn ),
  1750. X                         0, 0, xsize, ysize, 2,
  1751. X                         0, 0, vis,
  1752. X                         CWBackingStore | CWColormap | CWEventMask |
  1753. X                         CWBackPixel | CWBorderPixel,
  1754. X                         &attrs );
  1755. X
  1756. X    sh.flags = PSize | PMinSize | PMaxSize;
  1757. X    sh.width = sh.min_width = sh.max_width = xsize;
  1758. X    sh.height = sh.min_height = sh.max_height = ysize;
  1759. X    XSetStandardProperties( dpy, win, name, name, None, NULL, 0, &sh );
  1760. X
  1761. X    XMapWindow( dpy, win );
  1762. X
  1763. X    XFlush( dpy );
  1764. X}
  1765. X
  1766. X/*
  1767. X * Draw the pixel at (xp, yp) in the color given by the rgb-triple,
  1768. X * 0 indicating 0 intensity, 255 max intensity.
  1769. X */
  1770. XGraphicsDrawPixel(xp, yp, color)
  1771. Xint xp, yp;
  1772. Xunsigned char color[3];
  1773. X{
  1774. X    float bwvalue;
  1775. X    int val;
  1776. X
  1777. X    bwvalue = ( 0.35*color[0] + 0.55*color[1] + 0.10*color[2] ) / 256.0;
  1778. X    val = (int) ( bwvalue * max_colors );
  1779. X    XSetForeground( dpy, gc, graymap[val] );
  1780. X    XFillRectangle( dpy, win, gc, xp, (screen_height - (yp + 1)),
  1781. X                    1, 1 );
  1782. X}
  1783. X
  1784. X/*
  1785. X * Draw the rect with lower left corner (xp, yp) and upper right
  1786. X * corner (xp+ys, yp+ys).  The colors of the l-l, l-r, u-r, and u-l
  1787. X * corners are given as arrays of unsigned chars as above.
  1788. X */
  1789. XGraphicsDrawRectangle(xp, yp, xs, ys, ll, lr, ur, ul)
  1790. Xint xp, yp, xs, ys;
  1791. Xunsigned char ll[3], lr[3], ur[3], ul[3];
  1792. X{
  1793. X    float bwvalue;
  1794. X    int val;
  1795. X
  1796. X    bwvalue = ( 0.35*ll[0] + 0.55*ll[1] + 0.10*ll[2] ) / 256.0;
  1797. X    val = (int) ( bwvalue * max_colors );
  1798. X    XSetForeground( dpy, gc, graymap[val] );
  1799. X    XFillRectangle( dpy, win, gc, xp, (screen_height - (yp + ys + 1)),
  1800. X                    xs+1, ys+1 );
  1801. X    XFlush( dpy );
  1802. X}
  1803. X
  1804. XGraphicsLeftMouseEvent()
  1805. X{
  1806. X    Window root_ret, child_ret;
  1807. X    int rx, ry, wx, wy;
  1808. X    unsigned int mask;
  1809. X
  1810. X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
  1811. X                      &rx, &ry, &wx, &wy, &mask)) {
  1812. X        return mask & Button1Mask;
  1813. X    }
  1814. X    else
  1815. X        return 0;
  1816. X}
  1817. X
  1818. XGraphicsMiddleMouseEvent()
  1819. X{
  1820. X    Window root_ret, child_ret;
  1821. X    int rx, ry, wx, wy;
  1822. X    unsigned int mask;
  1823. X
  1824. X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
  1825. X                      &rx, &ry, &wx, &wy, &mask)) {
  1826. X        return mask & Button2Mask;
  1827. X    }
  1828. X    else
  1829. X        return 0;
  1830. X}
  1831. X
  1832. XGraphicsRightMouseEvent()
  1833. X{
  1834. X    Window root_ret, child_ret;
  1835. X    int rx, ry, wx, wy;
  1836. X    unsigned int mask;
  1837. X
  1838. X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
  1839. X                      &rx, &ry, &wx, &wy, &mask)) {
  1840. X        return mask & Button3Mask;
  1841. X    }
  1842. X    else
  1843. X        return 0;
  1844. X}
  1845. X
  1846. XGraphicsGetMousePos(x, y)
  1847. Xint *x, *y;
  1848. X{
  1849. X    Window root_ret, child_ret;
  1850. X    int rx, ry, wx, wy;
  1851. X    unsigned int mask;
  1852. X
  1853. X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
  1854. X                      &rx, &ry, &wx, &wy, &mask)) {
  1855. X        *x = wx;
  1856. X        *y = screen_height - wy - 1;
  1857. X    }
  1858. X    else {
  1859. X        *x = 0;
  1860. X        *y = 0;
  1861. X    }
  1862. X}
  1863. X
  1864. XGraphicsRedraw()
  1865. X{
  1866. X        XEvent event;
  1867. X        if (XCheckTypedEvent(dpy, Expose, &event)) {
  1868. X                XSetForeground( dpy, gc, graymap[0] );
  1869. X                XFillRectangle( dpy, win, gc, event.xexpose.x, event.xexpose.y,
  1870. X                    event.xexpose.width, event.xexpose.height );
  1871. X                XFlush( dpy );
  1872. X                return 1;
  1873. X        }
  1874. X        else
  1875. X                return 0;
  1876. X}
  1877. X
  1878. END_OF_FILE
  1879. if test 7806 -ne `wc -c <'raypaint/xgraphics.c'`; then
  1880.     echo shar: \"'raypaint/xgraphics.c'\" unpacked with wrong size!
  1881. fi
  1882. # end of 'raypaint/xgraphics.c'
  1883. fi
  1884. echo shar: End of archive 11 \(of 19\).
  1885. cp /dev/null ark11isdone
  1886. MISSING=""
  1887. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1888.     if test ! -f ark${I}isdone ; then
  1889.     MISSING="${MISSING} ${I}"
  1890.     fi
  1891. done
  1892. if test "${MISSING}" = "" ; then
  1893.     echo You have unpacked all 19 archives.
  1894.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1895. else
  1896.     echo You still need to unpack the following archives:
  1897.     echo "        " ${MISSING}
  1898. fi
  1899. ##  End of shell archive.
  1900. exit 0
  1901.  
  1902. exit 0 # Just in case...
  1903.