Home | History | Annotate | Download | only in Imath
      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 #ifndef INCLUDED_IMATHPLANE_H
     38 #define INCLUDED_IMATHPLANE_H
     39 
     40 //----------------------------------------------------------------------
     41 //
     42 //	template class Plane3
     43 //
     44 //	The Imath::Plane3<> class represents a half space, so the
     45 //	normal may point either towards or away from origin.  The
     46 //	plane P can be represented by Imath::Plane3 as either p or -p
     47 //	corresponding to the two half-spaces on either side of the
     48 //	plane. Any function which computes a distance will return
     49 //	either negative or positive values for the distance indicating
     50 //	which half-space the point is in. Note that reflection, and
     51 //	intersection functions will operate as expected.
     52 //
     53 //----------------------------------------------------------------------
     54 
     55 #include "ImathVec.h"
     56 #include "ImathLine.h"
     57 
     58 namespace Imath {
     59 
     60 
     61 template <class T>
     62 class Plane3
     63 {
     64   public:
     65 
     66     Vec3<T>			normal;
     67     T				distance;
     68 
     69     Plane3() {}
     70     Plane3(const Vec3<T> &normal, T distance);
     71     Plane3(const Vec3<T> &point, const Vec3<T> &normal);
     72     Plane3(const Vec3<T> &point1,
     73        const Vec3<T> &point2,
     74        const Vec3<T> &point3);
     75 
     76     //----------------------
     77     //	Various set methods
     78     //----------------------
     79 
     80     void                        set(const Vec3<T> &normal,
     81                     T distance);
     82 
     83     void                        set(const Vec3<T> &point,
     84                     const Vec3<T> &normal);
     85 
     86     void                        set(const Vec3<T> &point1,
     87                     const Vec3<T> &point2,
     88                     const Vec3<T> &point3 );
     89 
     90     //----------------------
     91     //	Utilities
     92     //----------------------
     93 
     94     bool                        intersect(const Line3<T> &line,
     95                                           Vec3<T> &intersection) const;
     96 
     97     bool                        intersectT(const Line3<T> &line,
     98                        T &parameter) const;
     99 
    100     T				distanceTo(const Vec3<T> &) const;
    101 
    102     Vec3<T>                     reflectPoint(const Vec3<T> &) const;
    103     Vec3<T>                     reflectVector(const Vec3<T> &) const;
    104 };
    105 
    106 
    107 //--------------------
    108 // Convenient typedefs
    109 //--------------------
    110 
    111 typedef Plane3<float> Plane3f;
    112 typedef Plane3<double> Plane3d;
    113 
    114 
    115 //---------------
    116 // Implementation
    117 //---------------
    118 
    119 template <class T>
    120 inline Plane3<T>::Plane3(const Vec3<T> &p0,
    121              const Vec3<T> &p1,
    122              const Vec3<T> &p2)
    123 {
    124     set(p0,p1,p2);
    125 }
    126 
    127 template <class T>
    128 inline Plane3<T>::Plane3(const Vec3<T> &n, T d)
    129 {
    130     set(n, d);
    131 }
    132 
    133 template <class T>
    134 inline Plane3<T>::Plane3(const Vec3<T> &p, const Vec3<T> &n)
    135 {
    136     set(p, n);
    137 }
    138 
    139 template <class T>
    140 inline void Plane3<T>::set(const Vec3<T>& point1,
    141                const Vec3<T>& point2,
    142                const Vec3<T>& point3)
    143 {
    144     normal = (point2 - point1) % (point3 - point1);
    145     normal.normalize();
    146     distance = normal ^ point1;
    147 }
    148 
    149 template <class T>
    150 inline void Plane3<T>::set(const Vec3<T>& point, const Vec3<T>& n)
    151 {
    152     normal = n;
    153     normal.normalize();
    154     distance = normal ^ point;
    155 }
    156 
    157 template <class T>
    158 inline void Plane3<T>::set(const Vec3<T>& n, T d)
    159 {
    160     normal = n;
    161     normal.normalize();
    162     distance = d;
    163 }
    164 
    165 template <class T>
    166 inline T Plane3<T>::distanceTo(const Vec3<T> &point) const
    167 {
    168     return (point ^ normal) - distance;
    169 }
    170 
    171 template <class T>
    172 inline Vec3<T> Plane3<T>::reflectPoint(const Vec3<T> &point) const
    173 {
    174     return normal * distanceTo(point) * -2.0 + point;
    175 }
    176 
    177 
    178 template <class T>
    179 inline Vec3<T> Plane3<T>::reflectVector(const Vec3<T> &v) const
    180 {
    181     return normal * (normal ^ v)  * 2.0 - v;
    182 }
    183 
    184 
    185 template <class T>
    186 inline bool Plane3<T>::intersect(const Line3<T>& line, Vec3<T>& point) const
    187 {
    188     T d = normal ^ line.dir;
    189     if ( d == 0.0 ) return false;
    190     T t = - ((normal ^ line.pos) - distance) /  d;
    191     point = line(t);
    192     return true;
    193 }
    194 
    195 template <class T>
    196 inline bool Plane3<T>::intersectT(const Line3<T>& line, T &t) const
    197 {
    198     T d = normal ^ line.dir;
    199     if ( d == 0.0 ) return false;
    200     t = - ((normal ^ line.pos) - distance) /  d;
    201     return true;
    202 }
    203 
    204 template<class T>
    205 std::ostream &operator<< (std::ostream &o, const Plane3<T> &plane)
    206 {
    207     return o << "(" << plane.normal << ", " << plane.distance
    208          << ")";
    209 }
    210 
    211 template<class T>
    212 Plane3<T> operator* (const Plane3<T> &plane, const Matrix44<T> &M)
    213 {
    214     //                        T
    215     //	                    -1
    216     //	Could also compute M    but that would suck.
    217     //
    218 
    219     Vec3<T> dir1   = Vec3<T> (1, 0, 0) % plane.normal;
    220     T dir1Len      = dir1 ^ dir1;
    221 
    222     Vec3<T> tmp    = Vec3<T> (0, 1, 0) % plane.normal;
    223     T tmpLen       = tmp ^ tmp;
    224 
    225     if (tmpLen > dir1Len)
    226     {
    227     dir1      = tmp;
    228     dir1Len   = tmpLen;
    229     }
    230 
    231     tmp            = Vec3<T> (0, 0, 1) % plane.normal;
    232     tmpLen         = tmp ^ tmp;
    233 
    234     if (tmpLen > dir1Len)
    235     {
    236     dir1      = tmp;
    237     }
    238 
    239     Vec3<T> dir2   = dir1 % plane.normal;
    240     Vec3<T> point  = plane.distance * plane.normal;
    241 
    242     return Plane3<T> ( point         * M,
    243               (point + dir2) * M,
    244               (point + dir1) * M );
    245 }
    246 
    247 template<class T>
    248 Plane3<T> operator- (const Plane3<T> &plane)
    249 {
    250     return Plane3<T>(-plane.normal,-plane.distance);
    251 }
    252 
    253 
    254 } // namespace Imath
    255 
    256 #endif
    257