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

  1. /*
  2.  * vecmath.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.  * vecmath.c,v 4.1 1994/08/09 07:55:27 explorer Exp
  17.  *
  18.  * vecmath.c,v
  19.  * Revision 4.1  1994/08/09  07:55:27  explorer
  20.  * Bump version to 4.1
  21.  *
  22.  * Revision 1.1.1.1  1994/08/08  04:52:02  explorer
  23.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  24.  *
  25.  * Revision 4.0.1.2  91/11/26  21:36:15  cek
  26.  * patch3: Potential roundoff problems.
  27.  * 
  28.  * Revision 4.0.1.1  91/09/29  15:38:41  cek
  29.  * patch1: Fixed floating-point compare in normalization code.
  30.  *
  31.  * Revision 4.0  91/07/17  14:33:02  kolb
  32.  * Initial version.
  33.  * 
  34.  */
  35. #include "common.h"
  36.  
  37. /*
  38.  * Normalize a vector, return original length.
  39.  */
  40. Float
  41. VecNormalize(a)
  42. register Vector *a;
  43. {
  44.     Float d;
  45.  
  46.     d = sqrt(a->x*a->x + a->y*a->y + a->z*a->z);
  47.     if (equal(d, 0.))
  48.         return 0.;
  49.     a->x /= d;
  50.     a->y /= d;
  51.     a->z /= d;
  52. #ifdef CRAY
  53.     /*
  54.      * The Cray Research Inc. math functional units don't work in the IEEE
  55.      * standard way, so when we get here, we just might have an x,y or z
  56.      * that is not in the range  -1.0 <= J <= 1.0 Yes, I know that that
  57.      * can't happen, but it does. So since we know we just normalized this
  58.      * vector, we'll just force x,y and z into the range -1.0 to 1.0 O.K?
  59.      */
  60.     if (a->x >= 1.0) a->x = 1.0;
  61.     else if (a->x <= -1.0) a->x = -1.0;
  62.     if (a->y >= 1.0) a->y = 1.0;
  63.     else if (a->y <= -1.0) a->y = -1.0;
  64.     if (a->z >= 1.0) a->z = 1.0;
  65.     else if (a->z <= -1.0) a->z = -1.0;
  66. #endif /* CRAY */
  67.  
  68.     return d;
  69. }
  70.  
  71. /*
  72.  * Compute cross-product of a and b, place normalized result in o.  Returns
  73.  * length of result before normalization.
  74.  */
  75. Float
  76. VecNormCross(a, b, r)
  77. Vector *a, *b, *r;
  78. {
  79.     VecCross(a, b, r);
  80.     return VecNormalize(r);
  81. }
  82.  
  83. /*
  84.  * Compute (euclidian) distance between two points [PhB]
  85.  */
  86. Float
  87. VecDist(a, b)
  88. Vector *a, *b;
  89. {
  90.         Vector temp;
  91.         VecSub(*a, *b, &temp);
  92.         return VecNorm(temp);
  93. }
  94.  
  95. /*
  96.  * Compute cross-product of a and b, place result in o.
  97.  */
  98. void
  99. VecCross(a, b, r)
  100. Vector *a, *b, *r;
  101. {
  102.     r->x = (a->y * b->z) - (a->z * b->y);
  103.     r->y = (a->z * b->x) - (a->x * b->z);
  104.     r->z = (a->x * b->y) - (a->y * b->x);
  105. }
  106.  
  107. /*
  108.  * Calculate direction of refracted ray using Heckbert's formula.  Returns TRUE
  109.  * if a total internal reflection occurs.
  110.  */
  111. int
  112. Refract(dir, from_index, to_index, I, N, cos1)
  113. Float from_index, to_index, cos1;
  114. Vector *dir, *I, *N;
  115. {
  116.     double kn, cos2, k;
  117.     Vector nrm;
  118.  
  119.     if (cos1 < 0.) {
  120.         /*
  121.          * Hit the 'backside' of a surface -- flip the normal.
  122.          */
  123.         nrm.x = -N->x;
  124.         nrm.y = -N->y;
  125.         nrm.z = -N->z;
  126.         cos1 = -cos1;
  127.     } else
  128.         nrm = *N;
  129.  
  130.     kn = from_index / to_index;
  131.     cos2 = 1. - kn*kn*(1. - cos1*cos1);
  132.     if (cos2 < 0.)
  133.         return TRUE;        /* Total internal reflection. */
  134.     k = kn * cos1 - sqrt((double)cos2);
  135.     VecComb(kn, *I, k, nrm, dir);
  136.     return FALSE;
  137. }
  138.  
  139. /*
  140.  * Given a vector, find two additional vectors such that all three
  141.  * are mutually perpendicular and uaxis X vaxis = vector.  The given
  142.  * vector need not be normalized. uaxis and vaxis are normalized.
  143.  */
  144. void
  145. VecCoordSys(vector, uaxis, vaxis)
  146. Vector *vector, *uaxis, *vaxis;
  147. {
  148.     uaxis->x = -vector->y;
  149.     uaxis->y = vector->x;
  150.     uaxis->z = 0.;
  151.     if (VecNormalize(uaxis) == 0.) {
  152.         uaxis->x = vector->z;
  153.         uaxis->y = 0.;
  154.         uaxis->z = -vector->x;
  155.         if (VecNormalize(uaxis) == 0.)
  156.             RLerror(RL_WARN,
  157.                 "VecCoordSys passed degenerate vector.\n");
  158.     }
  159.     (void)VecNormCross(vector, uaxis, vaxis);
  160. }
  161.  
  162. /*
  163.  * Modify given normal by "bumping" it.
  164.  */
  165. void
  166. MakeBump(norm, dpdu, dpdv, fu, fv)
  167. Vector *norm, *dpdu, *dpdv;    /* normal, surface derivatives */
  168. Float fu, fv;            /* bump function partial derivatives in uv */
  169. {
  170.     Vector tmp1, tmp2;
  171.  
  172.     VecCross(norm, dpdv, &tmp1);
  173.     VecScale(fu, tmp1, &tmp1);
  174.     VecCross(norm, dpdu, &tmp2);
  175.     VecScale(fv, tmp2, &tmp2);
  176.     VecSub(tmp1, tmp2, &tmp1);
  177.     VecAdd(*norm, tmp1, norm);
  178.     (void)VecNormalize(norm);
  179. }
  180.