1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[Line.h]"19 #include "[Ray.h]"20 #include "[LineSegment.h]"21 #include "../Math/float3x3.h"22 #include "../Math/float3x4.h"23 #include "../Math/float4x4.h"24 #include "[OBB.h]"25 #include "../Math/Quat.h"26 #include "[Frustum.h]"27 #include "[Triangle.h]"28 #include "[Plane.h]"29 #include "[Polygon.h]"30 #include "[Polyhedron.h]"31 #include "[Sphere.h]"32 #include "[AABB.h]"33 #include "[Capsule.h]"34 #include "[Circle.h]"35 #include "../Math/MathFunc.h"36 37 #ifdef MATH_ENABLE_STL_SUPPORT38 #include <iostream>39 #endif40 41 [MATH_BEGIN_NAMESPACE]42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 void [Line::ClosestPointLineLine](const vec &v0, const vec &v10, const vec &v2, const vec &v32, float &[d], float &d2)57 {58 [assume](!v10.IsZero());59 [assume](!v32.IsZero());60 vec v02 = v0 - v2;61 float d0232 = v02.Dot(v32);62 float d3210 = v32.Dot(v10);63 float d3232 = v32.Dot(v32);64 [assume](d3232 != 0.f); 65 float d0210 = v02.Dot(v10);66 float d1010 = v10.Dot(v10);67 float denom = d1010*d3232 - d3210*d3210;68 if (denom != 0.f)69 d = (d0232*d3210 - d0210*d3232) / denom;70 else71 d = 0.f;72 d2 = (d0232 + d * d3210) / d3232;73 }74 75 [Line::Line](const vec &pos_, const vec &dir_)76 :pos(pos_), dir(dir_)77 {78 [assume2](dir.IsNormalized(), dir, dir.LengthSq());79 }80 81 [Line::Line](const [Ray] &ray)82 :pos(ray.pos), dir(ray.dir)83 {84 [assume2](dir.IsNormalized(), dir, dir.LengthSq());85 }86 87 [Line::Line](const [LineSegment] &lineSegment)88 :pos(lineSegment.a), dir(lineSegment.Dir())89 {90 }91 92 bool [Line::IsFinite]() const93 {94 return [pos].[IsFinite]() && [dir].[IsFinite]();95 }96 97 vec [Line::GetPoint](float d) const98 {99 [assume2]([dir].[IsNormalized](), [dir], [dir].[LengthSq]());100 return [pos] + d * [dir];101 }102 103 void [Line::Translate](const vec &offset)104 {105 [pos] += offset;106 }107 108 void [Line::Transform](const [float3x3] &transform)109 {110 [pos] = transform.[Transform]([pos]);111 [dir] = transform.[Transform]([dir]);112 }113 114 void [Line::Transform](const [float3x4] &transform)115 {116 [pos] = transform.[MulPos]([pos]);117 [dir] = transform.[MulDir]([dir]);118 }119 120 void [Line::Transform](const [float4x4] &transform)121 {122 [pos] = transform.[MulPos]([pos]);123 [dir] = transform.[MulDir]([dir]);124 }125 126 void [Line::Transform](const [Quat] &transform)127 {128 [pos] = transform.[Transform]([pos]);129 [dir] = transform.[Transform]([dir]);130 }131 132 bool [Line::Contains](const vec &point, float distanceThreshold) const133 {134 return [ClosestPoint](point).[DistanceSq](point) <= distanceThreshold;135 }136 137 bool [Line::Contains](const [Ray] &ray, float [epsilon]) const138 {139 return [Contains](ray.[pos], epsilon) && [dir].[Equals](ray.[dir], epsilon);140 }141 142 bool [Line::Contains](const [LineSegment] &lineSegment, float epsilon) const143 {144 return [Contains](lineSegment.[a], epsilon) && [Contains](lineSegment.[b], epsilon);145 }146 147 bool [Line::Equals](const [Line] &line, float epsilon) const148 {149 [assume2]([dir].[IsNormalized](), [dir], [dir].[LengthSq]());150 [assume2](line.[dir].[IsNormalized](), line.[dir], line.[dir].[LengthSq]());151 152 153 return [Contains](line.[pos], epsilon) && [EqualAbs]([Abs]([dir].[Dot](line.[dir])), 1.f, epsilon);154 }155 156 float [Line::Distance](const vec &point, float &d) const157 {158 return [ClosestPoint](point, d).[Distance](point);159 }160 161 float [Line::Distance](const [Ray] &other, float &d, float &d2) const162 {163 vec c = [ClosestPoint](other, d, d2);164 return c.Distance(other.[GetPoint](d2));165 }166 167 float [Line::Distance](const [Line] &other, float &d, float &d2) const168 {169 vec c = [ClosestPoint](other, d, d2);170 return c.Distance(other.[GetPoint](d2));171 }172 173 float [Line::Distance](const [LineSegment] &other, float &d, float &d2) const174 {175 vec c = [ClosestPoint](other, d, d2);176 [mathassert](d2 >= 0.f);177 [mathassert](d2 <= 1.f);178 return c.Distance(other.[GetPoint](d2));179 }180 181 float [Line::Distance](const [Sphere] &other) const182 {183 return [Max](0.f, [Distance](other.[pos]) - other.[r]);184 }185 186 float [Line::Distance](const [Capsule] &other) const187 {188 return [Max](0.f, [Distance](other.[l]) - other.[r]);189 }190 191 bool [Line::Intersects](const [Triangle] &triangle, float *d, vec *intersectionPoint) const192 {193 return triangle.[Intersects](*this, d, intersectionPoint);194 }195 196 bool [Line::Intersects](const [Plane] &plane, float *d) const197 {198 return plane.[Intersects](*this, d);199 }200 201 bool [Line::Intersects](const [Sphere] &s, vec *intersectionPoint, vec *intersectionNormal, float *d) const202 {203 return s.[Intersects](*this, intersectionPoint, intersectionNormal, d) > 0;204 }205 206 bool [Line::Intersects](const [AABB] &aabb) const207 {208 return aabb.[Intersects](*this);209 }210 211 bool [Line::Intersects](const [AABB] &aabb, float &dNear, float &dFar) const212 {213 return aabb.[Intersects](*this, dNear, dFar);214 }215 216 bool [Line::Intersects](const [OBB] &obb) const217 {218 return obb.[Intersects](*this);219 }220 221 bool [Line::Intersects](const [OBB] &obb, float &dNear, float &dFar) const222 {223 return obb.[Intersects](*this, dNear, dFar);224 }225 226 bool [Line::Intersects](const [Capsule] &capsule) const227 {228 return capsule.[Intersects](*this);229 }230 231 bool [Line::Intersects](const [Polygon] &polygon) const232 {233 return polygon.[Intersects](*this);234 }235 236 bool [Line::Intersects](const [Frustum] &frustum) const237 {238 return frustum.[Intersects](*this);239 }240 241 bool [Line::Intersects](const [Polyhedron] &polyhedron) const242 {243 return polyhedron.[Intersects](*this);244 }245 246 bool [Line::IntersectsDisc](const [Circle] &disc) const247 {248 return disc.[IntersectsDisc](*this);249 }250 251 vec [Line::ClosestPoint](const vec &targetPoint, float &d) const252 {253 d = [Dot](targetPoint - [pos], [dir]);254 return [GetPoint](d);255 }256 257 vec [Line::ClosestPoint](const [Ray] &other, float &d, float &d2) const258 {259 [ClosestPointLineLine]([pos], [dir], other.[pos], other.[dir], d, d2);260 if (d2 >= 0.f)261 return [GetPoint](d);262 else263 {264 d2 = 0.f;265 return [ClosestPoint](other.[pos], d);266 }267 }268 269 vec [Line::ClosestPoint](const [Line] &other, float &d, float &d2) const270 {271 [ClosestPointLineLine]([pos], [dir], other.[pos], other.[dir], d, d2);272 return [GetPoint](d);273 }274 275 vec [Line::ClosestPoint](const [LineSegment] &other, float &d, float &d2) const276 {277 [ClosestPointLineLine]([pos], [dir], other.[a], other.[b] - other.[a], d, d2);278 if (d2 < 0.f)279 {280 d2 = 0.f;281 return [ClosestPoint](other.[a], d);282 }283 else if (d2 > 1.f)284 {285 d2 = 1.f;286 return [ClosestPoint](other.[b], d);287 }288 else289 return [GetPoint](d);290 }291 292 vec [Line::ClosestPoint](const [Triangle] &triangle, float &d) const293 {294 vec closestPointTriangle = triangle.[ClosestPoint](*this);295 return [ClosestPoint](closestPointTriangle, d);296 }297 298 vec [Line::ClosestPoint](const [Triangle] &triangle, float &d, [float2] &outBarycentricUV) const299 {300 vec closestPointTriangle = triangle.[ClosestPoint](*this);301 outBarycentricUV = triangle.[BarycentricUV](closestPointTriangle);302 return [ClosestPoint](closestPointTriangle, d);303 }304 305 bool [Line::AreCollinear](const vec &p1, const vec &p2, const vec &p3, float epsilon)306 {307 return vec::AreCollinear(p1, p2, p3, epsilon);308 }309 310 [Ray] [Line::ToRay]() const311 {312 return [Ray]([pos], [dir]);313 }314 315 [LineSegment] [Line::ToLineSegment](float d) const316 {317 return [LineSegment]([pos], [GetPoint](d));318 }319 320 void [Line::ProjectToAxis](const vec &direction, float &outMin, float &outMax) const321 {322 323 324 325 if ([dir].[IsPerpendicular](direction))326 outMin = outMax = [Dot](direction, [pos]);327 else328 {329 outMin = -[FLOAT_INF];330 outMax = [FLOAT_INF];331 }332 }333 334 [LineSegment] [Line::ToLineSegment](float dStart, float dEnd) const335 {336 return [LineSegment]([GetPoint](dStart), [GetPoint](dEnd));337 }338 339 [Line] [operator *](const [float3x3] &transform, const [Line] &l)340 {341 return [Line](transform * l.[pos], transform * l.[dir]);342 }343 344 [Line] [operator *](const [float3x4] &transform, const [Line] &l)345 {346 return [Line](transform.[MulPos](l.[pos]), transform.[MulDir](l.[dir]));347 }348 349 [Line] [operator *](const [float4x4] &transform, const [Line] &l)350 {351 return [Line](transform.[MulPos](l.[pos]), transform.[MulDir](l.[dir]));352 }353 354 [Line] [operator *](const [Quat] &transform, const [Line] &l)355 {356 return [Line](transform * l.[pos], transform * l.[dir]);357 }358 359 #ifdef MATH_ENABLE_STL_SUPPORT360 std::string [Line::ToString]() const361 {362 char str[256];363 sprintf(str, "Line(Pos:(%.2f, %.2f, %.2f) Dir:(%.3f, %.3f, %.3f))", [pos].[x], [pos].[y], [pos].[z], [dir].[x], [dir].[y], [dir].[z]);364 return str;365 }366 367 std::string [Line::SerializeToString]() const368 {369 char str[256];370 char *s = [SerializeFloat]([pos].[x], str); *s = ','; ++s;371 s = [SerializeFloat]([pos].[y], s); *s = ','; ++s;372 s = [SerializeFloat]([pos].[z], s); *s = ','; ++s;373 s = [SerializeFloat]([dir].[x], s); *s = ','; ++s;374 s = [SerializeFloat]([dir].[y], s); *s = ','; ++s;375 s = [SerializeFloat]([dir].[z], s);376 [assert](s+1 - str < 256);377 MARK_UNUSED(s);378 return str;379 }380 381 std::string [Line::SerializeToCodeString]() const382 {383 return "Line(" + [pos].[SerializeToCodeString]() + "," + [dir].[SerializeToCodeString]() + ")";384 }385 386 std::ostream &[operator <<](std::ostream &o, const [Line] &line)387 {388 o << line.[ToString]();389 return o;390 }391 392 #endif393 394 [Line] [Line::FromString](const char *str, const char **outEndStr)395 {396 [assume](str);397 if (!str)398 return [Line]([vec::nan], [vec::nan]);399 [Line] l;400 [MATH_SKIP_WORD](str, "Line(");401 [MATH_SKIP_WORD](str, "Pos:(");402 l.[pos] = [PointVecFromString](str, &str);403 [MATH_SKIP_WORD](str, " Dir:(");404 l.[dir] = [DirVecFromString](str, &str);405 if (outEndStr)406 *outEndStr = str;407 return l;408 }409 410 [MATH_END_NAMESPACE] Go back to previous page