home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / msdos / raytrace / rayshade / src / mapping.c < prev    next >
C/C++ Source or Header  |  1992-04-28  |  6KB  |  272 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.  * $Id: mapping.c,v 4.0 91/07/17 14:42:54 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    mapping.c,v $
  19.  * Revision 4.0  91/07/17  14:42:54  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "geom.h"
  24. #include "mapping.h"
  25.  
  26. void UVMapping(), SphereMapping(), CylinderMapping(), LinearMapping();
  27.  
  28. Mapping *
  29. UVMappingCreate()
  30. {
  31.     Mapping *res;
  32.  
  33.     res = (Mapping *)RayMalloc(sizeof(Mapping));
  34.     res->flags = PRIMSPACE;
  35.     res->method = UVMapping;
  36.     return res;
  37. }
  38.  
  39. Mapping *
  40. SphereMappingCreate(center, norm, uaxis)
  41. Vector *center, *norm, *uaxis;
  42. {
  43.     Mapping *res;
  44.  
  45.     res = (Mapping *)RayMalloc(sizeof(Mapping));
  46.     res->flags = OBJSPACE;
  47.     res->method = SphereMapping;
  48.     if (center)
  49.         res->center = *center;
  50.     else
  51.         res->center.x = res->center.y = res->center.z = 0.;
  52.     if (norm && uaxis) {
  53.         res->norm = *norm;
  54.         if (VecNormalize(&res->norm) == 0.) {
  55.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  56.             return (Mapping *)NULL;
  57.         }
  58.         if (VecNormCross(norm, uaxis, &res->vaxis) == 0.) {
  59.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  60.             return (Mapping *)NULL;
  61.         }
  62.         (void)VecNormCross(&res->vaxis, norm, &res->uaxis);
  63.     } else {
  64.         res->norm.x = res->norm.y = res->uaxis.y = res->uaxis.z =
  65.             res->vaxis.x = res->vaxis.z = 0.;
  66.         res->norm.z = res->uaxis.x = res->vaxis.y = 1.;
  67.     }
  68.     return res;
  69. }
  70.  
  71. Mapping *
  72. CylMappingCreate(center, norm, uaxis)
  73. Vector *center, *norm, *uaxis;
  74. {
  75.     Mapping *res;
  76.  
  77.     res = (Mapping *)RayMalloc(sizeof(Mapping));
  78.     res->flags = OBJSPACE;
  79.     res->method = CylinderMapping;
  80.     if (center)
  81.         res->center = *center;
  82.     else
  83.         res->center.x = res->center.y = res->center.z = 0.;
  84.     if (norm && uaxis) {
  85.         res->norm = *norm;
  86.         if (VecNormalize(&res->norm) == 0.) {
  87.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  88.             return (Mapping *)NULL;
  89.         }
  90.         /*
  91.          * Here, uaxis indicates where theta (u) = 0.
  92.          */
  93.         if (VecNormCross(norm, uaxis, &res->vaxis) == 0.) {
  94.             RLerror(RL_ABORT, "Degenerate mapping vector.\n");
  95.             return (Mapping *)NULL;
  96.         }
  97.         (void)VecNormCross(&res->vaxis, norm, &res->uaxis);
  98.     } else {
  99.         res->norm.x = res->norm.y = res->uaxis.y = res->uaxis.z =
  100.             res->vaxis.x = res->vaxis.z = 0.;
  101.         res->norm.z = res->uaxis.x = res->vaxis.y = 1.;
  102.     }
  103.     return res;
  104. }
  105.  
  106. Mapping *
  107. LinearMappingCreate(center, vaxis, uaxis)
  108. Vector *center, *vaxis, *uaxis;
  109. {
  110.     Mapping *res;
  111.     RSMatrix m;
  112.     Vector n;
  113.  
  114.     res = (Mapping *)RayMalloc(sizeof(Mapping));
  115.     res->flags = OBJSPACE;
  116.     res->method= LinearMapping;
  117.  
  118.     if (center)
  119.         res->center = *center;
  120.     else
  121.         res->center.x = res->center.y = res->center.z = 0.;
  122.  
  123.     if (uaxis && vaxis) {
  124.         VecCross(uaxis, vaxis, &n);
  125.         /* this is wrong, since uaxis and vaxis
  126.          * give U and V in world space, and we
  127.          * need the inverse.
  128.          */
  129.         ArbitraryMatrix(
  130.             uaxis->x, uaxis->y, uaxis->z,
  131.             vaxis->x, vaxis->y, vaxis->z,
  132.             n.x, n.y, n.z,
  133.             res->center.x, res->center.y, res->center.z,
  134.             &m);
  135.         MatrixInvert(&m, &res->m);
  136.         res->uaxis = *uaxis;
  137.         res->vaxis = *vaxis;
  138.         VecNormalize(&res->uaxis);
  139.         VecNormalize(&res->vaxis);
  140.     } else {
  141.         VecScale(-1., res->center, &n);
  142.         TranslationMatrix(n.x, n.y, n.z, &res->m);
  143.         res->uaxis.x = res->vaxis.y = 1.;
  144.         res->uaxis.y = res->uaxis.z = res->vaxis.x =
  145.             res->vaxis.z = 0.;
  146.     }
  147.     return res;
  148. }
  149.  
  150. void
  151. UVMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  152. Mapping *map;
  153. Geom *obj;
  154. Vec2d *uv;
  155. Vector *pos, *norm, *dpdu, *dpdv;
  156. {
  157.     PrimUV(obj, pos, norm, uv, dpdu, dpdv);
  158. }
  159.  
  160. void
  161. SphereMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  162. Mapping *map;
  163. Geom *obj;
  164. Vec2d *uv;
  165. Vector *pos, *norm, *dpdu, *dpdv;
  166. {
  167.     Vector vtmp;
  168.     Float nx, ny, nz, phi, theta;
  169.  
  170.     VecSub(*pos, map->center, &vtmp);
  171.     if (VecNormalize(&vtmp) == 0.) {
  172.         /*
  173.          * Point is coincident with origin of sphere.  Punt.
  174.          */
  175.         uv->u = uv->v = 0.;
  176.         return;
  177.     }
  178.  
  179.     /*
  180.      * Find location of point projected onto unit sphere
  181.      * in the sphere's coordinate system.
  182.      */
  183.     nx = dotp(&map->uaxis, &vtmp);
  184.     ny = dotp(&map->vaxis, &vtmp);
  185.     nz = dotp(&map->norm, &vtmp);
  186.  
  187.     if (nz > 1.)    /* roundoff */
  188.         phi = PI;
  189.     else if (nz < -1.)
  190.         phi = 0;
  191.     else
  192.         phi = acos(-nz);
  193.  
  194.     uv->v = phi / PI;
  195.  
  196.     if (fabs(uv->v) < EPSILON || equal(uv->v, 1.))
  197.         uv->u = 0.;
  198.     else {
  199.         theta = nx / sin(phi);
  200.         if (theta > 1.)
  201.             theta = 0.;
  202.         else if (theta < -1.)
  203.             theta = 0.5;
  204.         else
  205.             theta = acos(theta) / TWOPI;
  206.  
  207.         if (ny > 0)
  208.             uv->u = theta;
  209.         else
  210.             uv->u = 1 - theta;
  211.     }
  212. }
  213.  
  214. void
  215. CylinderMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  216. Mapping *map;
  217. Geom *obj;
  218. Vec2d *uv;
  219. Vector *pos, *norm, *dpdu, *dpdv;
  220. {
  221.     Vector vtmp;
  222.     Float nx, ny, r;
  223.  
  224.     VecSub(*pos, map->center, &vtmp);
  225.     nx = dotp(&map->uaxis, &vtmp);
  226.     ny = dotp(&map->vaxis, &vtmp);
  227.     uv->v = dotp(&map->norm, &vtmp);
  228.  
  229.     r = sqrt(nx*nx + ny*ny);
  230.  
  231.     if (r < EPSILON) {
  232.         uv->u = 0.;
  233.         return;
  234.     }
  235.  
  236.     nx /= r;
  237.     ny /= r;
  238.  
  239.     if (fabs(nx) > 1.)
  240.         uv->u = 0.5;
  241.     else
  242.         uv->u = acos(nx) / TWOPI;
  243.     if (ny < 0.)
  244.         uv->u = 1. - uv->u;
  245.  
  246.     if (dpdv)
  247.         *dpdv = map->norm;
  248.     if (dpdu)
  249.         (void)VecNormCross(&map->norm, pos, dpdu);
  250. }
  251.  
  252. void
  253. LinearMapping(map, obj, pos, norm, uv, dpdu, dpdv)
  254. Mapping *map;
  255. Geom *obj;
  256. Vec2d *uv;
  257. Vector *pos, *norm, *dpdu, *dpdv;
  258. {
  259.     Vector vtmp;
  260.  
  261.     vtmp = *pos;
  262.     VecTransform(&vtmp, &map->m);
  263.     uv->u = vtmp.x; uv->v = vtmp.y;
  264.  
  265.     if (dpdu) {
  266.         *dpdu = map->uaxis;
  267.     }
  268.     if (dpdv) {
  269.         *dpdv = map->vaxis;
  270.     }
  271. }
  272.