1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // * Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34
35
36
37 //----------------------------------------------------------------------------
38 //
39 // Specializations of the Vec2<T> and Vec3<T> templates.
40 //
41 //----------------------------------------------------------------------------
42
43 #include "ImathVec.h"
44
45 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
46 // suppress exception specification warnings
47 #pragma warning(disable:4290)
48 #endif
49
50
51 namespace Imath {
52
53 namespace
54 {
55
56 template<class T>
57 bool
normalizeOrThrow(Vec2<T> & v)58 normalizeOrThrow(Vec2<T> &v)
59 {
60 int axis = -1;
61 for (int i = 0; i < 2; i ++)
62 {
63 if (v[i] != 0)
64 {
65 if (axis != -1)
66 {
67 throw IntVecNormalizeExc ("Cannot normalize an integer "
68 "vector unless it is parallel "
69 "to a principal axis");
70 }
71 axis = i;
72 }
73 }
74 v[axis] = (v[axis] > 0) ? 1 : -1;
75 return true;
76 }
77
78
79 template<class T>
80 bool
normalizeOrThrow(Vec3<T> & v)81 normalizeOrThrow(Vec3<T> &v)
82 {
83 int axis = -1;
84 for (int i = 0; i < 3; i ++)
85 {
86 if (v[i] != 0)
87 {
88 if (axis != -1)
89 {
90 throw IntVecNormalizeExc ("Cannot normalize an integer "
91 "vector unless it is parallel "
92 "to a principal axis");
93 }
94 axis = i;
95 }
96 }
97 v[axis] = (v[axis] > 0) ? 1 : -1;
98 return true;
99 }
100
101
102 template<class T>
103 bool
normalizeOrThrow(Vec4<T> & v)104 normalizeOrThrow(Vec4<T> &v)
105 {
106 int axis = -1;
107 for (int i = 0; i < 4; i ++)
108 {
109 if (v[i] != 0)
110 {
111 if (axis != -1)
112 {
113 throw IntVecNormalizeExc ("Cannot normalize an integer "
114 "vector unless it is parallel "
115 "to a principal axis");
116 }
117 axis = i;
118 }
119 }
120 v[axis] = (v[axis] > 0) ? 1 : -1;
121 return true;
122 }
123
124 }
125
126
127 // Vec2<short>
128
129 template <>
130 short
length() const131 Vec2<short>::length () const
132 {
133 float lenF = Math<float>::sqrt ((float)dot (*this));
134 short lenS = (short) (lenF + 0.5f);
135 return lenS;
136 }
137
138 template <>
139 const Vec2<short> &
normalize()140 Vec2<short>::normalize ()
141 {
142 normalizeOrThrow<short>(*this);
143 return *this;
144 }
145
146 template <>
147 const Vec2<short> &
normalizeExc()148 Vec2<short>::normalizeExc () throw (Iex::MathExc)
149 {
150 if ((x == 0) && (y == 0))
151 throw NullVecExc ("Cannot normalize null vector.");
152
153 normalizeOrThrow<short>(*this);
154 return *this;
155 }
156
157 template <>
158 const Vec2<short> &
normalizeNonNull()159 Vec2<short>::normalizeNonNull ()
160 {
161 normalizeOrThrow<short>(*this);
162 return *this;
163 }
164
165 template <>
166 Vec2<short>
normalized() const167 Vec2<short>::normalized () const
168 {
169 Vec2<short> v(*this);
170 normalizeOrThrow<short>(v);
171 return v;
172 }
173
174 template <>
175 Vec2<short>
normalizedExc() const176 Vec2<short>::normalizedExc () const throw (Iex::MathExc)
177 {
178 if ((x == 0) && (y == 0))
179 throw NullVecExc ("Cannot normalize null vector.");
180
181 Vec2<short> v(*this);
182 normalizeOrThrow<short>(v);
183 return v;
184 }
185
186 template <>
187 Vec2<short>
normalizedNonNull() const188 Vec2<short>::normalizedNonNull () const
189 {
190 Vec2<short> v(*this);
191 normalizeOrThrow<short>(v);
192 return v;
193 }
194
195
196 // Vec2<int>
197
198 template <>
199 int
length() const200 Vec2<int>::length () const
201 {
202 float lenF = Math<float>::sqrt ((float)dot (*this));
203 int lenI = (int) (lenF + 0.5f);
204 return lenI;
205 }
206
207 template <>
208 const Vec2<int> &
normalize()209 Vec2<int>::normalize ()
210 {
211 normalizeOrThrow<int>(*this);
212 return *this;
213 }
214
215 template <>
216 const Vec2<int> &
normalizeExc()217 Vec2<int>::normalizeExc () throw (Iex::MathExc)
218 {
219 if ((x == 0) && (y == 0))
220 throw NullVecExc ("Cannot normalize null vector.");
221
222 normalizeOrThrow<int>(*this);
223 return *this;
224 }
225
226 template <>
227 const Vec2<int> &
normalizeNonNull()228 Vec2<int>::normalizeNonNull ()
229 {
230 normalizeOrThrow<int>(*this);
231 return *this;
232 }
233
234 template <>
235 Vec2<int>
normalized() const236 Vec2<int>::normalized () const
237 {
238 Vec2<int> v(*this);
239 normalizeOrThrow<int>(v);
240 return v;
241 }
242
243 template <>
244 Vec2<int>
normalizedExc() const245 Vec2<int>::normalizedExc () const throw (Iex::MathExc)
246 {
247 if ((x == 0) && (y == 0))
248 throw NullVecExc ("Cannot normalize null vector.");
249
250 Vec2<int> v(*this);
251 normalizeOrThrow<int>(v);
252 return v;
253 }
254
255 template <>
256 Vec2<int>
normalizedNonNull() const257 Vec2<int>::normalizedNonNull () const
258 {
259 Vec2<int> v(*this);
260 normalizeOrThrow<int>(v);
261 return v;
262 }
263
264
265 // Vec3<short>
266
267 template <>
268 short
length() const269 Vec3<short>::length () const
270 {
271 float lenF = Math<float>::sqrt ((float)dot (*this));
272 short lenS = (short) (lenF + 0.5f);
273 return lenS;
274 }
275
276 template <>
277 const Vec3<short> &
normalize()278 Vec3<short>::normalize ()
279 {
280 normalizeOrThrow<short>(*this);
281 return *this;
282 }
283
284 template <>
285 const Vec3<short> &
normalizeExc()286 Vec3<short>::normalizeExc () throw (Iex::MathExc)
287 {
288 if ((x == 0) && (y == 0) && (z == 0))
289 throw NullVecExc ("Cannot normalize null vector.");
290
291 normalizeOrThrow<short>(*this);
292 return *this;
293 }
294
295 template <>
296 const Vec3<short> &
normalizeNonNull()297 Vec3<short>::normalizeNonNull ()
298 {
299 normalizeOrThrow<short>(*this);
300 return *this;
301 }
302
303 template <>
304 Vec3<short>
normalized() const305 Vec3<short>::normalized () const
306 {
307 Vec3<short> v(*this);
308 normalizeOrThrow<short>(v);
309 return v;
310 }
311
312 template <>
313 Vec3<short>
normalizedExc() const314 Vec3<short>::normalizedExc () const throw (Iex::MathExc)
315 {
316 if ((x == 0) && (y == 0) && (z == 0))
317 throw NullVecExc ("Cannot normalize null vector.");
318
319 Vec3<short> v(*this);
320 normalizeOrThrow<short>(v);
321 return v;
322 }
323
324 template <>
325 Vec3<short>
normalizedNonNull() const326 Vec3<short>::normalizedNonNull () const
327 {
328 Vec3<short> v(*this);
329 normalizeOrThrow<short>(v);
330 return v;
331 }
332
333
334 // Vec3<int>
335
336 template <>
337 int
length() const338 Vec3<int>::length () const
339 {
340 float lenF = Math<float>::sqrt ((float)dot (*this));
341 int lenI = (int) (lenF + 0.5f);
342 return lenI;
343 }
344
345 template <>
346 const Vec3<int> &
normalize()347 Vec3<int>::normalize ()
348 {
349 normalizeOrThrow<int>(*this);
350 return *this;
351 }
352
353 template <>
354 const Vec3<int> &
normalizeExc()355 Vec3<int>::normalizeExc () throw (Iex::MathExc)
356 {
357 if ((x == 0) && (y == 0) && (z == 0))
358 throw NullVecExc ("Cannot normalize null vector.");
359
360 normalizeOrThrow<int>(*this);
361 return *this;
362 }
363
364 template <>
365 const Vec3<int> &
normalizeNonNull()366 Vec3<int>::normalizeNonNull ()
367 {
368 normalizeOrThrow<int>(*this);
369 return *this;
370 }
371
372 template <>
373 Vec3<int>
normalized() const374 Vec3<int>::normalized () const
375 {
376 Vec3<int> v(*this);
377 normalizeOrThrow<int>(v);
378 return v;
379 }
380
381 template <>
382 Vec3<int>
normalizedExc() const383 Vec3<int>::normalizedExc () const throw (Iex::MathExc)
384 {
385 if ((x == 0) && (y == 0) && (z == 0))
386 throw NullVecExc ("Cannot normalize null vector.");
387
388 Vec3<int> v(*this);
389 normalizeOrThrow<int>(v);
390 return v;
391 }
392
393 template <>
394 Vec3<int>
normalizedNonNull() const395 Vec3<int>::normalizedNonNull () const
396 {
397 Vec3<int> v(*this);
398 normalizeOrThrow<int>(v);
399 return v;
400 }
401
402
403 // Vec4<short>
404
405 template <>
406 short
length() const407 Vec4<short>::length () const
408 {
409 float lenF = Math<float>::sqrt ((float)dot (*this));
410 short lenS = (short) (lenF + 0.5f);
411 return lenS;
412 }
413
414 template <>
415 const Vec4<short> &
normalize()416 Vec4<short>::normalize ()
417 {
418 normalizeOrThrow<short>(*this);
419 return *this;
420 }
421
422 template <>
423 const Vec4<short> &
normalizeExc()424 Vec4<short>::normalizeExc () throw (Iex::MathExc)
425 {
426 if ((x == 0) && (y == 0) && (z == 0) && (w == 0))
427 throw NullVecExc ("Cannot normalize null vector.");
428
429 normalizeOrThrow<short>(*this);
430 return *this;
431 }
432
433 template <>
434 const Vec4<short> &
normalizeNonNull()435 Vec4<short>::normalizeNonNull ()
436 {
437 normalizeOrThrow<short>(*this);
438 return *this;
439 }
440
441 template <>
442 Vec4<short>
normalized() const443 Vec4<short>::normalized () const
444 {
445 Vec4<short> v(*this);
446 normalizeOrThrow<short>(v);
447 return v;
448 }
449
450 template <>
451 Vec4<short>
normalizedExc() const452 Vec4<short>::normalizedExc () const throw (Iex::MathExc)
453 {
454 if ((x == 0) && (y == 0) && (z == 0) && (w == 0))
455 throw NullVecExc ("Cannot normalize null vector.");
456
457 Vec4<short> v(*this);
458 normalizeOrThrow<short>(v);
459 return v;
460 }
461
462 template <>
463 Vec4<short>
normalizedNonNull() const464 Vec4<short>::normalizedNonNull () const
465 {
466 Vec4<short> v(*this);
467 normalizeOrThrow<short>(v);
468 return v;
469 }
470
471
472 // Vec4<int>
473
474 template <>
475 int
length() const476 Vec4<int>::length () const
477 {
478 float lenF = Math<float>::sqrt ((float)dot (*this));
479 int lenI = (int) (lenF + 0.5f);
480 return lenI;
481 }
482
483 template <>
484 const Vec4<int> &
normalize()485 Vec4<int>::normalize ()
486 {
487 normalizeOrThrow<int>(*this);
488 return *this;
489 }
490
491 template <>
492 const Vec4<int> &
normalizeExc()493 Vec4<int>::normalizeExc () throw (Iex::MathExc)
494 {
495 if ((x == 0) && (y == 0) && (z == 0) && (w == 0))
496 throw NullVecExc ("Cannot normalize null vector.");
497
498 normalizeOrThrow<int>(*this);
499 return *this;
500 }
501
502 template <>
503 const Vec4<int> &
normalizeNonNull()504 Vec4<int>::normalizeNonNull ()
505 {
506 normalizeOrThrow<int>(*this);
507 return *this;
508 }
509
510 template <>
511 Vec4<int>
normalized() const512 Vec4<int>::normalized () const
513 {
514 Vec4<int> v(*this);
515 normalizeOrThrow<int>(v);
516 return v;
517 }
518
519 template <>
520 Vec4<int>
normalizedExc() const521 Vec4<int>::normalizedExc () const throw (Iex::MathExc)
522 {
523 if ((x == 0) && (y == 0) && (z == 0) && (w == 0))
524 throw NullVecExc ("Cannot normalize null vector.");
525
526 Vec4<int> v(*this);
527 normalizeOrThrow<int>(v);
528 return v;
529 }
530
531 template <>
532 Vec4<int>
normalizedNonNull() const533 Vec4<int>::normalizedNonNull () const
534 {
535 Vec4<int> v(*this);
536 normalizeOrThrow<int>(v);
537 return v;
538 }
539
540 } // namespace Imath
541