00001 #include <math.h>
00002 #include <math/math2.h>
00003
00004 #include "geometry\MPK_Sphere.h"
00005 #include "geometry\MPK_Segment.h"
00006
00007 namespace MPK
00008 {
00009
00010
00011 Segment::Segment (FrameManager* frameManager)
00012
00013
00014
00015 :ObjectBase( frameManager )
00016
00017 {
00018
00019
00020 }
00021
00022 Segment::Segment (const Segment& right)
00023
00024
00025
00026 :ObjectBase( right ),
00027 startPos( right.startPos ),
00028 endPos( right.endPos )
00029
00030
00031 {
00032
00033
00034 }
00035
00036
00037 Segment::~Segment()
00038 {
00039
00040
00041 }
00042
00043
00044
00045
00046 Entity* Segment::Clone () const
00047 {
00048
00049 ObjectBase* returnme = new Segment( *this ) ;
00050 return returnme ;
00051
00052 }
00053
00054 bool Segment::IsInterfering (const Entity* entity) const
00055 {
00056
00057 assert( CanCheckInterference( entity ) ) ;
00058
00059
00060 if( dynamic_cast< const Segment* >( entity ) != NULL )
00061 {
00062 return( IsInterfering( dynamic_cast< const Segment* >( entity ) ) ) ;
00063 }
00064 else if( dynamic_cast< const MPK_Sphere* >( entity ) != NULL )
00065 {
00066 return( IsInterfering( dynamic_cast< const MPK_Sphere* >( entity ) ) ) ; ;
00067 }
00068 else
00069 {
00070 assert( false ) ;
00071
00072 }
00073 return false ;
00074
00075
00076 }
00077
00078 bool Segment::CanCheckInterference (const Entity* entity) const
00079 {
00080
00081
00082 if( dynamic_cast< const Segment* >( entity ) != NULL )
00083 {
00084 return true ;
00085 }
00086 if( dynamic_cast< const MPK_Sphere* >( entity ) != NULL )
00087 {
00088 return true ;
00089 }
00090 return false ;
00091
00092
00093 }
00094
00095 bool Segment::IsInterfering (const Segment* entity) const
00096 {
00097
00098 Matrix4x4 relative = frameManager->GetTransformRelative( baseFrame, entity->baseFrame );
00099 Vector4 p1 = startPos ;
00100 Vector4 v1 = endPos - startPos ;
00101 double& v1x = v1[ 0 ] ;
00102 double& v1y = v1[ 1 ] ;
00103 double& v1z = v1[ 2 ] ;
00104
00105 Vector4 q1 = entity->startPos ;
00106 Vector4 q2 = entity->endPos ;
00107 q1 = relative * q1 ;
00108 q2 = relative * q2 ;
00109
00110 Vector4 p2 = q1 ;
00111 Vector4 v2 = q2 - q1 ;
00112 double& v2x = v2[ 0 ] ;
00113 double& v2y = v2[ 1 ] ;
00114 double& v2z = v2[ 2 ] ;
00115
00116 Vector4 p = p2 - p1 ;
00117 Vector4 d = v1.Cross( v2 ) ;
00118
00119 double& px = p[ 0 ] ;
00120 double& py = p[ 1 ] ;
00121 double& pz = p[ 2 ] ;
00122 double& dx = d[ 0 ] ;
00123 double& dy = d[ 1 ] ;
00124 double& dz = d[ 2 ] ;
00125
00126 double magSquared = d.MagSquared() ;
00127 if( magSquared == 0 )
00128 {
00129
00130
00131
00132 Vector4 endPoints = startPos - entity->startPos ;
00133 if( endPoints.Projection( v1 ).MagSquared() != v1.MagSquared() )
00134 {
00135
00136 return false ;
00137 }
00138
00139 double a1 = startPos.ProjectionMag( v1 ) ;
00140 double a2 = endPos.ProjectionMag( v1 ) ;
00141 double b1 = entity->startPos.ProjectionMag( v1 ) ;
00142 double b2 = entity->endPos.ProjectionMag( v1 ) ;
00143
00144
00145 if( Between( a1, b1, b2 ) ) { return true ; }
00146 if( Between( a2, b1, b2 ) ) { return true ; }
00147
00148
00149 if( Between( b1, a1, a2 ) ) { return true ; }
00150 if( Between( b2, a1, a2 ) ) { return true ; }
00151 return false ;
00152 }
00153
00154
00155 double t = ( px * v2y * dz ) + ( v2x * dy * pz ) + ( dx * py * v2z )
00156 - ( dx * v2y * pz ) - ( dy * v2z * px ) - ( dz * v2x * py );
00157 t /= magSquared ;
00158 if( t < 0 )
00159 {
00160 return false ;
00161 }
00162 if( t > 1 )
00163 {
00164 return false ;
00165 }
00166
00167 double s = ( px * v1y * dz ) + ( v1x * dy * pz ) + ( dx * py * v1z )
00168 - ( dx * v1y * pz ) - ( dy * v1z * px ) - ( dz * v1x * py );
00169 s /= magSquared ;
00170 if( s < 0 )
00171 {
00172 return false ;
00173 }
00174 if( s > 1 )
00175 {
00176 return false ;
00177 }
00178
00179 assert( ( p1 + v1 * t ) == ( p2 + v2 * s ) ) ;
00180 return true ;
00181
00182 }
00183
00184 void Segment::SetStart (const Vector4& start)
00185 {
00186
00187 startPos = start ;
00188
00189 }
00190
00191 void Segment::SetEnd (const Vector4& end)
00192 {
00193
00194 endPos = end ;
00195
00196 }
00197
00198 bool Segment::IsInterfering (const MPK_Sphere* entity) const
00199 {
00200
00201
00202 Matrix4x4 r1 = frameManager->GetTransformRelative( baseFrame, 0 );
00203 Matrix4x4 r2 = frameManager->GetTransformRelative( entity->BaseFrame(), 0 );
00204 Matrix4x4 relative = r1.Inverse() * r2 ;
00205
00206 Vector4 center = entity->Position() ;
00207 center = relative * center ;
00208 Vector4 g = startPos - center ;
00209 Vector4 lv = endPos - startPos ;
00210 double a = lv.Dot( lv ) ;
00211 double b = 2 * ( lv.Dot( g ) ) ;
00212 double c = ( g.Dot( g ) - pow( entity->Radius(), 2 ) ) ;
00213 double d = pow( b, 2 ) - 4 * a * c ;
00214 if( d < 0 )
00215 {
00216 return false ;
00217 }
00218
00219 assert( ( 2 * a ) != 0 ) ;
00220 double p1 = ( -b + sqrt( d ) ) / ( 2 * a ) ;
00221 double p2 = ( -b - sqrt( d ) ) / ( 2 * a ) ;
00222 if( Between( p1, 0.0, 1.0 ) )
00223 {
00224 return true ;
00225 }
00226 if( Between( p2, 0.0, 1.0 ) )
00227 {
00228 return true ;
00229 }
00230 if( Between( 0.0, p1, p2 ) )
00231 {
00232 return true ;
00233 }
00234 assert( !Between( 1.0, p1, p2 ) ) ;
00235 return false ;
00236
00237 }
00238
00239 void Segment::Deserialize (istream& is)
00240 {
00241
00242 assert( false );
00243
00244 }
00245
00246 void Segment::Serialize (ostream& os) const
00247 {
00248
00249 assert( false );
00250
00251 }
00252
00253
00254 bool Segment::Verify() const
00255 {
00256 return true;
00257 }
00258
00259
00260
00261
00262
00263
00264 }