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