00001 #include "Common/Assert.h"
00002 #include "Common/Error.h"
00003 #include "Common/Console.h"
00004 #include "Common/Vector.h"
00005 #include "Common/Matrix.h"
00006 #include "Common/Point.h"
00007 #include "Common/Plane.h"
00008
00009 #include "Common/Math3D.h"
00010
00011 #define EPSILON 0.1f
00012 #define COLL_TEST_CULL
00013
00014
00015 void GetLocalAngleFromNormal( KVector& Normal, float& AngleX, float& AngleY, float& AngleZ )
00016 {
00017
00018 if( ( Normal.y > -0.001f ) && ( Normal.y < 0.001f ) )
00019 if( ( Normal.z > -0.001f ) && ( Normal.z < 0.001f ) )
00020 AngleX = 0.0f;
00021 else
00022 if( Normal.z > 0.0f )
00023 AngleX = PI / 2.0f;
00024 else
00025 AngleX = 3.0f * PI / 2.0f;
00026 else
00027 if( Normal.y > 0.0f )
00028 AngleX = atanf( Normal.z / Normal.y );
00029 else
00030 AngleX = atanf( Normal.z / Normal.y ) + PI;
00031
00032 AngleX = fmodf( AngleX + 2.0f * PI, 2.0f * PI );
00033
00034
00035 AngleY = 0.0f;
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 if( ( Normal.x > -0.001f ) && ( Normal.x < 0.001f ) )
00057 if( ( Normal.y > -0.001f ) && ( Normal.y < 0.001f ) )
00058 AngleZ = 0.0f;
00059 else
00060 if( Normal.y > 0.0f )
00061 AngleZ = PI / 2.0f;
00062 else
00063 AngleZ = 3.0f * PI / 2.0f;
00064 else
00065 if( Normal.x > 0.0f )
00066 AngleZ = atanf( Normal.y / Normal.x );
00067 else
00068 AngleZ = atanf( Normal.y / Normal.x ) + PI;
00069
00070 AngleZ -= PI / 2.0f;
00071 AngleZ = fmodf( AngleZ + 2.0f * PI, 2.0f * PI );
00072
00073 KVector NormalZ = Normal;
00074
00075 NormalZ.x = Normal.x * cosf( -AngleZ ) + Normal.y * -sinf( -AngleZ );
00076 NormalZ.y = Normal.x * sinf( -AngleZ ) + Normal.y * cosf( -AngleZ );
00077 NormalZ.z = Normal.z;
00078
00079
00080 if( ( NormalZ.y > -0.001f ) && ( NormalZ.y < 0.001f ) )
00081 if( ( NormalZ.z > -0.001f ) && ( NormalZ.z < 0.001f ) )
00082 AngleX = 0.0f;
00083 else
00084 if( NormalZ.z > 0.0f )
00085 AngleX = PI / 2.0f;
00086 else
00087 AngleX = 3.0f * PI / 2.0f;
00088 else
00089 if( NormalZ.y > 0.0f )
00090 AngleX = atanf( NormalZ.z / NormalZ.y );
00091 else
00092 AngleX = atanf( NormalZ.z / NormalZ.y ) + PI;
00093
00094 AngleX = fmodf( AngleX + 2.0f * PI, 2.0f * PI );
00095 }
00096
00097
00098 bool IntersectTriangle( KVector& orig, KVector& dir, KVector& v0, KVector& v1, KVector& v2, float* t, float* u, float* v )
00099 {
00100
00101 KVector edge1 = v1 - v0;
00102 KVector edge2 = v2 - v0;
00103
00104
00105 KVector pvec;
00106 pvec = KVector::CrossProduct( dir, edge2 );
00107
00108 KVector Normal = KVector::CrossProduct( edge1, edge2 );
00109 Normal.Normalize();
00110 KPlane Plane( Normal, KVector::DotProduct( Normal, v0 ) );
00111
00112 float fOrig = KVector::DotProduct( Plane.m_Normal, orig ) - Plane.m_Distance;
00113 float fDir = KVector::DotProduct( Plane.m_Normal, orig + dir ) - Plane.m_Distance;
00114
00115
00116
00117
00118
00119
00120
00121
00122 if( ( ( fOrig > 0.0f ) && ( fDir > 0.0f ) ) || ( ( fOrig < 0.0f ) && ( fDir < 0.0f ) ) )
00123 return false;
00124
00125
00126
00127
00128 float det = KVector::DotProduct( edge1, pvec );
00129
00130 #ifdef COLL_TEST_CULL
00131
00132 if( det < EPSILON )
00133 return false;
00134
00135
00136 KVector tvec = orig - v0;
00137
00138
00139 *u = KVector::DotProduct( tvec, pvec );
00140 if( *u < 0.0f || *u > det )
00141 return false;
00142
00143
00144 KVector qvec;
00145 qvec = KVector::CrossProduct( tvec, edge1 );
00146
00147
00148 *v = KVector::DotProduct( dir, qvec );
00149 if( *v < 0.0f || *u + *v > det )
00150 return false;
00151
00152
00153 *t = KVector::DotProduct( edge2, qvec );
00154 float fInvDet = 1.0f / det;
00155 *t *= fInvDet;
00156 *u *= fInvDet;
00157 *v *= fInvDet;
00158
00159
00160
00161
00162
00163
00164
00165 #else
00166
00167 if ((det > -EPSILON) && (det < EPSILON))
00168 return false;
00169
00170 float inv_det = 1.0f / det;
00171
00172
00173 KVector tvec = orig - v0;
00174
00175
00176 *u = KVector::DotProduct( tvec, pvec ) * inv_det;
00177
00178 if ((*u < 0.0f) || (*u > 1.0f))
00179 return false;
00180
00181
00182 KVector qvec = KVector::CrossProduct( tvec, edge1 );
00183
00184
00185 *v = KVector::DotProduct( dir, qvec ) * inv_det;
00186
00187 if ((*v < 0.0f) || ((*u + *v) > 1.0f))
00188 return false;
00189
00190
00191 *t = KVector::DotProduct( edge2, qvec ) * inv_det;
00192
00193 #endif
00194
00195 return true;
00196 }
00197
00198
00199 bool IntersectTriangleCullNone( KVector& orig, KVector& dir, KVector& v0, KVector& v1, KVector& v2, float* t, float* u, float* v )
00200 {
00201
00202 KVector edge1 = v1 - v0;
00203 KVector edge2 = v2 - v0;
00204
00205
00206 KVector pvec;
00207 pvec = KVector::CrossProduct( dir, edge2 );
00208
00209
00210 float det = KVector::DotProduct( edge1, pvec );
00211
00212 if ((det > -EPSILON) && (det < EPSILON))
00213 return false;
00214
00215 float inv_det = 1.0f / det;
00216
00217
00218 KVector tvec = orig - v0;
00219
00220
00221 *u = KVector::DotProduct( tvec, pvec ) * inv_det;
00222
00223 if ((*u < 0.0f) || (*u > 1.0f))
00224 return false;
00225
00226
00227 KVector qvec = KVector::CrossProduct( tvec, edge1 );
00228
00229
00230 *v = KVector::DotProduct( dir, qvec ) * inv_det;
00231
00232 if ((*v < 0.0f) || ((*u + *v) > 1.0f))
00233 return false;
00234
00235
00236 *t = KVector::DotProduct( edge2, qvec ) * inv_det;
00237
00238 return true;
00239 }
00240
00241
00242
00243 bool IntersectTriangle( KVector& center, float radius, KVector& v0, KVector& v1, KVector& v2, KVector* pPoint )
00244 {
00245
00246 KVector edge1 = v1 - v0;
00247 KVector edge2 = v2 - v0;
00248 KVector edge3 = v1 - v2;
00249
00250 KVector Normal = KVector::CrossProduct( edge1, edge2 );
00251 Normal.Normalize();
00252 KPlane Plane( Normal, KVector::DotProduct( Normal, v0 ) );
00253
00254 float fDist = (KVector::DotProduct( Plane.m_Normal, center ) - Plane.m_Distance);
00255
00256
00257 if( fDist > radius )
00258 return false;
00259
00260 if( fDist < 0.0f )
00261 return false;
00262
00263
00264
00265
00266 *pPoint = center + Normal * -fDist;
00267
00268
00269 KVector ve1 = KVector::CrossProduct( Normal, v1 - v0 );
00270 ve1.Normalize();
00271 KPlane Plane1( ve1, KVector::DotProduct( ve1, v0 ) );
00272 float d1 = KVector::DotProduct( Plane1.m_Normal, *pPoint ) - Plane1.m_Distance;
00273 if( d1 < 0.0f )
00274 return false;
00275
00276
00277 KVector ve2 = KVector::CrossProduct( Normal, v0 - v2 );
00278 ve2.Normalize();
00279 KPlane Plane2( ve2, KVector::DotProduct( ve2, v0 ) );
00280 float d2 = KVector::DotProduct( Plane2.m_Normal, *pPoint ) - Plane2.m_Distance;
00281 if( d2 < 0.0f )
00282 return false;
00283
00284
00285 KVector ve3 = KVector::CrossProduct( Normal, v2 - v1 );
00286 ve3.Normalize();
00287 KPlane Plane3( ve3, KVector::DotProduct( ve3, v1 ) );
00288 float d3 = KVector::DotProduct( Plane3.m_Normal, *pPoint ) - Plane3.m_Distance;
00289 if( d3 < 0.0f )
00290 return false;
00291
00292 return true;
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 }
00327
00328
00329 void ComputePickVector( KMatrix& MatProj, KMatrix& MatView, KPt& PickPoint, KPt& ViewportSize, KVector* PickRayOrig, KVector* PickRayDir )
00330 {
00331
00332 KVector v;
00333 v.x = ( ( ( 2.0f * PickPoint.x ) / ViewportSize.x ) - 1 ) / MatProj._11;
00334 v.y = -( ( ( 2.0f * PickPoint.y ) / ViewportSize.y ) - 1 ) / MatProj._22;
00335 v.z = 1.0f;
00336
00337
00338 KMatrix m = MatView;
00339 m.Inverse();
00340
00341
00342
00343 PickRayDir->x = v.x * m._11 + v.y * m._21 + v.z * m._31;
00344 PickRayDir->y = v.x * m._12 + v.y * m._22 + v.z * m._32;
00345 PickRayDir->z = v.x * m._13 + v.y * m._23 + v.z * m._33;
00346 PickRayOrig->x = m._41;
00347 PickRayOrig->y = m._42;
00348 PickRayOrig->z = m._43;
00349 }
00350
00351
00352
00353
00354
00355 KVector ClosestPointOnLine( KVector& Point, KVector& v0, KVector& v1 )
00356 {
00357 KVector c = Point - v0;
00358 KVector V = v1 - v0;
00359 float d = V.Magnitude();
00360
00361 V.Normalize();
00362 float t = KVector::DotProduct( V, c );
00363
00364 if( t < 0.0f ) return v0;
00365 if( t > d ) return v1;
00366
00367 V *= t;
00368
00369 return v0 + V;
00370 }
00371
00372
00373 KVector ClosestPointOnTriangle( KVector& Point, KVector& v0, KVector& v1, KVector& v2 )
00374 {
00375 KVector r01 = ClosestPointOnLine( Point, v0, v1 );
00376 KVector r12 = ClosestPointOnLine( Point, v1, v2 );
00377 KVector r20 = ClosestPointOnLine( Point, v2, v0 );
00378 KVector m01 = Point - r01;
00379 KVector m12 = Point - r12;
00380 KVector m20 = Point - r20;
00381
00382 float d01 = m01.Magnitude();
00383 float d12 = m12.Magnitude();
00384 float d20 = m20.Magnitude();
00385
00386 float min = d01;
00387 KVector Result = r01;
00388
00389 if( d12 < min )
00390 {
00391 min = d12;
00392 Result = r12;
00393 }
00394
00395 if( d20 < min )
00396 Result = r20;
00397
00398 return Result;
00399 }
00400
00401
00402 bool CheckPointInTriangle( KVector& Point, KVector& v0, KVector& v1, KVector& v2 )
00403 {
00404 float TotalAngles = 0.0f;
00405
00406
00407 KVector VecteurA = Point - v0;
00408 KVector VecteurB = Point - v1;
00409 KVector VecteurC = Point - v2;
00410
00411 VecteurA.Normalize();
00412 VecteurB.Normalize();
00413 VecteurC.Normalize();
00414
00415 TotalAngles += acosf( KVector::DotProduct( VecteurA, VecteurB ) );
00416 TotalAngles += acosf( KVector::DotProduct( VecteurB, VecteurC ) );
00417 TotalAngles += acosf( KVector::DotProduct( VecteurC, VecteurA ) );
00418
00419
00420 if( fabsf( TotalAngles - 2.0f * PI ) <= 0.005 )
00421 return true;
00422
00423 return false;
00424 }
00425
00426
00427 bool CheckPointInSphere( KVector Point, KVector& sO, float sR )
00428 {
00429 Point -= sO;
00430 float d = Point.Magnitude();
00431
00432 if( d <= sR )
00433 return true;
00434
00435 return false;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 float IntersectRayPlaneDistance( KVector& RayOrigin, KVector& RayVector, KVector& PointOrigin, KVector& PointNormal )
00453 {
00454 float d = -KVector::DotProduct( PointNormal, PointOrigin );
00455 float numer = KVector::DotProduct( PointNormal, RayOrigin ) + d;
00456 float denom = KVector::DotProduct( PointNormal, RayVector );
00457
00458 if( denom == 0 )
00459 return -1.0f;
00460
00461 return -( numer / denom );
00462 }
00463
00464
00465 float IntersectRaySphere( KVector& RayOrigin, KVector& RayVector, KVector& SphereOrigin, float SphereRadius )
00466 {
00467 KVector Q = SphereOrigin - RayOrigin;
00468 float c = Q.Magnitude();
00469 float v = KVector::DotProduct( Q, RayVector );
00470 float d = SphereRadius * SphereRadius - ( c * c - v * v );
00471
00472 if( d < 0.0f )
00473 return -1.0f;
00474
00475 return v - sqrtf( d );
00476 }
00477
00478
00479 float IntersectRayPlaneDistance( KVector& RayOrigin, KVector& RayVector, KVector& PlaneNormal, float PlaneDist )
00480 {
00481 float CosAlpha;
00482 float Delta;
00483
00484 CosAlpha = KVector::DotProduct( RayVector, PlaneNormal );
00485
00486
00487 if( CosAlpha == 0 )
00488 return -1.0f;
00489
00490 Delta = PlaneDist - KVector::DotProduct( RayOrigin, PlaneNormal );
00491
00492 return ( Delta / CosAlpha );
00493 }
00494
00495
00496 bool GetLowestRoot( float a, float b, float c, float maxR, float* root )
00497 {
00498
00499 float determinant = b * b - 4.0f * a * c;
00500
00501
00502 if( determinant < 0.0f )
00503 return false;
00504
00505
00506
00507 float sqrtD = sqrtf( determinant );
00508 float r1 = (-b - sqrtD) / (2*a);
00509 float r2 = (-b + sqrtD) / (2*a);
00510
00511
00512 if (r1 > r2)
00513 {
00514 float temp = r2;
00515 r2 = r1;
00516 r1 = temp;
00517 }
00518
00519
00520 if (r1 > 0 && r1 < maxR)
00521 {
00522 *root = r1;
00523 return true;
00524 }
00525
00526
00527
00528 if (r2 > 0 && r2 < maxR)
00529 {
00530 *root = r2;
00531 return true;
00532 }
00533
00534 return false;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 bool CheckSphereCollision( KCollisionData* pData, KVector v0, KVector v1, KVector v2, float Epsilon )
00608 {
00609
00610 v0 /= pData->m_Radius;
00611 v1 /= pData->m_Radius;
00612 v2 /= pData->m_Radius;
00613
00614
00615 KVector NormalizedVelocity = pData->m_Velocity;
00616 NormalizedVelocity.Normalize();
00617
00618
00619 KVector Edge1 = v1 - v0;
00620 KVector Edge2 = v2 - v0;
00621
00622
00623 KVector Normal = KVector::CrossProduct( Edge1, Edge2 );
00624 Normal.Normalize();
00625
00626
00627 KPlane Plane( Normal, KVector::DotProduct( v0, Normal ) );
00628
00629
00630 KVector SpherePoint = pData->m_Position - Normal;
00631
00632
00633 KVector PlanePoint;
00634 float Distance;
00635
00636 if( Plane.GetPointSide( SpherePoint, Epsilon ) == KPPS_BACKSIDE )
00637 {
00638
00639
00640 Distance = IntersectRayPlaneDistance( SpherePoint, Normal, v0, Normal );
00641 PlanePoint = SpherePoint + Normal * Distance;
00642
00643 }
00644 else
00645 {
00646
00647
00648 Distance = IntersectRayPlaneDistance( SpherePoint, NormalizedVelocity, v0, Normal );
00649 PlanePoint = SpherePoint + NormalizedVelocity * Distance;
00650
00651 }
00652
00653
00654 KVector TrianglePoint = PlanePoint;
00655
00656
00657 if( !CheckPointInTriangle( PlanePoint, v0, v1, v2 ) )
00658 {
00659
00660 TrianglePoint = ClosestPointOnTriangle( PlanePoint, v0, v1, v2 );
00661 Distance = IntersectRaySphere( TrianglePoint, -NormalizedVelocity, pData->m_Position, 1.0f );
00662
00663 if( Distance > 0.0f )
00664 {
00665 SpherePoint = TrianglePoint - NormalizedVelocity * Distance;
00666 }
00667 }
00668
00669
00670 if( CheckPointInSphere( TrianglePoint, pData->m_Position, 1.0f ) )
00671 pData->m_bStuck = true;
00672
00673
00674 if( ( Distance > 0.0f ) && ( Distance <= pData->m_Velocity.Magnitude() ) )
00675 {
00676 if( ( pData->m_bFoundCollision == false ) || ( Distance < pData->m_NearestDistance ) )
00677 {
00678 pData->m_NearestDistance = Distance;
00679 pData->m_NearestIntersectionPoint = SpherePoint;
00680 pData->m_NearestPolygonIntersectionPoint = TrianglePoint;
00681 pData->m_bFoundCollision = true;
00682 return true;
00683 }
00684 }
00685
00686 return false;
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696 void CheckSphereCollision2( KCollisionData2* pData, KVector v0, KVector v1, KVector v2 )
00697 {
00698 v0 /= pData->m_eRadius;
00699 v1 /= pData->m_eRadius;
00700 v2 /= pData->m_eRadius;
00701
00702
00703 KPlane TrianglePlane( v0, v1, v2 );
00704
00705
00706
00707
00708 if( TrianglePlane.IsFrontFacingTo( pData->m_NormalizedVelocity ) )
00709 {
00710
00711 float t0, t1;
00712 bool bEmbeddedInPlane = false;
00713
00714
00715
00716 float SignedDistToTrianglePlane = (float)TrianglePlane.SignedDistanceTo( pData->m_BasePoint );
00717
00718
00719 float NormalDotVelocity = TrianglePlane.m_Normal.DotProductf( pData->m_Velocity );
00720
00721
00722 if( NormalDotVelocity == 0.0f )
00723 {
00724 if( fabs( SignedDistToTrianglePlane ) >= 1.0f )
00725 {
00726
00727
00728 return;
00729 }
00730 else
00731 {
00732
00733
00734 bEmbeddedInPlane = true;
00735 t0 = 0.0;
00736 t1 = 1.0;
00737 }
00738 }
00739 else
00740 {
00741
00742 t0 = ( -1.0f - SignedDistToTrianglePlane ) / NormalDotVelocity;
00743 t1 = ( 1.0f - SignedDistToTrianglePlane ) / NormalDotVelocity;
00744
00745
00746 if( t0 > t1 )
00747 {
00748 float temp = t1;
00749 t1 = t0;
00750 t0 = temp;
00751 }
00752
00753
00754 if( t0 > 1.0f || t1 < 0.0f )
00755 {
00756
00757
00758 return;
00759 }
00760
00761
00762 if (t0 < 0.0) t0 = 0.0;
00763 if (t1 < 0.0) t1 = 0.0;
00764 if (t0 > 1.0) t0 = 1.0;
00765 if (t1 > 1.0) t1 = 1.0;
00766 }
00767
00768
00769
00770
00771
00772 KVector CollisionPoint;
00773 bool bFoundCollison = false;
00774 float t = 1.0;
00775
00776
00777
00778
00779
00780 if( !bEmbeddedInPlane )
00781 {
00782 KVector PlaneIntersectionPoint = ( pData->m_BasePoint - TrianglePlane.m_Normal ) + pData->m_Velocity * t0;
00783
00784 if( CheckPointInTriangle( PlaneIntersectionPoint, v0, v1, v2 ) )
00785 {
00786 bFoundCollison = true;
00787 t = t0;
00788 CollisionPoint = PlaneIntersectionPoint;
00789 }
00790 }
00791
00792
00793
00794
00795
00796
00797 if( bFoundCollison == false )
00798 {
00799
00800 KVector Velocity = pData->m_Velocity;
00801 KVector Base = pData->m_BasePoint;
00802 float VelocitySquaredLength = Velocity.SquareMagnitude();
00803 float a,b,c;
00804 float newT;
00805
00806
00807
00808
00809
00810 a = VelocitySquaredLength;
00811
00812
00813 b = 2.0f * Velocity.DotProductf( Base - v0 );
00814 c = ( v0 - Base ).SquareMagnitude() - 1.0f;
00815 if( GetLowestRoot( a, b, c, t, &newT ) )
00816 {
00817 t = newT;
00818 bFoundCollison = true;
00819 CollisionPoint = v0;
00820 }
00821
00822
00823 b = 2.0f * Velocity.DotProductf( Base - v1 );
00824 c = ( v1 - Base ).SquareMagnitude() - 1.0f;
00825 if( GetLowestRoot( a, b, c, t, &newT ) )
00826 {
00827 t = newT;
00828 bFoundCollison = true;
00829 CollisionPoint = v1;
00830 }
00831
00832
00833 b = 2.0f * Velocity.DotProductf( Base - v2 );
00834 c = ( v2 - Base ).SquareMagnitude() - 1.0f;
00835 if( GetLowestRoot( a, b, c, t, &newT ) )
00836 {
00837 t = newT;
00838 bFoundCollison = true;
00839 CollisionPoint = v2;
00840 }
00841
00842
00843
00844 KVector Edge = v1 - v0;
00845 KVector BaseToVertex = v0 - Base;
00846 float EdgeSquaredLength = Edge.SquareMagnitude();
00847 float EdgeDotVelocity = Edge.DotProductf( Velocity );
00848 float EdgeDotBaseToVertex = Edge.DotProductf( BaseToVertex );
00849
00850
00851 a = EdgeSquaredLength * -VelocitySquaredLength + EdgeDotVelocity * EdgeDotVelocity;
00852 b = EdgeSquaredLength * ( 2.0f * Velocity.DotProductf( BaseToVertex ) ) - 2.0f * EdgeDotVelocity * EdgeDotBaseToVertex;
00853 c = EdgeSquaredLength * ( 1.0f - BaseToVertex.SquareMagnitude() ) + EdgeDotBaseToVertex * EdgeDotBaseToVertex;
00854
00855
00856 if( GetLowestRoot( a, b, c, t, &newT ) )
00857 {
00858
00859 float f = ( EdgeDotVelocity * newT - EdgeDotBaseToVertex ) / EdgeSquaredLength;
00860 if( f >= 0.0f && f <= 1.0f )
00861 {
00862
00863 t = newT;
00864 bFoundCollison = true;
00865 CollisionPoint = v0 + Edge * f;
00866 }
00867 }
00868
00869
00870 Edge = v2 - v1;
00871 BaseToVertex = v1 - Base;
00872 EdgeSquaredLength = Edge.SquareMagnitude();
00873 EdgeDotVelocity = Edge.DotProductf( Velocity );
00874 EdgeDotBaseToVertex = Edge.DotProductf( BaseToVertex );
00875 a = EdgeSquaredLength * -VelocitySquaredLength + EdgeDotVelocity * EdgeDotVelocity;
00876 b = EdgeSquaredLength * ( 2.0f * Velocity.DotProductf( BaseToVertex ) ) - 2.0f * EdgeDotVelocity * EdgeDotBaseToVertex;
00877 c = EdgeSquaredLength * ( 1.0f - BaseToVertex.SquareMagnitude() ) + EdgeDotBaseToVertex * EdgeDotBaseToVertex;
00878
00879 if( GetLowestRoot( a, b, c, t, &newT ) )
00880 {
00881 float f = ( EdgeDotVelocity * newT - EdgeDotBaseToVertex ) / EdgeSquaredLength;
00882 if( f >= 0.0f && f <= 1.0f )
00883 {
00884 t = newT;
00885 bFoundCollison = true;
00886 CollisionPoint = v1 + Edge * f;
00887 }
00888 }
00889
00890
00891 Edge = v0 - v2;
00892 BaseToVertex = v2 - Base;
00893 EdgeSquaredLength = Edge.SquareMagnitude();
00894 EdgeDotVelocity = Edge.DotProductf( Velocity );
00895 EdgeDotBaseToVertex = Edge.DotProductf( BaseToVertex );
00896 a = EdgeSquaredLength * -VelocitySquaredLength + EdgeDotVelocity * EdgeDotVelocity;
00897 b = EdgeSquaredLength * ( 2.0f * Velocity.DotProductf( BaseToVertex ) ) - 2.0f * EdgeDotVelocity * EdgeDotBaseToVertex;
00898 c = EdgeSquaredLength * ( 1.0f - BaseToVertex.SquareMagnitude() ) + EdgeDotBaseToVertex * EdgeDotBaseToVertex;
00899
00900 if ( GetLowestRoot( a, b, c, t, &newT ) )
00901 {
00902 float f = ( EdgeDotVelocity * newT - EdgeDotBaseToVertex ) / EdgeSquaredLength;
00903 if( f >= 0.0f && f <= 1.0f )
00904 {
00905 t = newT;
00906 bFoundCollison = true;
00907 CollisionPoint = v2 + Edge * f;
00908 }
00909 }
00910 }
00911
00912
00913 if( bFoundCollison == true )
00914 {
00915
00916 float DistToCollision = t * pData->m_Velocity.Magnitude();
00917
00918
00919
00920 if( pData->m_bFoundCollision == false || DistToCollision < pData->m_NearestDistance )
00921 {
00922
00923 pData->m_NearestDistance = DistToCollision;
00924 pData->m_IntersectionPoint = CollisionPoint;
00925 pData->m_CollisionNormal = TrianglePlane.m_Normal;
00926 pData->m_bFoundCollision = true;
00927 }
00928 }
00929 }
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 bool CheckRayEllipse( KVector& vRayOrigin, KVector& vRayDestination, KVector& vEllipseOrigin, KVector& vEllipseRadius, float* pFraction )
01004 {
01005 return CheckRaySphere( vRayOrigin / vEllipseRadius, vRayDestination / vEllipseRadius, vEllipseOrigin / vEllipseRadius, 1.0f, pFraction );
01006 }
01007
01008
01009 bool CheckRaySphere( KVector& vRayOrigin, KVector& vRayDestination, KVector& vSphereCenter, float SphereRadius, float* pFraction )
01010 {
01011 KVector RayParam = vRayDestination - vRayOrigin;
01012
01013
01014
01015 float a = SQR( RayParam.x ) + SQR( RayParam.y ) + SQR( RayParam.z );
01016 float b = 2.0f * RayParam.x * ( vRayOrigin.x - vSphereCenter.x ) + 2.0f * RayParam.y * ( vRayOrigin.y - vSphereCenter.y ) + 2.0f * RayParam.z * ( vRayOrigin.z - vSphereCenter.z );
01017 float c = SQR( vSphereCenter.x ) + SQR( vSphereCenter.y ) + SQR( vSphereCenter.z )
01018 + SQR( vRayOrigin.x ) + SQR( vRayOrigin.y ) + SQR( vRayOrigin.z )
01019 + 2.0f * ( -vSphereCenter.x * vRayOrigin.x - vSphereCenter.y * vRayOrigin.y - vSphereCenter.z * vRayOrigin.z )
01020 - SQR( SphereRadius );
01021
01022
01023 float d = SQR( b ) - 4.0f * a * c;
01024
01025
01026 if( d < 0.0f )
01027 {
01028 *pFraction = 1.0f;
01029 return false;
01030 }
01031
01032
01033 if( d == 0.0f )
01034 {
01035 *pFraction = -b / (2.0f * a);
01036 return true;
01037 }
01038
01039
01040 float sqrta = sqrtf( a );
01041 float t0 = (-b - sqrta) / (2.0f * a);
01042 float t1 = (-b + sqrta) / (2.0f * a);
01043 *pFraction = (t0 < t1) ? t0 : t1;
01044
01045 return true;
01046 }
01047