home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / libtext / mapping.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  5.7 KB  |  278 lines

  1. /*
  2.  * mapping.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * mapping.c,v 4.1 1994/08/09 08:02:55 explorer Exp
  17.  *
  18.  * mapping.c,v
  19.  * Revision 4.1  1994/08/09  08:02:55  explorer
  20.  * Bump version to 4.1
  21.  *
  22.  * Revision 1.1.1.1  1994/08/08  04:52:15  explorer
  23.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  24.  *
  25.  * Revision 4.0  91/07/17  14:42:54  kolb
  26.  * Initial version.
  27.  * 
  28.  */
  29. #include "libobj/geom.h"
  30. #include "mapping.h"
  31.  
  32. void UVMapping(), SphereMapping(), CylinderMapping(), LinearMapping();
  33.  
  34. Mapping *
  35. UVMappingCreate()
  36. {
  37.     Mapping *res;
  38.  
  39.     res = (Mapping *)Malloc(sizeof(Mapping));
  40.     res->flags = PRIMSPACE;
  41.     res->method = UVMapping;
  42.     return res;
  43. }
  44.  
  45. Mapping *
  46. SphereMappingCreate(center, norm, uaxis)
  47. Vector *center, *norm, *uaxis;
  48. {
  49.     Mapping *res;
  50.  
  51.     res = (Mapping *)Malloc(sizeof(Mapping));
  52.     res->flags = OBJSPACE;
  53.     res->method = SphereMapping;
  54.     if (center)
  55.         res->center = *center;
  56.     else
  57.         res->center.x = res->center.y = res->center.z = 0.;
  58.     if (norm && uaxis) {
  59.         res->norm = *norm;
  60.         if (VecNormalize(&res->norm) == 0.) {
  61.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  62.             return (Mapping *)NULL;
  63.         }
  64.         if (VecNormCross(norm, uaxis, &res->vaxis) == 0.) {
  65.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  66.             return (Mapping *)NULL;
  67.         }
  68.         (void)VecNormCross(&res->vaxis, norm, &res->uaxis);
  69.     } else {
  70.         res->norm.x = res->norm.y = res->uaxis.y = res->uaxis.z =
  71.             res->vaxis.x = res->vaxis.z = 0.;
  72.         res->norm.z = res->uaxis.x = res->vaxis.y = 1.;
  73.     }
  74.     return res;
  75. }
  76.  
  77. Mapping *
  78. CylMappingCreate(center, norm, uaxis)
  79. Vector *center, *norm, *uaxis;
  80. {
  81.     Mapping *res;
  82.  
  83.     res = (Mapping *)Malloc(sizeof(Mapping));
  84.     res->flags = OBJSPACE;
  85.     res->method = CylinderMapping;
  86.     if (center)
  87.         res->center = *center;
  88.     else
  89.         res->center.x = res->center.y = res->center.z = 0.;
  90.     if (norm && uaxis) {
  91.         res->norm = *norm;
  92.         if (VecNormalize(&res->norm) == 0.) {
  93.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  94.             return (Mapping *)NULL;
  95.         }
  96.         /*
  97.          * Here, uaxis indicates where theta (u) = 0.
  98.          */
  99.         if (VecNormCross(norm, uaxis, &res->vaxis) == 0.) {
  100.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  101.             return (Mapping *)NULL;
  102.         }
  103.         (void)VecNormCross(&res->vaxis, norm, &res->uaxis);
  104.     } else {
  105.         res->norm.x = res->norm.y = res->uaxis.y = res->uaxis.z =
  106.             res->vaxis.x = res->vaxis.z = 0.;
  107.         res->norm.z = res->uaxis.x = res->vaxis.y = 1.;
  108.     }
  109.     return res;
  110. }
  111.  
  112. Mapping *
  113. LinearMappingCreate(center, vaxis, uaxis)
  114. Vector *center, *vaxis, *uaxis;
  115. {
  116.     Mapping *res;
  117.     RSMatrix m;
  118.     Vector n;
  119.  
  120.     res = (Mapping *)Malloc(sizeof(Mapping));
  121.     res->flags = OBJSPACE;
  122.     res->method= LinearMapping;
  123.  
  124.     if (center)
  125.         res->center = *center;
  126.     else
  127.         res->center.x = res->center.y = res->center.z = 0.;
  128.  
  129.     if (uaxis && vaxis) {
  130.         VecCross(uaxis, vaxis, &n);
  131.         /* this is wrong, since uaxis and vaxis
  132.          * give U and V in world space, and we
  133.          * need the inverse.
  134.          */
  135.         ArbitraryMatrix(
  136.             uaxis->x, uaxis->y, uaxis->z,
  137.             vaxis->x, vaxis->y, vaxis->z,
  138.             n.x, n.y, n.z,
  139.             res->center.x, res->center.y, res->center.z,
  140.             &m);
  141.         MatrixInvert(&m, &res->m);
  142.         res->uaxis = *uaxis;
  143.         res->vaxis = *vaxis;
  144.         VecNormalize(&res->uaxis);
  145.         VecNormalize(&res->vaxis);
  146.     } else {
  147.         VecScale(-1., res->center, &n);
  148.         TranslationMatrix(n.x, n.y, n.z, &res->m);
  149.         res->uaxis.x = res->vaxis.y = 1.;
  150.         res->uaxis.y = res->uaxis.z = res->vaxis.x =
  151.             res->vaxis.z = 0.;
  152.     }
  153.     return res;
  154. }
  155.  
  156. void
  157. UVMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  158. Mapping *map;
  159. Geom *obj;
  160. Vec2d *uv;
  161. Vector *pos, *norm, *dpdu, *dpdv;
  162. {
  163.     PrimUV(obj, pos, norm, uv, dpdu, dpdv);
  164. }
  165.  
  166. void
  167. SphereMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  168. Mapping *map;
  169. Geom *obj;
  170. Vec2d *uv;
  171. Vector *pos, *norm, *dpdu, *dpdv;
  172. {
  173.     Vector vtmp;
  174.     Float nx, ny, nz, phi, theta;
  175.  
  176.     VecSub(*pos, map->center, &vtmp);
  177.     if (VecNormalize(&vtmp) == 0.) {
  178.         /*
  179.          * Point is coincident with origin of sphere.  Punt.
  180.          */
  181.         uv->u = uv->v = 0.;
  182.         return;
  183.     }
  184.  
  185.     /*
  186.      * Find location of point projected onto unit sphere
  187.      * in the sphere's coordinate system.
  188.      */
  189.     nx = dotp(&map->uaxis, &vtmp);
  190.     ny = dotp(&map->vaxis, &vtmp);
  191.     nz = dotp(&map->norm, &vtmp);
  192.  
  193.     if (nz > 1.)    /* roundoff */
  194.         phi = PI;
  195.     else if (nz < -1.)
  196.         phi = 0;
  197.     else
  198.         phi = acos(-nz);
  199.  
  200.     uv->v = phi / PI;
  201.  
  202.     if (fabs(uv->v) < EPSILON || equal(uv->v, 1.))
  203.         uv->u = 0.;
  204.     else {
  205.         theta = nx / sin(phi);
  206.         if (theta > 1.)
  207.             theta = 0.;
  208.         else if (theta < -1.)
  209.             theta = 0.5;
  210.         else
  211.             theta = acos(theta) / TWOPI;
  212.  
  213.         if (ny > 0)
  214.             uv->u = theta;
  215.         else
  216.             uv->u = 1 - theta;
  217.     }
  218. }
  219.  
  220. void
  221. CylinderMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  222. Mapping *map;
  223. Geom *obj;
  224. Vec2d *uv;
  225. Vector *pos, *norm, *dpdu, *dpdv;
  226. {
  227.     Vector vtmp;
  228.     Float nx, ny, r;
  229.  
  230.     VecSub(*pos, map->center, &vtmp);
  231.     nx = dotp(&map->uaxis, &vtmp);
  232.     ny = dotp(&map->vaxis, &vtmp);
  233.     uv->v = dotp(&map->norm, &vtmp);
  234.  
  235.     r = sqrt(nx*nx + ny*ny);
  236.  
  237.     if (r < EPSILON) {
  238.         uv->u = 0.;
  239.         return;
  240.     }
  241.  
  242.     nx /= r;
  243.     ny /= r;
  244.  
  245.     if (fabs(nx) > 1.)
  246.         uv->u = 0.5;
  247.     else
  248.         uv->u = acos(nx) / TWOPI;
  249.     if (ny < 0.)
  250.         uv->u = 1. - uv->u;
  251.  
  252.     if (dpdv)
  253.         *dpdv = map->norm;
  254.     if (dpdu)
  255.         (void)VecNormCross(&map->norm, pos, dpdu);
  256. }
  257.  
  258. void
  259. LinearMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  260. Mapping *map;
  261. Geom *obj;
  262. Vec2d *uv;
  263. Vector *pos, *norm, *dpdu, *dpdv;
  264. {
  265.     Vector vtmp;
  266.  
  267.     vtmp = *pos;
  268.     VecTransform(&vtmp, &map->m);
  269.     uv->u = vtmp.x; uv->v = vtmp.y;
  270.  
  271.     if (dpdu) {
  272.         *dpdu = map->uaxis;
  273.     }
  274.     if (dpdv) {
  275.         *dpdv = map->vaxis;
  276.     }
  277. }
  278.