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 #include "LampBasic.h"
00026 #include "Geometry/Intersection/SphereIntersection.h"
00027 #include "Geometry/System/Intersection.h"
00028
00029 #include "Geometry/Primitive/Triangle.h"
00030
00031 namespace Lamp{
00032
00033
00034
00035
00036
00037 bool SphereIntersection::intersect(const Sphere& sphere, const Vector3& point){
00038 Assert(false);
00039 return false;
00040 }
00041
00042
00043
00044
00045 bool SphereIntersection::intersect(
00046 const Sphere& sphere0, const Sphere& sphere1){
00047
00048 float radius = sphere0.getRadius() + sphere1.getRadius();
00049 Vector3 direction = sphere1.getCenter() - sphere0.getCenter();
00050 if(direction.getSquaredLength() > (radius * radius)){ return false; }
00051 return true;
00052 }
00053
00054
00055 bool SphereIntersection::intersect(Intersection* intersection,
00056 const Sphere& sphere0, const Sphere& sphere1){
00057 const Vector3& center0 = sphere0.getCenter();
00058 float radius0 = sphere0.getRadius();
00059 const Vector3& center1 = sphere1.getCenter();
00060 float radius1 = sphere1.getRadius();
00061
00062 float totalRadius = radius0 + radius1;
00063 Vector3 distance = center1 - center0;
00064 float squaredLength = distance.getSquaredLength();
00065 if(squaredLength > (totalRadius * totalRadius)){ return false; }
00066
00067 if(distance.isZero()){ distance = Vector3::unitY; }
00068 else{ distance.normalize(); }
00069 intersection->set(center0 + (distance * radius0),
00070 distance * (totalRadius - Math::sqrt(squaredLength)));
00071 return true;
00072 }
00073
00074
00075
00076
00077 bool SphereIntersection::intersect(
00078 const Sphere& sphere, const Triangle& triangle){
00079 const Vector3& center = sphere.getCenter();
00080 float radius = sphere.getRadius();
00081 const Vector3& vertex0 = triangle.getVertex(0);
00082 const Vector3& vertex1 = triangle.getVertex(1);
00083 const Vector3& vertex2 = triangle.getVertex(2);
00084
00085
00086 Vector3 edge0 = vertex1 - vertex0;
00087 Vector3 edge1 = vertex2 - vertex1;
00088 Vector3 normal = edge0.crossProduct(edge1).normalize();
00089
00090
00091 float constant = -normal.dotProduct(vertex0);
00092 float distance = normal.dotProduct(center) + constant;
00093
00094
00095 if(distance <= 0.f){ return false; }
00096
00097 if(distance > radius){ return false; }
00098
00099
00100 Vector3 edge2 = vertex0 - vertex2;
00101 bool outside = false;
00102 Vector3 distance0 = center - vertex0;
00103 outside |= (normal.dotProduct(edge0.crossProduct(distance0)) < 0.f);
00104 Vector3 distance1 = center - vertex1;
00105 outside |= (normal.dotProduct(edge1.crossProduct(distance1)) < 0.f);
00106 Vector3 distance2 = center - vertex2;
00107 outside |= (normal.dotProduct(edge2.crossProduct(distance2)) < 0.f);
00108
00109 if(!outside){
00110
00111 return true;
00112 }
00113
00114
00115 float squaredRadius = radius * radius;
00116 float t0 = distance0.dotProduct(edge0);
00117 if(t0 > 0.f){
00118 float edgeSquaredLength = edge0.getSquaredLength();
00119 if(t0 >= edgeSquaredLength){
00120
00121 distance0 -= edge0;
00122 }else{
00123 t0 /= edgeSquaredLength;
00124 distance0 -= t0 * edge0;
00125 }
00126 }
00127
00128 if(distance0.getSquaredLength() <= squaredRadius){
00129
00130 return true;
00131 }
00132
00133
00134 float t1 = distance1.dotProduct(edge1);
00135 if(t1 > 0.f){
00136 float edgeSquaredLength = edge1.getSquaredLength();
00137 if(t1 >= edgeSquaredLength){
00138
00139 distance1 -= edge1;
00140 }else{
00141 t1 /= edgeSquaredLength;
00142 distance1 -= t1 * edge1;
00143 }
00144 }
00145
00146 if(distance1.getSquaredLength() <= squaredRadius){
00147
00148 return true;
00149 }
00150
00151
00152 float t2 = distance2.dotProduct(edge2);
00153 if(t2 > 0.f){
00154 float edgeSquaredLength = edge2.getSquaredLength();
00155 if(t2 >= edgeSquaredLength){
00156
00157 distance2 -= edge2;
00158 }else{
00159 t2 /= edgeSquaredLength;
00160 distance2 -= t2 * edge2;
00161 }
00162 }
00163
00164 if(distance2.getSquaredLength() <= squaredRadius){
00165
00166 return true;
00167 }
00168
00169 return false;
00170 }
00171
00172
00173 bool SphereIntersection::intersect(Intersection* intersection,
00174 const Sphere& sphere, const Triangle& triangle){
00175 const Vector3& center = sphere.getCenter();
00176 float radius = sphere.getRadius();
00177 const Vector3& vertex0 = triangle.getVertex(0);
00178 const Vector3& vertex1 = triangle.getVertex(1);
00179 const Vector3& vertex2 = triangle.getVertex(2);
00180
00181
00182 Vector3 edge0 = vertex1 - vertex0;
00183 Vector3 edge1 = vertex2 - vertex1;
00184 Vector3 normal = edge0.crossProduct(edge1).normalize();
00185
00186
00187 float constant = -normal.dotProduct(vertex0);
00188 float distance = normal.dotProduct(center) + constant;
00189
00190
00191 if(distance <= 0.f){ return false; }
00192
00193 if(distance > radius){ return false; }
00194
00195
00196 Vector3 edge2 = vertex0 - vertex2;
00197 bool outside = false;
00198 Vector3 distance0 = center - vertex0;
00199 outside |= (normal.dotProduct(edge0.crossProduct(distance0)) < 0.f);
00200 Vector3 distance1 = center - vertex1;
00201 outside |= (normal.dotProduct(edge1.crossProduct(distance1)) < 0.f);
00202 Vector3 distance2 = center - vertex2;
00203 outside |= (normal.dotProduct(edge2.crossProduct(distance2)) < 0.f);
00204
00205 if(!outside){
00206
00207
00208 Vector3 inverseNormal(-normal);
00209 intersection->set(center + inverseNormal * radius,
00210 inverseNormal * (radius - distance));
00211 return true;
00212 }
00213
00214
00215 float squaredRadius = radius * radius;
00216 float t0 = distance0.dotProduct(edge0);
00217 if(t0 > 0.f){
00218 float edgeSquaredLength = edge0.getSquaredLength();
00219 if(t0 >= edgeSquaredLength){
00220 t0 = 1.f;
00221 distance0 -= edge0;
00222 }else{
00223 t0 /= edgeSquaredLength;
00224 distance0 -= t0 * edge0;
00225 }
00226 }
00227
00228 float squaredLength0 = distance0.getSquaredLength();
00229 if(squaredLength0 <= squaredRadius){
00230
00231
00232 Vector3 position0 = -distance0;
00233 float length0 = radius - Math::sqrt(squaredLength0);
00234 if(position0.isZero()){
00235
00236 position0 = Vector3::unitY * radius;
00237 intersection->set(center + position0, position0);
00238 }else if(length0 <= Math::epsilon){
00239
00240 intersection->set(center + position0.setLength(radius),
00241 Vector3::zero);
00242 }else{
00243
00244 position0.normalize();
00245 intersection->set(center + position0 * radius,
00246 position0 * length0);
00247 }
00248 return true;
00249 }
00250
00251
00252 float t1 = distance1.dotProduct(edge1);
00253 if(t1 > 0.f){
00254 float edgeSquaredLength = edge1.getSquaredLength();
00255 if(t1 >= edgeSquaredLength){
00256 t1 = 1.f;
00257 distance1 -= edge1;
00258 }else{
00259 t1 /= edgeSquaredLength;
00260 distance1 -= t1 * edge1;
00261 }
00262 }
00263
00264 float squaredLength1 = distance1.getSquaredLength();
00265 if(squaredLength1 <= squaredRadius){
00266
00267
00268 Vector3 position1 = -distance1;
00269 float length1 = radius - Math::sqrt(squaredLength1);
00270 if(position1.isZero()){
00271
00272 position1 = Vector3::unitY * radius;
00273 intersection->set(center + position1, position1);
00274 }else if(length1 <= Math::epsilon){
00275
00276 intersection->set(center + position1.setLength(radius),
00277 Vector3::zero);
00278 }else{
00279
00280 position1.normalize();
00281 intersection->set(center + position1 * radius,
00282 position1 * length1);
00283 }
00284 return true;
00285 }
00286
00287
00288 float t2 = distance2.dotProduct(edge2);
00289 if(t2 > 0.f){
00290 float edgeSquaredLength = edge2.getSquaredLength();
00291 if(t2 >= edgeSquaredLength){
00292 t2 = 1.f;
00293 distance2 -= edge2;
00294 }else{
00295 t2 /= edgeSquaredLength;
00296 distance2 -= t2 * edge2;
00297 }
00298 }
00299
00300 float squaredLength2 = distance2.getSquaredLength();
00301 if(squaredLength2 <= squaredRadius){
00302
00303
00304 Vector3 position2 = -distance2;
00305 float length2 = radius - Math::sqrt(squaredLength2);
00306 if(position2.isZero()){
00307
00308 position2 = Vector3::unitY * radius;
00309 intersection->set(center + position2, position2);
00310 }else if(length2 <= Math::epsilon){
00311
00312 intersection->set(center + position2.setLength(radius),
00313 Vector3::zero);
00314 }else{
00315
00316 position2.normalize();
00317 intersection->set(center + position2 * radius,
00318 position2 * length2);
00319 }
00320 return true;
00321 }
00322
00323 return false;
00324 }
00325
00326 }
00327