Ticket #3588: geometry1.patch
File geometry1.patch, 4.8 KB (added by , 8 years ago) |
---|
-
source/simulation2/helpers/Geometry.cpp
diff --git a/source/simulation2/helpers/Geometry.cpp b/source/simulation2/helpers/Geometry.cpp index 4173a7a..c6e1b6a 100644
a b 1 /* Copyright (C) 201 5Wildfire Games.1 /* Copyright (C) 2016 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … bool Geometry::TestRaySquare(const CFixedVector2D& a, const CFixedVector2D& b, c 196 196 /* 197 197 * We only consider collisions to be when the ray goes from outside to inside the shape (and possibly out again). 198 198 * Various cases to consider: 199 * 'a' inside, 'b' inside -> no collision 200 * 'a' inside, 'b' outside -> no collision 201 * 'a' outside, 'b' inside -> collision 202 * 'a' outside, 'b' outside -> depends; use separating axis theorem: 199 * 'a' inside -> no collision 200 * use separating axis theorem: 203 201 * if the ray's bounding box is outside the square -> no collision 204 202 * if the whole square is on the same side of the ray -> no collision 205 203 * otherwise -> collision … … bool Geometry::TestRaySquare(const CFixedVector2D& a, const CFixedVector2D& b, c 218 216 fixed bu = b.Dot(u); 219 217 fixed bv = b.Dot(v); 220 218 221 if (-hw <= bu && bu <= hw && -hh <= bv && bv <= hh) // TODO: isn't this subsumed by the next checks?222 return true; // a is outside, b is inside223 224 219 if ((au < -hw && bu < -hw) || (au > hw && bu > hw) || (av < -hh && bv < -hh) || (av > hh && bv > hh)) 225 220 return false; // ab is entirely above/below/side the square 226 221 227 CFixedVector2D abp = (b - a).Perpendicular(); 228 fixed s0 = abp.Dot((u.Multiply(hw) + v.Multiply(hh)) - a); 229 fixed s1 = abp.Dot((u.Multiply(hw) - v.Multiply(hh)) - a); 230 fixed s2 = abp.Dot((-u.Multiply(hw) - v.Multiply(hh)) - a); 231 fixed s3 = abp.Dot((-u.Multiply(hw) + v.Multiply(hh)) - a); 232 if (s0.IsZero() || s1.IsZero() || s2.IsZero() || s3.IsZero()) 233 return true; // ray intersects the corner 234 235 bool sign = (s0 < fixed::Zero()); 236 if ((s1 < fixed::Zero()) != sign || (s2 < fixed::Zero()) != sign || (s3 < fixed::Zero()) != sign) 237 return true; // ray cuts through the square 238 239 return false; 222 // Check if all points are on one side of a->b. 223 // This can be simplified by using the following equivalence: 224 // (x +- y +- z) are all > 0 or all < 0 <=> |x| > |y| + |z| 225 // and the linearity of scalar products. 226 // Furthermore, we already computed 227 // u.Dot((b-a).Perpendicular()) = (u.Perpendicular()).Dot(b-a) = av - bv, v.Dot(...) similarly 228 // Also, a.Dot(a.Perpendicular()) = 0. 229 fixed s0 = a.Dot(b.Perpendicular()).Absolute(); 230 fixed s1 = (av - bv).Absolute().Multiply(hw) + (bu - au).Absolute().Multiply(hh); 231 return (s0 <= s1); 240 232 } 241 233 242 234 // Exactly like TestRaySquare with u=(1,0), v=(0,1) … … bool Geometry::TestRayAASquare(const CFixedVector2D& a, const CFixedVector2D& b, 248 240 if (-hw <= a.X && a.X <= hw && -hh <= a.Y && a.Y <= hh) 249 241 return false; // a is inside 250 242 251 if (-hw <= b.X && b.X <= hw && -hh <= b.Y && b.Y <= hh) // TODO: isn't this subsumed by the next checks?252 return true; // a is outside, b is inside253 254 243 if ((a.X < -hw && b.X < -hw) || (a.X > hw && b.X > hw) || (a.Y < -hh && b.Y < -hh) || (a.Y > hh && b.Y > hh)) 255 244 return false; // ab is entirely above/below/side the square 256 245 257 246 CFixedVector2D abp = (b - a).Perpendicular(); 258 fixed s0 = abp.Dot(CFixedVector2D(hw, hh) - a); 259 fixed s1 = abp.Dot(CFixedVector2D(hw, -hh) - a); 260 fixed s2 = abp.Dot(CFixedVector2D(-hw, -hh) - a); 261 fixed s3 = abp.Dot(CFixedVector2D(-hw, hh) - a); 262 if (s0.IsZero() || s1.IsZero() || s2.IsZero() || s3.IsZero()) 263 return true; // ray intersects the corner 264 265 bool sign = (s0 < fixed::Zero()); 266 if ((s1 < fixed::Zero()) != sign || (s2 < fixed::Zero()) != sign || (s3 < fixed::Zero()) != sign) 267 return true; // ray cuts through the square 268 269 return false; 247 fixed s0 = a.Dot(abp).Absolute(); 248 fixed s1 = abp.X.Absolute().Multiply(hw) + abp.Y.Absolute().Multiply(hh); 249 return (s0 <= s1); 270 250 } 271 251 272 252 /** … … static bool SquareSAT(const CFixedVector2D& a, const CFixedVector2D& axis, const 279 259 fixed hh = halfSize.Y; 280 260 281 261 CFixedVector2D p = axis.Perpendicular(); 282 if (p.Dot((u.Multiply(hw) + v.Multiply(hh)) - a) <= fixed::Zero()) 283 return true; 284 if (p.Dot((u.Multiply(hw) - v.Multiply(hh)) - a) <= fixed::Zero()) 262 // We only check the "counterclockwisest" point. 263 // But first we check if the center is on the wrong side. 264 fixed s0 = p.Dot(a); 265 if (s0 >= fixed::Zero()) 285 266 return true; 286 if (p.Dot((-u.Multiply(hw) - v.Multiply(hh)) - a) <= fixed::Zero()) 287 return true; 288 if (p.Dot((-u.Multiply(hw) + v.Multiply(hh)) - a) <= fixed::Zero()) 289 return true; 290 291 return false; 267 s0 += u.Dot(p).Absolute().Multiply(hw) + v.Dot(p).Absolute().Multiply(hh); 268 return (s0 >= fixed::Zero()); 292 269 } 293 270 294 271 bool Geometry::TestSquareSquare(