00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef __SGL_PLANE_HPP
00026 #define __SGL_PLANE_HPP
00027
00028 #include <assert.h>
00029 #include <sgl.h>
00030 #include <sglVector.hpp>
00031 #include <sglMatrix.hpp>
00032
00033
00034
00035
00036
00037 template <class T> class sglPlane;
00038
00039 typedef sglPlane<float> sglPlanef;
00040 typedef sglPlane<double> sglPlaned;
00041
00042
00043 template <class T>
00044 class sglPlane
00045 {
00046 public:
00047 sglPlane() {};
00048 sglPlane(const sglPlane &rhs) :
00049 m_normal(rhs.m_normal), m_distance(rhs.m_distance) {};
00050
00051 sglPlane(const sglVec3<T> &n, T d) :
00052 m_normal(n), m_distance(d) { normalize(); }
00053
00054 sglPlane(T x, T y, T z, T d) :
00055 m_normal(x,y,z), m_distance(d) { normalize(); }
00056
00057 ~sglPlane() {};
00058
00059 #ifndef WIN32
00060 inline sglPlane& operator=(const sglPlane &rhs)
00061 {
00062 if (this != &rhs)
00063 {
00064 m_normal = rhs.m_normal;
00065 m_distance = rhs.m_distance;
00066 }
00067 return *this;
00068 }
00069 #endif
00070
00071 template <class S>
00072 inline sglPlane<T>& operator=(const sglPlane<S> &rhs)
00073 {
00074 if (this != (sglPlane<T>*) &rhs)
00075 {
00076 m_normal = rhs.getNormal();
00077 m_distance = rhs.getDistance();
00078 }
00079 return *this;
00080 }
00081
00082 template <class S>
00083 inline void set(const sglVec3<S>& normal, T distance)
00084 {
00085 m_normal = normal; m_distance = distance; normalize();
00086 }
00087 inline const sglVec3<T>& getNormal() const { return m_normal; }
00088 inline T getDistance() const { return m_distance; }
00089
00090
00091 inline void normalize()
00092 {
00093 T len = m_normal.normalize();
00094 m_distance *= (1.0/len);
00095 }
00096
00097
00098
00099 bool build(const sglVec3<T>& p1,
00100 const sglVec3<T>& p2,
00101 const sglVec3<T>& p3);
00102
00103
00104 bool getVertices(sglVec3<T>& p1, sglVec3<T>& p2, sglVec3<T>& p3) const;
00105
00106
00107 template <class S>
00108 inline void mul(const sglPlane<T>& p, const sglMat3<S>& m)
00109 {
00110 ::mulTranspose(p.getNormal(), m, m_normal);
00111 m_distance = p.getDistance();
00112 }
00113
00114
00115 template <class S>
00116 void mul(const sglPlane<T>& p, const sglMat4<S>& m)
00117 {
00118
00119 sglVec4<T> normal;
00120 ::mul(p.getNormal(), (T)0, m, normal);
00121 T zoom = normal.normalize();
00122
00123
00124 sglVec3<T> translation(m[3][0],m[3][1],m[3][2]);
00125 translation *= (1.0/zoom);
00126 m_distance = p.getDistance() - (normal[0]*translation[0] +
00127 normal[1]*translation[1] +
00128 normal[2]*translation[2]);
00129 m_distance *= zoom;
00130 m_normal.set(normal[0], normal[1], normal[2]);
00131 }
00132
00133
00134 void translate(const sglPlane<T>& p, T x, T y, T z)
00135 {
00136 m_normal = p.getNormal();
00137
00138 m_distance = p.getDistance() - (m_normal[0]*x +
00139 m_normal[1]*y +
00140 m_normal[2]*z);
00141 }
00142
00143
00144 void scale(const sglPlane<T>& p, T scale)
00145 {
00146 m_normal = p.getNormal();
00147 m_distance = p.getDistance()*scale;
00148 }
00149
00150
00151 template <class S>
00152 void rotate(const sglPlane<T>& p, const sglMat4<S>& m)
00153 {
00154 sglVec4<T> normal;
00155 ::mul(p.getNormal(), (T)0, m, normal);
00156 T zoom = normal.normalize();
00157
00158 m_distance = p.getDistance()*zoom;
00159 m_normal.set(normal[0], normal[1], normal[2]);
00160 }
00161 template <class S>
00162 void rotate(const sglPlane<T>& p, const sglMat3<S>& m)
00163 {
00164 sglVec3<T> normal;
00165 ::mul(p.getNormal(), m, normal);
00166 T zoom = normal.normalize();
00167
00168 m_distance = p.getDistance()*zoom;
00169 m_normal = normal;
00170 }
00171
00172
00173 template <class S>
00174 inline float signedDistance(const sglVec3<S>& p) const
00175 {
00176 return m_normal.dot(p) + m_distance;
00177 }
00178
00179 friend ostream& operator<<(ostream& ostrm, const sglPlane<T>& p)
00180 {
00181 return (ostrm << "[" << p.getNormal() << ", "
00182 << p.getDistance() << "]");
00183 }
00184
00185 private:
00186 sglVec3<T> m_normal;
00187 T m_distance;
00188 };
00189
00190
00191
00192
00193
00194
00195 template <class T>
00196 inline bool sglPlane<T>::build(const sglVec3<T>& p1,
00197 const sglVec3<T>& p2,
00198 const sglVec3<T>& p3)
00199 {
00200 sglVec3<T> v1,v2;
00201 v1.sub(p1,p2);
00202 v2.sub(p3,p2);
00203
00204 m_normal.cross(v1,v2);
00205 float d = m_normal.normalize();
00206 if (d == 0.f)
00207 return false;
00208
00209
00210 m_distance = -(m_normal.dot(p2));
00211
00212 return true;
00213 }
00214
00215
00216
00217
00218
00219
00220 template <class T>
00221 inline bool sglPlane<T>::getVertices(sglVec3<T>& pnt1,
00222 sglVec3<T>& pnt2,
00223 sglVec3<T>& pnt3) const
00224 {
00225
00226 sglVec3<T> p1,p2,p3;
00227
00228 int index = 0;
00229 float max = SGL_ABS(m_normal[index]);
00230 if (SGL_ABS(m_normal[1]) > max)
00231 {
00232 index = 1;
00233 max = SGL_ABS(m_normal[index]);
00234 }
00235 if (SGL_ABS(m_normal[2]) > max)
00236 {
00237 index = 2;
00238 }
00239
00240 p2.set(((index == 0) ? (-m_distance/m_normal[0]) : 0),
00241 ((index == 1) ? (-m_distance/m_normal[1]) : 0),
00242 ((index == 2) ? (-m_distance/m_normal[2]) : 0));
00243
00244
00245 sglVec3<T> temp(((index == 0) ? 0 : 1),
00246 ((index == 1) ? 0 : 1),
00247 ((index == 2) ? 0 : 1));
00248
00249 p1.cross(m_normal,temp);
00250 p3.cross(m_normal,p1);
00251
00252 temp.cross(p1,p3);
00253
00254 p1 += p2;
00255 p3 += p2;
00256
00257
00258 sglPlane<T> testplane;
00259 testplane.build(p1,p2,p3);
00260
00261 sglVec3<T> n = testplane.getNormal();
00262 if (n[0]*m_normal[0] < 0)
00263 {
00264 pnt1 = p3;
00265 pnt2 = p2;
00266 pnt3 = p1;
00267 }
00268 else
00269 {
00270 pnt1 = p1;
00271 pnt2 = p2;
00272 pnt3 = p3;
00273 }
00274 return true;
00275 }
00276
00277 #endif