当前位置:   article > 正文

【学习日志】2022.09.12 Game-Physics-Cookbook----Geometry3D_cutsfclsbygeometry3d

cutsfclsbygeometry3d

Geometry3D.h

  1. #ifndef _H_GEOMETRY_3D_
  2. #define _H_GEOMETRY_3D_
  3. #include <vector>
  4. #include <utility>
  5. //#include <cfloat>
  6. #include "vectors.h"
  7. #include "matrices.h"
  8. #include <ostream>
  9. typedef vec3 Point;
  10. typedef struct Line {
  11. Point start;
  12. Point end;
  13. inline Line() {}
  14. inline Line(const Point& s, const Point& e) :
  15. start(s), end(e) { }
  16. } Line;
  17. typedef struct Ray {
  18. Point origin;
  19. vec3 direction;
  20. inline Ray() : direction(0.0f, 0.0f, 1.0f) {}
  21. inline Ray(const Point& o, const vec3& d) :
  22. origin(o), direction(d) {
  23. NormalizeDirection();
  24. }
  25. inline void NormalizeDirection() {
  26. Normalize(direction);
  27. }
  28. } Ray;
  29. typedef struct Sphere {
  30. Point position;
  31. float radius;
  32. inline Sphere() : radius(1.0f) { }
  33. inline Sphere(const Point& p, float r) :
  34. position(p), radius(r) { }
  35. } Sphere;
  36. typedef struct AABB {
  37. Point position;
  38. vec3 size; // HALF SIZE!
  39. inline AABB() : size(1, 1, 1) { }
  40. inline AABB(const Point& p, const vec3& s) :
  41. position(p), size(s) { }
  42. } AABB;
  43. typedef struct OBB {
  44. Point position;
  45. vec3 size; // HALF SIZE!
  46. mat3 orientation;
  47. inline OBB() : size(1, 1, 1) { }
  48. inline OBB(const Point& p, const vec3& s) :
  49. position(p), size(s) { }
  50. inline OBB(const Point& p, const vec3& s, const mat3& o) :
  51. position(p), size(s), orientation(o) { }
  52. } OBB;
  53. typedef struct Plane {
  54. vec3 normal;
  55. float distance;
  56. inline Plane() : normal(1, 0, 0) { }
  57. inline Plane(const vec3& n, float d) :
  58. normal(n), distance(d) { }
  59. } Plane;
  60. typedef struct Triangle {
  61. union {
  62. struct {
  63. Point a;
  64. Point b;
  65. Point c;
  66. };
  67. struct {
  68. Point p1;
  69. Point p2;
  70. Point p3;
  71. };
  72. Point points[3];
  73. float values[9];
  74. };
  75. inline Triangle() { }
  76. inline Triangle(const Point& _p1, const Point& _p2, const Point& _p3) :
  77. a(_p1), b(_p2), c(_p3) { }
  78. } Triangle;
  79. typedef struct BVHNode {
  80. AABB bounds;
  81. BVHNode* children;
  82. int numTriangles;
  83. int* triangles;
  84. BVHNode() : children(0), numTriangles(0), triangles(0) {}
  85. } BVHNode;
  86. typedef struct Mesh {
  87. int numTriangles;
  88. union {
  89. Triangle* triangles;
  90. Point* vertices;
  91. float* values;
  92. };
  93. BVHNode* accelerator;
  94. Mesh() : numTriangles(0), values(0), accelerator(0) {}
  95. } Mesh;
  96. class Model {
  97. protected:
  98. Mesh* content;
  99. AABB bounds;
  100. public:
  101. vec3 position;
  102. vec3 rotation;
  103. bool flag;
  104. Model* parent;
  105. inline Model() : parent(0), content(0), flag(false) { }
  106. inline Mesh* GetMesh() const {
  107. return content;
  108. }
  109. inline AABB GetBounds() const {
  110. return bounds;
  111. }
  112. void SetContent(Mesh* mesh);
  113. };
  114. typedef struct Interval {
  115. float min;
  116. float max;
  117. } Interval;
  118. typedef struct Frustum {
  119. union {
  120. struct {
  121. Plane top;
  122. Plane bottom;
  123. Plane left;
  124. Plane right;
  125. Plane _near;
  126. Plane _far;
  127. };
  128. Plane planes[6];
  129. };
  130. inline Frustum() { }
  131. } Frustum;
  132. typedef struct RaycastResult {
  133. vec3 point;
  134. vec3 normal;
  135. float t;
  136. bool hit;
  137. } RaycastResult;
  138. void ResetRaycastResult(RaycastResult* outResult);
  139. Point Intersection(Plane p1, Plane p2, Plane p3);
  140. void GetCorners(const Frustum& f, vec3* outCorners);
  141. typedef vec3 Point3D;
  142. typedef Line Line3D;
  143. typedef Ray Ray3D;
  144. typedef AABB Rectangle3D;
  145. typedef Interval Interval3D;
  146. std::ostream& operator<<(std::ostream& os, const Line& shape);
  147. std::ostream& operator<<(std::ostream& os, const Ray& shape);
  148. std::ostream& operator<<(std::ostream& os, const Sphere& shape);
  149. std::ostream& operator<<(std::ostream& os, const AABB& shape);
  150. std::ostream& operator<<(std::ostream& os, const OBB& shape);
  151. std::ostream& operator<<(std::ostream& os, const Plane& shape);
  152. std::ostream& operator<<(std::ostream& os, const Triangle& shape);
  153. float Length(const Line& line);
  154. float LengthSq(const Line& line);
  155. Ray FromPoints(const Point& from, const Point& to);
  156. vec3 GetMin(const AABB& aabb);
  157. vec3 GetMax(const AABB& aabb);
  158. AABB FromMinMax(const vec3& min, const vec3& max);
  159. float PlaneEquation(const Point& point, const Plane& plane);
  160. float PlaneEquation(const Plane& plane, const Point& point);
  161. bool PointInSphere(const Point& point, const Sphere& sphere);
  162. bool PointInAABB(const Point& point, const AABB& aabb);
  163. bool PointInOBB(const Point& point, const OBB& obb);
  164. bool PointOnPlane(const Point& point, const Plane& plane);
  165. bool PointOnLine(const Point& point, const Line& line);
  166. bool PointOnRay(const Point& point, const Ray& ray);
  167. bool PointInPlane(const Point& point, const Plane& plane);
  168. bool PointInLine(const Point& point, const Line& line);
  169. bool PointInRay(const Point& point, const Ray& ray);
  170. bool ContainsPoint(const Sphere& sphere, const Point& point);
  171. bool ContainsPoint(const Point& point, const Sphere& sphere);
  172. bool ContainsPoint(const AABB& aabb, const Point& point);
  173. bool ContainsPoint(const Point& point, const AABB& aabb);
  174. bool ContainsPoint(const Point& point, const OBB& obb);
  175. bool ContainsPoint(const OBB& obb, const Point& point);
  176. bool ContainsPoint(const Point& point, const Plane& plane);
  177. bool ContainsPoint(const Plane& plane, const Point& point);
  178. bool ContainsPoint(const Point& point, const Line& line);
  179. bool ContainsPoint(const Line& line, const Point& point);
  180. bool ContainsPoint(const Point& point, const Ray& ray);
  181. bool ContainsPoint(const Ray& ray, const Point& point);
  182. Point ClosestPoint(const Sphere& sphere, const Point& point);
  183. Point ClosestPoint(const AABB& aabb, const Point& point);
  184. Point ClosestPoint(const OBB& obb, const Point& point);
  185. Point ClosestPoint(const Plane& plane, const Point& point);
  186. Point ClosestPoint(const Line& line, const Point& point);
  187. Point ClosestPoint(const Ray& ray, const Point& point);
  188. Point ClosestPoint(const Point& point, const Sphere& sphere);
  189. Point ClosestPoint(const Point& point, const AABB& aabb);
  190. Point ClosestPoint(const Point& point, const OBB& obb);
  191. Point ClosestPoint(const Point& point, const Plane& plane);
  192. Point ClosestPoint(const Point& point, const Line& line);
  193. Point ClosestPoint(const Point& point, const Ray& ray);
  194. Point ClosestPoint(const Point& p, const Triangle& t);
  195. Interval GetInterval(const AABB& aabb, const vec3& axis);
  196. Interval GetInterval(const OBB& obb, const vec3& axis);
  197. Interval GetInterval(const Triangle& triangle, const vec3& axis);
  198. bool OverlapOnAxis(const AABB& aabb, const OBB& obb, const vec3& axis);
  199. bool OverlapOnAxis(const OBB& obb1, const OBB& obb2, const vec3& axis);
  200. bool OverlapOnAxis(const AABB& aabb, const Triangle& triangle, const vec3& axis);
  201. bool OverlapOnAxis(const OBB& obb, const Triangle& triangle, const vec3& axis);
  202. bool OverlapOnAxis(const Triangle& t1, const Triangle& t2, const vec3& axis);
  203. bool SphereSphere(const Sphere& s1, const Sphere& s2);
  204. bool SphereAABB(const Sphere& sphere, const AABB& aabb);
  205. bool SphereOBB(const Sphere& sphere, const OBB& obb);
  206. bool SpherePlane(const Sphere& sphere, const Plane& plane);
  207. bool AABBAABB(const AABB& aabb1, const AABB& aabb2);
  208. bool AABBOBB(const AABB& aabb, const OBB& obb);
  209. bool AABBPlane(const AABB& aabb, const Plane& plane);
  210. bool OBBOBB(const OBB& obb1, const OBB& obb2);
  211. bool OBBPlane(const OBB& obb, const Plane& plane);
  212. bool PlanePlane(const Plane& plane1, const Plane& plane2);
  213. #define AABBSphere(aabb, sphere) \
  214. SphereAABB(Sphere, AABB)
  215. #define OBBSphere(obb, sphere) \
  216. SphereOBB(sphere, obb)
  217. #define PlaneSphere(plane, sphere) \
  218. SpherePlane(sphere, plane)
  219. #define OBBAABB(obb, aabb) \
  220. AABBOBB(aabb, obb)
  221. #define PlaneAABB(plane, aabb) \
  222. AABBPlane(aabb, plane)
  223. #define PlaneOBB(plane, obb) \
  224. OBBPlane(obb, plane)
  225. bool Raycast(const Sphere& sphere, const Ray& ray, RaycastResult* outResult);
  226. bool Raycast(const AABB& aabb, const Ray& ray, RaycastResult* outResult);
  227. bool Raycast(const OBB& obb, const Ray& ray, RaycastResult* outResult);
  228. bool Raycast(const Plane& plane, const Ray& ray, RaycastResult* outResult);
  229. bool Raycast(const Triangle& triangle, const Ray& ray, RaycastResult* outResult);
  230. bool Linetest(const Sphere& sphere, const Line& line);
  231. bool Linetest(const AABB& aabb, const Line& line);
  232. bool Linetest(const OBB& obb, const Line& line);
  233. bool Linetest(const Plane& plane, const Line& line);
  234. bool Linetest(const Triangle& triangle, const Line& line);
  235. bool Raycast(const Ray& ray, const Sphere& sphere, RaycastResult* outResult);
  236. bool Raycast(const Ray& ray, const AABB& aabb, RaycastResult* outResult);
  237. bool Raycast(const Ray& ray, const OBB& obb, RaycastResult* outResult);
  238. bool Raycast(const Ray& ray, const Plane& plane, RaycastResult* outResult);
  239. bool Linetest(const Line& line, const Sphere& sphere);
  240. bool Linetest(const Line& line, const AABB& aabb);
  241. bool Linetest(const Line& line, const OBB& obb);
  242. bool Linetest(const Line& line, const Plane& plane);
  243. vec3 BarycentricOptimized(const Point& p, const Triangle& t);
  244. vec3 Centroid(const Triangle& t);
  245. bool PointInTriangle(const Point& p, const Triangle& t);
  246. Plane FromTriangle(const Triangle& t);
  247. Point ClosestPoint(const Triangle& t, const Point& p);
  248. bool TriangleSphere(const Triangle& t, const Sphere& s);
  249. bool TriangleAABB(const Triangle& t, const AABB& a);
  250. bool TriangleOBB(const Triangle& t, const OBB& o);
  251. bool TriangleTriangle(const Triangle& t1, const Triangle& t2);
  252. bool TriangleTriangleRobust(const Triangle& t1, const Triangle& t2);
  253. bool TrianglePlane(const Triangle& t, const Plane& p);
  254. #define SphereTriangle(s, t) \
  255. TriangleSphere(t, s)
  256. #define AABBTriangle(a, t) \
  257. TriangleAABB(t, a)
  258. #define OBBTriangle(o, t) \
  259. TriangleOBB(t, o)
  260. #define PlaneTriangle(p, t) \
  261. TrianglePlane(t, p)
  262. // A - Edge 0, Point 0
  263. // B - Edge 0, Point 1
  264. // C - Edge 1, Point 0
  265. // D - Edge 1, Point 1
  266. vec3 SatCrossEdge(const vec3& a, const vec3& b, const vec3& c, const vec3& d);
  267. vec3 Barycentric(const Point& p, const Triangle& t);
  268. void AccelerateMesh(Mesh& mesh);
  269. void SplitBVHNode(BVHNode* node, const Mesh& model, int depth);
  270. void FreeBVHNode(BVHNode* node);
  271. bool Linetest(const Mesh& mesh, const Line& line);
  272. bool MeshSphere(const Mesh& mesh, const Sphere& sphere);
  273. bool MeshAABB(const Mesh& mesh, const AABB& aabb);
  274. bool MeshOBB(const Mesh& mesh, const OBB& obb);
  275. bool MeshPlane(const Mesh& mesh, const Plane& plane);
  276. bool MeshTriangle(const Mesh& mesh, const Triangle& triangle);
  277. float MeshRay(const Mesh& mesh, const Ray& ray);
  278. float Raycast(const Mesh& mesh, const Ray& ray);
  279. float Raycast(const Model& mesh, const Ray& ray);
  280. mat4 GetWorldMatrix(const Model& model);
  281. OBB GetOBB(const Model& model);
  282. float ModelRay(const Model& model, const Ray& ray);
  283. bool Linetest(const Model& model, const Line& line);
  284. bool ModelSphere(const Model& model, const Sphere& sphere);
  285. bool ModelAABB(const Model& model, const AABB& aabb);
  286. bool ModelOBB(const Model& model, const OBB& obb);
  287. bool ModelPlane(const Model& model, const Plane& plane);
  288. bool ModelTriangle(const Model& model, const Triangle& triangle);
  289. float Classify(const AABB& aabb, const Plane& plane);
  290. float Classify(const OBB& obb, const Plane& plane);
  291. bool Intersects(const Frustum& f, const Point& p);
  292. bool Intersects(const Frustum& f, const Sphere& s);
  293. bool Intersects(const Frustum& f, const AABB& aabb);
  294. bool Intersects(const Frustum& f, const OBB& obb);
  295. vec3 Unproject(const vec3& viewportPoint, const vec2& viewportOrigin, const vec2& viewportSize, const mat4& view, const mat4& projection);
  296. Ray GetPickRay(const vec2& viewportPoint, const vec2& viewportOrigin, const vec2& viewportSize, const mat4& view, const mat4& projection);
  297. // Chapter 15
  298. typedef struct CollisionManifold {
  299. bool colliding;
  300. vec3 normal;
  301. float depth;
  302. std::vector<vec3> contacts;
  303. };
  304. void ResetCollisionManifold(CollisionManifold* result);
  305. std::vector<Point> GetVertices(const OBB& obb);
  306. std::vector<Line> GetEdges(const OBB& obb);
  307. std::vector<Plane> GetPlanes(const OBB& obb);
  308. bool ClipToPlane(const Plane& plane, const Line& line, Point* outPoint);
  309. std::vector<Point> ClipEdgesToOBB(const std::vector<Line>& edges, const OBB& obb);
  310. float PenetrationDepth(const OBB& o1, const OBB& o2, const vec3& axis, bool* outShouldFlip);
  311. CollisionManifold FindCollisionFeatures(const Sphere& A, const Sphere& B);
  312. CollisionManifold FindCollisionFeatures(const OBB& A, const Sphere& B);
  313. CollisionManifold FindCollisionFeatures(const OBB& A, const OBB& B);
  314. #endif

Geometry3D.cpp 

  1. #include "Geometry3D.h"
  2. #include <cmath>
  3. #include <cfloat>
  4. #include <list>
  5. #define CMP(x, y) \
  6. (fabsf(x - y) <= FLT_EPSILON * fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))))
  7. float Length(const Line& line) {
  8. return Magnitude(line.start - line.end);
  9. }
  10. float LengthSq(const Line& line) {
  11. return MagnitudeSq(line.start - line.end);
  12. }
  13. Ray FromPoints(const Point& from, const Point& to) {
  14. return Ray(
  15. from,
  16. Normalized(to - from)
  17. );
  18. }
  19. vec3 GetMin(const AABB& aabb) {
  20. vec3 p1 = aabb.position + aabb.size;
  21. vec3 p2 = aabb.position - aabb.size;
  22. return vec3(fminf(p1.x, p2.x), fminf(p1.y, p2.y), fminf(p1.z, p2.z));
  23. }
  24. vec3 GetMax(const AABB& aabb) {
  25. vec3 p1 = aabb.position + aabb.size;
  26. vec3 p2 = aabb.position - aabb.size;
  27. return vec3(fmaxf(p1.x, p2.x), fmaxf(p1.y, p2.y), fmaxf(p1.z, p2.z));
  28. }
  29. AABB FromMinMax(const vec3& min, const vec3& max) {
  30. return AABB((min + max) * 0.5f, (max - min) * 0.5f);
  31. }
  32. float PlaneEquation(const Point& point, const Plane& plane) {
  33. return Dot(point, plane.normal) - plane.distance;
  34. }
  35. float PlaneEquation(const Plane& plane, const Point& point) {
  36. return Dot(point, plane.normal) - plane.distance;
  37. }
  38. std::ostream& operator<<(std::ostream& os, const Line& shape) {
  39. os << "start: (" << shape.start.x << ", " << shape.start.y << ", " << shape.start.z << "), end: (";
  40. os << shape.end.x << ", " << shape.end.y << ", " << shape.end.z << ")";
  41. return os;
  42. }
  43. std::ostream& operator<<(std::ostream& os, const Ray& shape) {
  44. os << "origin: (" << shape.origin.x << ", " << shape.origin.y << ", " << shape.origin.z << "), ";
  45. os << "direction: (" << shape.direction.x << ", " << shape.direction.y << ", " << shape.direction.z << ")";
  46. return os;
  47. }
  48. std::ostream& operator<<(std::ostream& os, const Sphere& shape) {
  49. os << "position:" << shape.position.x << ", " << shape.position.y << ", " << shape.position.z << "), ";
  50. os << "radius: " << shape.radius;
  51. return os;
  52. }
  53. std::ostream& operator<<(std::ostream& os, const AABB& shape) {
  54. vec3 min = GetMin(shape);
  55. vec3 max = GetMax(shape);
  56. os << "min: (" << min.x << ", " << min.y << ", " << min.z << "), ";
  57. os << "max: (" << max.x << ", " << max.y << ", " << max.z << ")";
  58. return os;
  59. }
  60. std::ostream& operator<<(std::ostream& os, const Plane& shape) {
  61. os << "normal: (" << shape.normal.x << ", " << shape.normal.y << ", " << shape.normal.z << "), ";
  62. os << "distance: " << shape.distance;
  63. return os;
  64. }
  65. std::ostream& operator<<(std::ostream& os, const Triangle& shape) {
  66. os << "a: (" << shape.a.x << ", " << shape.a.y << ", " << shape.a.z << "), ";
  67. os << "b: (" << shape.b.x << ", " << shape.b.y << ", " << shape.b.z << "), ";
  68. os << "c: (" << shape.c.x << ", " << shape.c.y << ", " << shape.c.z << ")";
  69. return os;
  70. }
  71. std::ostream& operator<<(std::ostream& os, const OBB& shape) {
  72. os << "position:" << shape.position.x << ", " << shape.position.y << ", " << shape.position.z << "), ";
  73. os << "size:" << shape.size.x << ", " << shape.size.y << ", " << shape.size.z << "), ";
  74. os << "x basis:" << shape.orientation._11 << ", " << shape.orientation._21 << ", " << shape.orientation._31 << "), ";
  75. os << "y basis:" << shape.orientation._12 << ", " << shape.orientation._22 << ", " << shape.orientation._32 << "), ";
  76. os << "z basis:" << shape.orientation._13 << ", " << shape.orientation._23 << ", " << shape.orientation._33 << ")";
  77. return os;
  78. }
  79. bool PointInSphere(const Point& point, const Sphere& sphere) {
  80. return MagnitudeSq(point - sphere.position) < sphere.radius * sphere.radius;
  81. }
  82. bool PointOnPlane(const Point& point, const Plane& plane) {
  83. // This should probably use an epsilon!
  84. //return Dot(point, plane.normal) - plane.distance == 0.0f;
  85. return CMP(Dot(point, plane.normal) - plane.distance, 0.0f);
  86. }
  87. bool PointInAABB(const Point& point, const AABB& aabb) {
  88. Point min = GetMin(aabb);
  89. Point max = GetMax(aabb);
  90. if (point.x < min.x || point.y < min.y || point.z < min.z) {
  91. return false;
  92. }
  93. if (point.x > max.x || point.y > max.y || point.z > max.z) {
  94. return false;
  95. }
  96. return true;
  97. }
  98. bool PointInOBB(const Point& point, const OBB& obb) {
  99. vec3 dir = point - obb.position;
  100. for (int i = 0; i < 3; ++i) {
  101. const float* orientation = &obb.orientation.asArray[i * 3];
  102. vec3 axis(orientation[0], orientation[1], orientation[2]);
  103. float distance = Dot(dir, axis);
  104. if (distance > obb.size.asArray[i]) {
  105. return false;
  106. }
  107. if (distance < -obb.size.asArray[i]) {
  108. return false;
  109. }
  110. }
  111. return true;
  112. }
  113. Point ClosestPoint(const Sphere& sphere, const Point& point) {
  114. vec3 sphereToPoint = point - sphere.position;
  115. Normalize(sphereToPoint);
  116. sphereToPoint = sphereToPoint * sphere.radius;
  117. return sphereToPoint + sphere.position;
  118. }
  119. Point ClosestPoint(const AABB& aabb, const Point& point) {
  120. Point result = point;
  121. Point min = GetMin(aabb);
  122. Point max = GetMax(aabb);
  123. result.x = (result.x < min.x) ? min.x : result.x;
  124. result.y = (result.y < min.x) ? min.y : result.y;
  125. result.z = (result.z < min.x) ? min.z : result.z;
  126. result.x = (result.x > max.x) ? max.x : result.x;
  127. result.y = (result.y > max.x) ? max.y : result.y;
  128. result.z = (result.z > max.x) ? max.z : result.z;
  129. return result;
  130. }
  131. Point ClosestPoint(const OBB& obb, const Point& point) {
  132. Point result = obb.position;
  133. vec3 dir = point - obb.position;
  134. for (int i = 0; i < 3; ++i) {
  135. const float* orientation = &obb.orientation.asArray[i * 3];
  136. vec3 axis(orientation[0], orientation[1], orientation[2]);
  137. float distance = Dot(dir, axis);
  138. if (distance > obb.size.asArray[i]) {
  139. distance = obb.size.asArray[i];
  140. }
  141. if (distance < -obb.size.asArray[i]) {
  142. distance = -obb.size.asArray[i];
  143. }
  144. result = result + (axis * distance);
  145. }
  146. return result;
  147. }
  148. Point ClosestPoint(const Plane& plane, const Point& point) {
  149. // This works assuming plane.Normal is normalized, which it should be
  150. float distance = Dot(plane.normal, point) - plane.distance;
  151. // If the plane normal wasn't normalized, we'd need this:
  152. // distance = distance / DOT(plane.Normal, plane.Normal);
  153. return point - plane.normal * distance;
  154. }
  155. bool PointOnLine(const Point& point, const Line& line) {
  156. Point closest = ClosestPoint(line, point);
  157. float distanceSq = MagnitudeSq(closest - point);
  158. return CMP(distanceSq, 0.0f);
  159. }
  160. Point ClosestPoint(const Line& line, const Point& point) {
  161. vec3 lVec = line.end - line.start; // Line Vector
  162. // Project "point" onto the "Line Vector", computing:
  163. // closest(t) = start + t * (end - start)
  164. // T is how far along the line the projected point is
  165. float t = Dot(point - line.start, lVec) / Dot(lVec, lVec);
  166. // Clamp t to the 0 to 1 range
  167. t = fmaxf(t, 0.0f);
  168. t = fminf(t, 1.0f);
  169. // Return projected position of t
  170. return line.start + lVec * t;
  171. }
  172. bool PointOnRay(const Point& point, const Ray& ray) {
  173. if (point == ray.origin) {
  174. return true;
  175. }
  176. vec3 norm = point - ray.origin;
  177. Normalize(norm);
  178. float diff = Dot(norm, ray.direction); // Direction is normalized
  179. // If BOTH vectors point in the same direction, diff should be 1
  180. return CMP(diff, 1.0f);
  181. }
  182. Point ClosestPoint(const Ray& ray, const Point& point) {
  183. // Project point onto ray,
  184. float t = Dot(point - ray.origin, ray.direction);
  185. // Not needed if direction is normalized!
  186. // t /= Dot(ray.direction, ray.direction);
  187. // We only want to clamp t in the positive direction.
  188. // The ray extends infinatley in this direction!
  189. t = fmaxf(t, 0.0f);
  190. // Compute the projected position from the clamped t
  191. // Notice we multiply r.Normal by t, not AB.
  192. // This is becuase we want the ray in the direction
  193. // of the normal, which technically the line segment is
  194. // but this is much more explicit and easy to read.
  195. return Point(ray.origin + ray.direction * t);
  196. }
  197. bool PointInPlane(const Point& point, const Plane& plane) {
  198. return PointOnPlane(point, plane);
  199. }
  200. bool PointInLine(const Point& point, const Line& line) {
  201. return PointOnLine(point, line);
  202. }
  203. bool PointInRay(const Point& point, const Ray& ray) {
  204. return PointOnRay(point, ray);
  205. }
  206. bool ContainsPoint(const Sphere& sphere, const Point& point) {
  207. return PointInSphere(point, sphere);
  208. }
  209. bool ContainsPoint(const Point& point, const Sphere& sphere) {
  210. return PointInSphere(point, sphere);
  211. }
  212. bool ContainsPoint(const AABB& aabb, const Point& point) {
  213. return PointInAABB(point, aabb);
  214. }
  215. bool ContainsPoint(const Point& point, const AABB& aabb) {
  216. return PointInAABB(point, aabb);
  217. }
  218. bool ContainsPoint(const Point& point, const OBB& obb) {
  219. return PointInOBB(point, obb);
  220. }
  221. bool ContainsPoint(const OBB& obb, const Point& point) {
  222. return PointInOBB(point, obb);
  223. }
  224. bool ContainsPoint(const Point& point, const Plane& plane) {
  225. return PointOnPlane(point, plane);
  226. }
  227. bool ContainsPoint(const Plane& plane, const Point& point) {
  228. return PointOnPlane(point, plane);
  229. }
  230. bool ContainsPoint(const Point& point, const Line& line) {
  231. return PointOnLine(point, line);
  232. }
  233. bool ContainsPoint(const Line& line, const Point& point) {
  234. return PointOnLine(point, line);
  235. }
  236. bool ContainsPoint(const Point& point, const Ray& ray) {
  237. return PointOnRay(point, ray);
  238. }
  239. bool ContainsPoint(const Ray& ray, const Point& point) {
  240. return PointOnRay(point, ray);
  241. }
  242. Point ClosestPoint(const Point& point, const Sphere& sphere) {
  243. return ClosestPoint(sphere, point);
  244. }
  245. Point ClosestPoint(const Point& point, const AABB& aabb) {
  246. return ClosestPoint(aabb, point);
  247. }
  248. Point ClosestPoint(const Point& point, const OBB& obb) {
  249. return ClosestPoint(obb, point);
  250. }
  251. Point ClosestPoint(const Point& point, const Plane& plane) {
  252. return ClosestPoint(plane, point);
  253. }
  254. Point ClosestPoint(const Point& point, const Line& line) {
  255. return ClosestPoint(line, point);
  256. }
  257. Point ClosestPoint(const Point& point, const Ray& ray) {
  258. return ClosestPoint(ray, point);
  259. }
  260. Point ClosestPoint(const Point& p, const Triangle& t) {
  261. return ClosestPoint(t, p);
  262. }
  263. bool SphereSphere(const Sphere& s1, const Sphere& s2) {
  264. float radiiSum = s1.radius + s2.radius;
  265. float sqDistance = MagnitudeSq(s1.position - s2.position);
  266. return sqDistance < radiiSum * radiiSum;
  267. }
  268. bool SphereAABB(const Sphere& sphere, const AABB& aabb) {
  269. Point closestPoint = ClosestPoint(aabb, sphere.position);
  270. float distSq = MagnitudeSq(sphere.position - closestPoint);
  271. float radiusSq = sphere.radius * sphere.radius;
  272. return distSq < radiusSq;
  273. }
  274. bool SphereOBB(const Sphere& sphere, const OBB& obb) {
  275. Point closestPoint = ClosestPoint(obb, sphere.position);
  276. float distSq = MagnitudeSq(sphere.position - closestPoint);
  277. float radiusSq = sphere.radius * sphere.radius;
  278. return distSq < radiusSq;
  279. }
  280. bool SpherePlane(const Sphere& sphere, const Plane& plane) {
  281. Point closestPoint = ClosestPoint(plane, sphere.position);
  282. float distSq = MagnitudeSq(sphere.position - closestPoint);
  283. float radiusSq = sphere.radius * sphere.radius;
  284. return distSq < radiusSq;
  285. }
  286. bool AABBAABB(const AABB& aabb1, const AABB& aabb2) {
  287. Point aMin = GetMin(aabb1);
  288. Point aMax = GetMax(aabb1);
  289. Point bMin = GetMin(aabb2);
  290. Point bMax = GetMax(aabb2);
  291. return (aMin.x <= bMax.x && aMax.x >= bMin.x) &&
  292. (aMin.y <= bMax.y && aMax.y >= bMin.y) &&
  293. (aMin.z <= bMax.z && aMax.z >= bMin.z);
  294. }
  295. bool AABBOBB(const AABB& aabb, const OBB& obb) {
  296. const float* o = obb.orientation.asArray;
  297. vec3 test[15] = {
  298. vec3(1, 0, 0), // AABB axis 1
  299. vec3(0, 1, 0), // AABB axis 2
  300. vec3(0, 0, 1), // AABB axis 3
  301. vec3(o[0], o[1], o[2]),
  302. vec3(o[3], o[4], o[5]),
  303. vec3(o[6], o[7], o[8])
  304. };
  305. for (int i = 0; i < 3; ++i) { // Fill out rest of axis
  306. test[6 + i * 3 + 0] = Cross(test[i], test[0]);
  307. test[6 + i * 3 + 1] = Cross(test[i], test[1]);
  308. test[6 + i * 3 + 2] = Cross(test[i], test[2]);
  309. }
  310. for (int i = 0; i < 15; ++i) {
  311. if (!OverlapOnAxis(aabb, obb, test[i])) {
  312. return false; // Seperating axis found
  313. }
  314. }
  315. return true; // Seperating axis not found
  316. }
  317. bool OverlapOnAxis(const AABB& aabb, const OBB& obb, const vec3& axis) {
  318. Interval a = GetInterval(aabb, axis);
  319. Interval b = GetInterval(obb, axis);
  320. return ((b.min <= a.max) && (a.min <= b.max));
  321. }
  322. bool OverlapOnAxis(const OBB& obb1, const OBB& obb2, const vec3& axis) {
  323. Interval a = GetInterval(obb1, axis);
  324. Interval b = GetInterval(obb1, axis);
  325. return ((b.min <= a.max) && (a.min <= b.max));
  326. }
  327. bool OverlapOnAxis(const AABB& aabb, const Triangle& triangle, const vec3& axis) {
  328. Interval a = GetInterval(aabb, axis);
  329. Interval b = GetInterval(triangle, axis);
  330. return ((b.min <= a.max) && (a.min <= b.max));
  331. }
  332. bool OverlapOnAxis(const OBB& obb, const Triangle& triangle, const vec3& axis) {
  333. Interval a = GetInterval(obb, axis);
  334. Interval b = GetInterval(triangle, axis);
  335. return ((b.min <= a.max) && (a.min <= b.max));
  336. }
  337. bool OverlapOnAxis(const Triangle& t1, const Triangle& t2, const vec3& axis) {
  338. Interval a = GetInterval(t1, axis);
  339. Interval b = GetInterval(t2, axis);
  340. return ((b.min <= a.max) && (a.min <= b.max));
  341. }
  342. Interval GetInterval(const Triangle& triangle, const vec3& axis) {
  343. Interval result;
  344. result.min = Dot(axis, triangle.points[0]);
  345. result.max = result.min;
  346. for (int i = 1; i < 3; ++i) {
  347. float value = Dot(axis, triangle.points[i]);
  348. result.min = fminf(result.min, value);
  349. result.max = fmaxf(result.max, value);
  350. }
  351. return result;
  352. }
  353. Interval GetInterval(const OBB& obb, const vec3& axis) {
  354. vec3 vertex[8];
  355. vec3 C = obb.position; // OBB Center
  356. vec3 E = obb.size; // OBB Extents
  357. const float* o = obb.orientation.asArray;
  358. vec3 A[] = { // OBB Axis
  359. vec3(o[0], o[1], o[2]),
  360. vec3(o[3], o[4], o[5]),
  361. vec3(o[6], o[7], o[8]),
  362. };
  363. vertex[0] = C + A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  364. vertex[1] = C - A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  365. vertex[2] = C + A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  366. vertex[3] = C + A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  367. vertex[4] = C - A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  368. vertex[5] = C + A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  369. vertex[6] = C - A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  370. vertex[7] = C - A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  371. Interval result;
  372. result.min = result.max = Dot(axis, vertex[0]);
  373. for (int i = 1; i < 8; ++i) {
  374. float projection = Dot(axis, vertex[i]);
  375. result.min = (projection < result.min) ? projection : result.min;
  376. result.max = (projection > result.max) ? projection : result.max;
  377. }
  378. return result;
  379. }
  380. Interval GetInterval(const AABB& aabb, const vec3& axis) {
  381. vec3 i = GetMin(aabb);
  382. vec3 a = GetMax(aabb);
  383. vec3 vertex[8] = {
  384. vec3(i.x, a.y, a.z),
  385. vec3(i.x, a.y, i.z),
  386. vec3(i.x, i.y, a.z),
  387. vec3(i.x, i.y, i.z),
  388. vec3(a.x, a.y, a.z),
  389. vec3(a.x, a.y, i.z),
  390. vec3(a.x, i.y, a.z),
  391. vec3(a.x, i.y, i.z)
  392. };
  393. Interval result;
  394. result.min = result.max = Dot(axis, vertex[0]);
  395. for (int i = 1; i < 8; ++i) {
  396. float projection = Dot(axis, vertex[i]);
  397. result.min = (projection < result.min) ? projection : result.min;
  398. result.max = (projection > result.max) ? projection : result.max;
  399. }
  400. return result;
  401. }
  402. bool AABBPlane(const AABB& aabb, const Plane& plane) {
  403. // Project the half extents of the AABB onto the plane normal
  404. float pLen =aabb.size.x * fabsf(plane.normal.x) +
  405. aabb.size.y * fabsf(plane.normal.y) +
  406. aabb.size.z * fabsf(plane.normal.z);
  407. // Find the distance from the center of the AABB to the plane
  408. float dist = Dot(plane.normal, aabb.position) - plane.distance;
  409. // Intersection occurs if the distance falls within the projected side
  410. return fabsf(dist) <= pLen;
  411. }
  412. bool OBBOBB(const OBB& obb1, const OBB& obb2) {
  413. const float* o1 = obb1.orientation.asArray;
  414. const float* o2 = obb2.orientation.asArray;
  415. vec3 test[15] = {
  416. vec3(o1[0], o1[1], o1[2]),
  417. vec3(o1[3], o1[4], o1[5]),
  418. vec3(o1[6], o1[7], o1[8]),
  419. vec3(o2[0], o2[1], o2[2]),
  420. vec3(o2[3], o2[4], o2[5]),
  421. vec3(o2[6], o2[7], o2[8])
  422. };
  423. for (int i = 0; i < 3; ++i) { // Fill out rest of axis
  424. test[6 + i * 3 + 0] = Cross(test[i], test[0]);
  425. test[6 + i * 3 + 1] = Cross(test[i], test[1]);
  426. test[6 + i * 3 + 2] = Cross(test[i], test[2]);
  427. }
  428. for (int i = 0; i < 15; ++i) {
  429. if (!OverlapOnAxis(obb1, obb2, test[i])) {
  430. return false; // Seperating axis found
  431. }
  432. }
  433. return true; // Seperating axis not found
  434. }
  435. bool OBBPlane(const OBB& obb, const Plane& plane) {
  436. // Local variables for readability only
  437. const float* o = obb.orientation.asArray;
  438. vec3 rot[] = { // rotation / orientation
  439. vec3(o[0], o[1], o[2]),
  440. vec3(o[3], o[4], o[5]),
  441. vec3(o[6], o[7], o[8]),
  442. };
  443. vec3 normal = plane.normal;
  444. // Project the half extents of the AABB onto the plane normal
  445. float pLen =obb.size.x * fabsf(Dot(normal, rot[0])) +
  446. obb.size.y * fabsf(Dot(normal, rot[1])) +
  447. obb.size.z * fabsf(Dot(normal, rot[2]));
  448. // Find the distance from the center of the OBB to the plane
  449. float dist = Dot(plane.normal, obb.position) - plane.distance;
  450. // Intersection occurs if the distance falls within the projected side
  451. return fabsf(dist) <= pLen;
  452. }
  453. bool PlanePlane(const Plane& plane1, const Plane& plane2) {
  454. // Compute direction of intersection line
  455. vec3 d = Cross(plane1.normal, plane2.normal);
  456. // Check the length of the direction line
  457. // if the length is 0, no intersection happened
  458. return !(CMP(Dot(d, d), 0));
  459. // We could have used the dot product here, instead of the cross product
  460. }
  461. bool Raycast(const Sphere& sphere, const Ray& ray, RaycastResult* outResult) {
  462. ResetRaycastResult(outResult);
  463. vec3 e = sphere.position - ray.origin;
  464. float rSq = sphere.radius * sphere.radius;
  465. float eSq = MagnitudeSq(e);
  466. float a = Dot(e, ray.direction); // ray.direction is assumed to be normalized
  467. float bSq = /*sqrtf(*/eSq - (a * a)/*)*/;
  468. float f = sqrt(fabsf((rSq)- /*(b * b)*/bSq));
  469. // Assume normal intersection!
  470. float t = a - f;
  471. // No collision has happened
  472. if (rSq - (eSq - a * a) < 0.0f) {
  473. return false;
  474. }
  475. // Ray starts inside the sphere
  476. else if (eSq < rSq) {
  477. // Just reverse direction
  478. t = a + f;
  479. }
  480. if (outResult != 0) {
  481. outResult->t = t;
  482. outResult->hit = true;
  483. outResult->point = ray.origin + ray.direction * t;
  484. outResult->normal = Normalized(outResult->point - sphere.position);
  485. }
  486. return true;
  487. }
  488. bool Raycast(const OBB& obb, const Ray& ray, RaycastResult* outResult) {
  489. ResetRaycastResult(outResult);
  490. const float* o = obb.orientation.asArray;
  491. const float* size = obb.size.asArray;
  492. vec3 p = obb.position - ray.origin;
  493. vec3 X(o[0], o[1], o[2]);
  494. vec3 Y(o[3], o[4], o[5]);
  495. vec3 Z(o[6], o[7], o[8]);
  496. vec3 f(
  497. Dot(X, ray.direction),
  498. Dot(Y, ray.direction),
  499. Dot(Z, ray.direction)
  500. );
  501. vec3 e(
  502. Dot(X, p),
  503. Dot(Y, p),
  504. Dot(Z, p)
  505. );
  506. #if 1
  507. float t[6] = { 0, 0, 0, 0, 0, 0 };
  508. for (int i = 0; i < 3; ++i) {
  509. if (CMP(f[i], 0)) {
  510. if (-e[i] - size[i] > 0 || -e[i] + size[i] < 0) {
  511. return false;
  512. }
  513. f[i] = 0.00001f; // Avoid div by 0!
  514. }
  515. t[i * 2 + 0] = (e[i] + size[i]) / f[i]; // tmin[x, y, z]
  516. t[i * 2 + 1] = (e[i] - size[i]) / f[i]; // tmax[x, y, z]
  517. }
  518. float tmin = fmaxf(fmaxf(fminf(t[0], t[1]), fminf(t[2], t[3])), fminf(t[4], t[5]));
  519. float tmax = fminf(fminf(fmaxf(t[0], t[1]), fmaxf(t[2], t[3])), fmaxf(t[4], t[5]));
  520. #else
  521. // The above loop simplifies the below if statements
  522. // this is done to make sure the sample fits into the book
  523. if (CMP(f.x, 0)) {
  524. if (-e.x - obb.size.x > 0 || -e.x + obb.size.x < 0) {
  525. return -1;
  526. }
  527. f.x = 0.00001f; // Avoid div by 0!
  528. }
  529. else if (CMP(f.y, 0)) {
  530. if (-e.y - obb.size.y > 0 || -e.y + obb.size.y < 0) {
  531. return -1;
  532. }
  533. f.y = 0.00001f; // Avoid div by 0!
  534. }
  535. else if (CMP(f.z, 0)) {
  536. if (-e.z - obb.size.z > 0 || -e.z + obb.size.z < 0) {
  537. return -1;
  538. }
  539. f.z = 0.00001f; // Avoid div by 0!
  540. }
  541. float t1 = (e.x + obb.size.x) / f.x;
  542. float t2 = (e.x - obb.size.x) / f.x;
  543. float t3 = (e.y + obb.size.y) / f.y;
  544. float t4 = (e.y - obb.size.y) / f.y;
  545. float t5 = (e.z + obb.size.z) / f.z;
  546. float t6 = (e.z - obb.size.z) / f.z;
  547. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  548. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  549. #endif
  550. // if tmax < 0, ray is intersecting AABB
  551. // but entire AABB is behing it's origin
  552. if (tmax < 0) {
  553. return false;
  554. }
  555. // if tmin > tmax, ray doesn't intersect AABB
  556. if (tmin > tmax) {
  557. return false;
  558. }
  559. // If tmin is < 0, tmax is closer
  560. float t_result = tmin;
  561. if (tmin < 0.0f) {
  562. t_result = tmax;
  563. }
  564. if (outResult != 0) {
  565. outResult->hit = true;
  566. outResult->t = t_result;
  567. outResult->point = ray.origin + ray.direction * t_result;
  568. vec3 normals[] = {
  569. X, // +x
  570. X * -1.0f, // -x
  571. Y, // +y
  572. Y * -1.0f, // -y
  573. Z, // +z
  574. Z * -1.0f // -z
  575. };
  576. for (int i = 0; i < 6; ++i) {
  577. if (CMP(t_result, t[i])) {
  578. outResult->normal = Normalized(normals[i]);
  579. }
  580. }
  581. }
  582. return true;
  583. }
  584. void ResetRaycastResult(RaycastResult* outResult) {
  585. if (outResult != 0) {
  586. outResult->t = -1;
  587. outResult->hit = false;
  588. outResult->normal = vec3(0, 0, 1);
  589. outResult->point = vec3(0, 0, 0);
  590. }
  591. }
  592. bool Raycast(const AABB& aabb, const Ray& ray, RaycastResult* outResult) {
  593. ResetRaycastResult(outResult);
  594. vec3 min = GetMin(aabb);
  595. vec3 max = GetMax(aabb);
  596. // Any component of direction could be 0!
  597. // Address this by using a small number, close to
  598. // 0 in case any of directions components are 0
  599. float t1 = (min.x - ray.origin.x) / (CMP(ray.direction.x, 0.0f) ? 0.00001f : ray.direction.x);
  600. float t2 = (max.x - ray.origin.x) / (CMP(ray.direction.x, 0.0f) ? 0.00001f : ray.direction.x);
  601. float t3 = (min.y - ray.origin.y) / (CMP(ray.direction.y, 0.0f) ? 0.00001f : ray.direction.y);
  602. float t4 = (max.y - ray.origin.y) / (CMP(ray.direction.y, 0.0f) ? 0.00001f : ray.direction.y);
  603. float t5 = (min.z - ray.origin.z) / (CMP(ray.direction.z, 0.0f) ? 0.00001f : ray.direction.z);
  604. float t6 = (max.z - ray.origin.z) / (CMP(ray.direction.z, 0.0f) ? 0.00001f : ray.direction.z);
  605. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  606. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  607. // if tmax < 0, ray is intersecting AABB
  608. // but entire AABB is behing it's origin
  609. if (tmax < 0) {
  610. return false;
  611. }
  612. // if tmin > tmax, ray doesn't intersect AABB
  613. if (tmin > tmax) {
  614. return false;
  615. }
  616. float t_result = tmin;
  617. // If tmin is < 0, tmax is closer
  618. if (tmin < 0.0f) {
  619. t_result = tmax;
  620. }
  621. if (outResult != 0) {
  622. outResult->t = t_result;
  623. outResult->hit = true;
  624. outResult->point = ray.origin + ray.direction * t_result;
  625. vec3 normals[] = {
  626. vec3(-1, 0, 0),
  627. vec3(1, 0, 0),
  628. vec3(0, -1, 0),
  629. vec3(0, 1, 0),
  630. vec3(0, 0, -1),
  631. vec3(0, 0, 1)
  632. };
  633. float t[] = { t1, t2, t3, t4, t5, t6 };
  634. for (int i = 0; i < 6; ++i) {
  635. if (CMP(t_result, t[i])) {
  636. outResult->normal = normals[i];
  637. }
  638. }
  639. }
  640. return true;
  641. }
  642. bool Raycast(const Plane& plane, const Ray& ray, RaycastResult* outResult) {
  643. ResetRaycastResult(outResult);
  644. float nd = Dot(ray.direction, plane.normal);
  645. float pn = Dot(ray.origin, plane.normal);
  646. // nd must be negative, and not 0
  647. // if nd is positive, the ray and plane normals
  648. // point in the same direction. No intersection.
  649. if (nd >= 0.0f) {
  650. return false;
  651. }
  652. float t = (plane.distance - pn) / nd;
  653. // t must be positive
  654. if (t >= 0.0f) {
  655. if (outResult != 0) {
  656. outResult->t = t;
  657. outResult->hit = true;
  658. outResult->point = ray.origin + ray.direction * t;
  659. outResult->normal = Normalized(plane.normal);
  660. }
  661. return true;
  662. }
  663. return false;
  664. }
  665. bool Linetest(const Sphere& sphere, const Line& line) {
  666. Point closest = ClosestPoint(line, sphere.position);
  667. float distSq = MagnitudeSq(sphere.position - closest);
  668. return distSq <= (sphere.radius * sphere.radius);
  669. }
  670. bool Linetest(const Plane& plane, const Line& line) {
  671. vec3 ab = line.end - line.start;
  672. float nA = Dot(plane.normal, line.start);
  673. float nAB = Dot(plane.normal, ab);
  674. if (CMP(nAB, 0)) {
  675. return false;
  676. }
  677. float t = (plane.distance - nA) / nAB;
  678. return t >= 0.0f && t <= 1.0f;
  679. }
  680. bool Linetest(const AABB& aabb, const Line& line) {
  681. Ray ray;
  682. ray.origin = line.start;
  683. ray.direction = Normalized(line.end - line.start);
  684. RaycastResult raycast;
  685. if (!Raycast(aabb, ray, &raycast)) {
  686. return false;
  687. }
  688. float t = raycast.t;
  689. return t >= 0 && t * t <= LengthSq(line);
  690. }
  691. bool Linetest(const OBB& obb, const Line& line) {
  692. if (MagnitudeSq(line.end - line.start) < 0.0000001f) {
  693. return PointInOBB(line.start, obb);
  694. }
  695. Ray ray;
  696. ray.origin = line.start;
  697. ray.direction = Normalized(line.end - line.start);
  698. RaycastResult result;
  699. if (!Raycast(obb, ray, &result)) {
  700. return false;
  701. }
  702. float t = result.t;
  703. return t >= 0 && t * t <= LengthSq(line);
  704. }
  705. bool Raycast(const Ray& ray, const Sphere& sphere, RaycastResult* outResult) {
  706. return Raycast(sphere, ray, outResult);
  707. }
  708. bool Raycast(const Ray& ray, const AABB& aabb, RaycastResult* outResult) {
  709. return Raycast(aabb, ray, outResult);
  710. }
  711. bool Raycast(const Ray& ray, const OBB& obb, RaycastResult* outResult) {
  712. return Raycast(obb, ray, outResult);
  713. }
  714. bool Raycast(const Ray& ray, const Plane& plane, RaycastResult* outResult) {
  715. return Raycast(plane, ray, outResult);
  716. }
  717. bool Linetest(const Line& line, const Sphere& sphere) {
  718. return Linetest(sphere, line);
  719. }
  720. bool Linetest(const Line& line, const AABB& aabb) {
  721. return Linetest(aabb, line);
  722. }
  723. bool Linetest(const Line& line, const OBB& obb) {
  724. return Linetest(obb, line);
  725. }
  726. bool Linetest(const Line& line, const Plane& plane) {
  727. return Linetest(plane, line);
  728. }
  729. vec3 Centroid(const Triangle& t) {
  730. vec3 result;
  731. result.x = t.a.x + t.b.x + t.c.x;
  732. result.y = t.a.y + t.b.y + t.c.y;
  733. result.z = t.a.z + t.b.z + t.c.z;
  734. result = result * (1.0f / 3.0f);
  735. return result;
  736. }
  737. bool PointInTriangle(const Point& p, const Triangle& t) {
  738. // Move the triangle so that the point is
  739. // now at the origin of the triangle
  740. vec3 a = t.a - p;
  741. vec3 b = t.b - p;
  742. vec3 c = t.c - p;
  743. // The point should be moved too, so they are both
  744. // relative, but because we don't use p in the
  745. // equation anymore, we don't need it!
  746. // p -= p; // This would just equal the zero vector!
  747. vec3 normPBC = Cross(b, c); // Normal of PBC (u)
  748. vec3 normPCA = Cross(c, a); // Normal of PCA (v)
  749. vec3 normPAB = Cross(a, b); // Normal of PAB (w)
  750. // Test to see if the normals are facing
  751. // the same direction, return false if not
  752. if (Dot(normPBC, normPCA) < 0.0f) {
  753. return false;
  754. }
  755. else if (Dot(normPBC, normPAB) < 0.0f) {
  756. return false;
  757. }
  758. // All normals facing the same way, return true
  759. return true;
  760. }
  761. vec3 BarycentricOptimized(const Point& p, const Triangle& t) {
  762. vec3 v0 = t.b - t.a;
  763. vec3 v1 = t.c - t.a;
  764. vec3 v2 = p - t.a;
  765. float d00 = Dot(v0, v0);
  766. float d01 = Dot(v0, v1);
  767. float d11 = Dot(v1, v1);
  768. float d20 = Dot(v2, v0);
  769. float d21 = Dot(v2, v1);
  770. float denom = d00 * d11 - d01 * d01;
  771. if (CMP(denom, 0.0f)) {
  772. return vec3();
  773. }
  774. vec3 result;
  775. result.y = (d11 * d20 - d01 * d21) / denom;
  776. result.z = (d00 * d21 - d01 * d20) / denom;
  777. result.x = 1.0f - result.y - result.z;
  778. return result;
  779. }
  780. vec3 Barycentric(const Point& p, const Triangle& t) {
  781. vec3 ap = p - t.a;
  782. vec3 bp = p - t.b;
  783. vec3 cp = p - t.c;
  784. vec3 ab = t.b - t.a;
  785. vec3 ac = t.c - t.a;
  786. vec3 bc = t.c - t.b;
  787. vec3 cb = t.b - t.c;
  788. vec3 ca = t.a - t.c;
  789. vec3 v = ab - Project(ab, cb);
  790. float a = 1.0f - (Dot(v, ap) / Dot(v, ab));
  791. v = bc - Project(bc, ac);
  792. float b = 1.0f - (Dot(v, bp) / Dot(v, bc));
  793. v = ca - Project(ca, ab);
  794. float c = 1.0f - (Dot(v, cp) / Dot(v, ca));
  795. return vec3(a, b, c);
  796. }
  797. Plane FromTriangle(const Triangle& t) {
  798. Plane result;
  799. result.normal = Normalized(Cross(t.b - t.a, t.c - t.a));
  800. result.distance = Dot(result.normal, t.a);
  801. return result;
  802. }
  803. Point ClosestPoint(const Triangle& t, const Point& p) {
  804. Plane plane = FromTriangle(t);
  805. Point closest = ClosestPoint(plane, p);
  806. // Closest point was inside triangle
  807. if (PointInTriangle(closest, t)) {
  808. return closest;
  809. }
  810. Point c1 = ClosestPoint(Line(t.a, t.b), closest); // Line AB
  811. Point c2 = ClosestPoint(Line(t.b, t.c), closest); // Line BC
  812. Point c3 = ClosestPoint(Line(t.c, t.a), closest); // Line CA
  813. float magSq1 = MagnitudeSq(closest - c1);
  814. float magSq2 = MagnitudeSq(closest - c2);
  815. float magSq3 = MagnitudeSq(closest - c3);
  816. if (magSq1 < magSq2 && magSq1 < magSq3) {
  817. return c1;
  818. }
  819. else if (magSq2 < magSq1 && magSq2 < magSq3) {
  820. return c2;
  821. }
  822. return c3;
  823. }
  824. bool TriangleSphere(const Triangle& t, const Sphere& s) {
  825. Point closest = ClosestPoint(t, s.position);
  826. float magSq = MagnitudeSq(closest - s.position);
  827. return magSq <= s.radius * s.radius;
  828. }
  829. bool TriangleAABB(const Triangle& t, const AABB& a) {
  830. // Compute the edge vectors of the triangle (ABC)
  831. vec3 f0 = t.b - t.a;
  832. vec3 f1 = t.c - t.b;
  833. vec3 f2 = t.a - t.c;
  834. // Compute the face normals of the AABB
  835. vec3 u0(1.0f, 0.0f, 0.0f);
  836. vec3 u1(0.0f, 1.0f, 0.0f);
  837. vec3 u2(0.0f, 0.0f, 1.0f);
  838. vec3 test[13] = {
  839. // 3 Normals of AABB
  840. u0, // AABB Axis 1
  841. u1, // AABB Axis 2
  842. u2, // AABB Axis 3
  843. // 1 Normal of the Triangle
  844. Cross(f0, f1),
  845. // 9 Axis, cross products of all edges
  846. Cross(u0, f0),
  847. Cross(u0, f1),
  848. Cross(u0, f2),
  849. Cross(u1, f0),
  850. Cross(u1, f1),
  851. Cross(u1, f2),
  852. Cross(u2, f0),
  853. Cross(u2, f1),
  854. Cross(u2, f2)
  855. };
  856. for (int i = 0; i < 13; ++i) {
  857. if (!OverlapOnAxis(a, t, test[i])) {
  858. return false; // Seperating axis found
  859. }
  860. }
  861. return true; // Seperating axis not found
  862. }
  863. bool TriangleOBB(const Triangle& t, const OBB& o) {
  864. // Compute the edge vectors of the triangle (ABC)
  865. vec3 f0 = t.b - t.a;
  866. vec3 f1 = t.c - t.b;
  867. vec3 f2 = t.a - t.c;
  868. // Compute the face normals of the AABB
  869. const float* orientation = o.orientation.asArray;
  870. vec3 u0(orientation[0], orientation[1], orientation[2]);
  871. vec3 u1(orientation[3], orientation[4], orientation[5]);
  872. vec3 u2(orientation[6], orientation[7], orientation[8]);
  873. vec3 test[13] = {
  874. // 3 Normals of AABB
  875. u0, // AABB Axis 1
  876. u1, // AABB Axis 2
  877. u2, // AABB Axis 3
  878. // 1 Normal of the Triangle
  879. Cross(f0, f1),
  880. // 9 Axis, cross products of all edges
  881. Cross(u0, f0),
  882. Cross(u0, f1),
  883. Cross(u0, f2),
  884. Cross(u1, f0),
  885. Cross(u1, f1),
  886. Cross(u1, f2),
  887. Cross(u2, f0),
  888. Cross(u2, f1),
  889. Cross(u2, f2)
  890. };
  891. for (int i = 0; i < 13; ++i) {
  892. if (!OverlapOnAxis(o, t, test[i])) {
  893. return false; // Seperating axis found
  894. }
  895. }
  896. return true; // Seperating axis not found
  897. }
  898. bool TriangleTriangle(const Triangle& t1, const Triangle& t2) {
  899. #if 0
  900. vec3 axisToTest[] = {
  901. // Triangle 1, Normal
  902. SatCrossEdge(t1.a, t1.b, t1.b, t1.c),
  903. // Triangle 2, Normal
  904. SatCrossEdge(t2.a, t2.b, t2.b, t2.c),
  905. // Cross Product of edges
  906. SatCrossEdge(t2.a, t2.b, t1.a, t1.b),
  907. SatCrossEdge(t2.a, t2.b, t1.b, t1.c),
  908. SatCrossEdge(t2.a, t2.b, t1.c, t1.a),
  909. SatCrossEdge(t2.b, t2.c, t1.a, t1.b),
  910. SatCrossEdge(t2.b, t2.c, t1.b, t1.c),
  911. SatCrossEdge(t2.b, t2.c, t1.c, t1.a),
  912. SatCrossEdge(t2.c, t2.a, t1.a, t1.b),
  913. SatCrossEdge(t2.c, t2.a, t1.b, t1.c),
  914. SatCrossEdge(t2.c, t2.a, t1.c, t1.a),
  915. };
  916. #else
  917. vec3 t1_f0 = t1.b - t1.a; // Edge 0
  918. vec3 t1_f1 = t1.c - t1.b; // Edge 1
  919. vec3 t1_f2 = t1.a - t1.c; // Edge 2
  920. vec3 t2_f0 = t2.b - t2.a; // Edge 0
  921. vec3 t2_f1 = t2.c - t2.b; // Edge 1
  922. vec3 t2_f2 = t2.a - t2.c; // Edge 2
  923. vec3 axisToTest[] = {
  924. // Triangle 1, Normal
  925. Cross(t1_f0, t1_f1),
  926. // Triangle 2, Normal
  927. Cross(t2_f0, t2_f1),
  928. // Cross Product of edges
  929. Cross(t2_f0, t1_f0),
  930. Cross(t2_f0, t1_f1),
  931. Cross(t2_f0, t1_f2),
  932. Cross(t2_f1, t1_f0),
  933. Cross(t2_f1, t1_f1),
  934. Cross(t2_f1, t1_f2),
  935. Cross(t2_f2, t1_f0),
  936. Cross(t2_f2, t1_f1),
  937. Cross(t2_f2, t1_f2),
  938. };
  939. #endif
  940. for (int i = 0; i < 11; ++i) {
  941. if (!OverlapOnAxis(t1, t2, axisToTest[i])) {
  942. return false; // Seperating axis found
  943. }
  944. }
  945. return true; // Seperating axis not found
  946. }
  947. bool TriangleTriangleRobust(const Triangle& t1, const Triangle& t2) {
  948. vec3 axisToTest[] = {
  949. // Triangle 1, Normal
  950. SatCrossEdge(t1.a, t1.b, t1.b, t1.c),
  951. // Triangle 2, Normal
  952. SatCrossEdge(t2.a, t2.b, t2.b, t2.c),
  953. // Cross Product of edges
  954. SatCrossEdge(t2.a, t2.b, t1.a, t1.b),
  955. SatCrossEdge(t2.a, t2.b, t1.b, t1.c),
  956. SatCrossEdge(t2.a, t2.b, t1.c, t1.a),
  957. SatCrossEdge(t2.b, t2.c, t1.a, t1.b),
  958. SatCrossEdge(t2.b, t2.c, t1.b, t1.c),
  959. SatCrossEdge(t2.b, t2.c, t1.c, t1.a),
  960. SatCrossEdge(t2.c, t2.a, t1.a, t1.b),
  961. SatCrossEdge(t2.c, t2.a, t1.b, t1.c),
  962. SatCrossEdge(t2.c, t2.a, t1.c, t1.a),
  963. };
  964. for (int i = 0; i < 11; ++i) {
  965. if (!OverlapOnAxis(t1, t2, axisToTest[i])) {
  966. if (!CMP(MagnitudeSq(axisToTest[i]), 0)) {
  967. return false; // Seperating axis found
  968. }
  969. }
  970. }
  971. return true; // Seperating axis not found
  972. }
  973. vec3 SatCrossEdge(const vec3& a, const vec3& b, const vec3& c, const vec3& d) {
  974. vec3 ab = b - a;
  975. vec3 cd = d - c;
  976. vec3 result = Cross(ab, cd);
  977. if (!CMP(MagnitudeSq(result), 0)) { // Is ab and cd parallel?
  978. return result; // Not parallel!
  979. }
  980. else { // ab and cd are parallel
  981. // Get an axis perpendicular to AB
  982. vec3 axis = Cross(ab, c - a);
  983. result = Cross(ab, axis);
  984. if (!CMP(MagnitudeSq(result), 0)) { // Still parallel?
  985. return result; // Not parallel
  986. }
  987. }
  988. // New axis being tested is parallel too.
  989. // This means that a, b, c and d are on a line
  990. // Nothing we can do!
  991. return vec3();
  992. }
  993. Point debugRaycastResult;
  994. bool Raycast(const Triangle& triangle, const Ray& ray, RaycastResult* outResult) {
  995. ResetRaycastResult(outResult);
  996. Plane plane = FromTriangle(triangle);
  997. RaycastResult planeResult;
  998. if (!Raycast(plane, ray, &planeResult)) {
  999. return false;
  1000. }
  1001. float t = planeResult.t;
  1002. Point result = ray.origin + ray.direction * t;
  1003. vec3 barycentric = Barycentric(result, triangle);
  1004. if (barycentric.x >= 0.0f && barycentric.x <= 1.0f &&
  1005. barycentric.y >= 0.0f && barycentric.y <= 1.0f &&
  1006. barycentric.z >= 0.0f && barycentric.z <= 1.0f) {
  1007. if (outResult != 0) {
  1008. outResult->t = t;
  1009. outResult->hit = true;
  1010. outResult->point = ray.origin + ray.direction * t;
  1011. outResult->normal = plane.normal;
  1012. }
  1013. return true;
  1014. }
  1015. return false;
  1016. }
  1017. bool Linetest(const Triangle& triangle, const Line& line) {
  1018. Ray ray;
  1019. ray.origin = line.start;
  1020. ray.direction = Normalized(line.end - line.start);
  1021. RaycastResult raycast;
  1022. if (!Raycast(triangle, ray, &raycast)) {
  1023. return false;
  1024. }
  1025. float t = raycast.t;
  1026. return t >= 0 && t * t <= LengthSq(line);
  1027. }
  1028. void AccelerateMesh(Mesh& mesh) {
  1029. if (mesh.accelerator != 0) {
  1030. return;
  1031. }
  1032. vec3 min = mesh.vertices[0];
  1033. vec3 max = mesh.vertices[0];
  1034. for (int i = 1; i < mesh.numTriangles * 3; ++i) {
  1035. min.x = fminf(mesh.vertices[i].x, min.x);
  1036. min.y = fminf(mesh.vertices[i].y, min.y);
  1037. min.z = fminf(mesh.vertices[i].z, min.z);
  1038. max.x = fmaxf(mesh.vertices[i].x, max.x);
  1039. max.y = fmaxf(mesh.vertices[i].y, max.y);
  1040. max.z = fmaxf(mesh.vertices[i].z, max.z);
  1041. }
  1042. mesh.accelerator = new BVHNode();
  1043. mesh.accelerator->bounds = FromMinMax(min, max);
  1044. mesh.accelerator->children = 0;
  1045. mesh.accelerator->numTriangles = mesh.numTriangles;
  1046. mesh.accelerator->triangles = new int[mesh.numTriangles];
  1047. for (int i = 0; i < mesh.numTriangles; ++i) {
  1048. mesh.accelerator->triangles[i] = i;
  1049. }
  1050. SplitBVHNode(mesh.accelerator, mesh, 3);
  1051. }
  1052. void SplitBVHNode(BVHNode* node, const Mesh& model, int depth) {
  1053. if (depth-- <= 0) { // Decrements depth
  1054. return;
  1055. }
  1056. if (node->children == 0) {
  1057. // Only split if this node contains triangles
  1058. if (node->numTriangles > 0) {
  1059. node->children = new BVHNode[8];
  1060. vec3 c = node->bounds.position;
  1061. vec3 e = node->bounds.size *0.5f;
  1062. node->children[0].bounds = AABB(c + vec3(-e.x, +e.y, -e.z), e);
  1063. node->children[1].bounds = AABB(c + vec3(+e.x, +e.y, -e.z), e);
  1064. node->children[2].bounds = AABB(c + vec3(-e.x, +e.y, +e.z), e);
  1065. node->children[3].bounds = AABB(c + vec3(+e.x, +e.y, +e.z), e);
  1066. node->children[4].bounds = AABB(c + vec3(-e.x, -e.y, -e.z), e);
  1067. node->children[5].bounds = AABB(c + vec3(+e.x, -e.y, -e.z), e);
  1068. node->children[6].bounds = AABB(c + vec3(-e.x, -e.y, +e.z), e);
  1069. node->children[7].bounds = AABB(c + vec3(+e.x, -e.y, +e.z), e);
  1070. }
  1071. }
  1072. // If this node was just split
  1073. if (node->children != 0 && node->numTriangles > 0) {
  1074. for (int i = 0; i < 8; ++i) { // For each child
  1075. // Count how many triangles each child will contain
  1076. node->children[i].numTriangles = 0;
  1077. for (int j = 0; j < node->numTriangles; ++j) {
  1078. Triangle t = model.triangles[node->triangles[j]];
  1079. if (TriangleAABB(t, node->children[i].bounds)) {
  1080. node->children[i].numTriangles += 1;
  1081. }
  1082. }
  1083. if (node->children[i].numTriangles == 0) {
  1084. continue;
  1085. }
  1086. node->children[i].triangles = new int[node->children[i].numTriangles];
  1087. int index = 0; // Add the triangles in the new child arrau
  1088. for (int j = 0; j < node->numTriangles; ++j) {
  1089. Triangle t = model.triangles[node->triangles[j]];
  1090. if (TriangleAABB(t, node->children[i].bounds)) {
  1091. node->children[i].triangles[index++] = node->triangles[j];
  1092. }
  1093. }
  1094. }
  1095. node->numTriangles = 0;
  1096. delete[] node->triangles;
  1097. node->triangles = 0;
  1098. // Recurse
  1099. for (int i = 0; i < 8; ++i) {
  1100. SplitBVHNode(&node->children[i], model, depth);
  1101. }
  1102. }
  1103. }
  1104. void FreeBVHNode(BVHNode* node) {
  1105. if (node->children != 0) {
  1106. for (int i = 0; i < 8; ++i) {
  1107. FreeBVHNode(&node->children[i]);
  1108. }
  1109. delete[] node->children;
  1110. node->children = 0;
  1111. }
  1112. if (node->numTriangles != 0 || node->triangles != 0) {
  1113. delete[] node->triangles;
  1114. node->triangles = 0;
  1115. node->numTriangles = 0;
  1116. }
  1117. }
  1118. bool MeshAABB(const Mesh& mesh, const AABB& aabb) {
  1119. if (mesh.accelerator == 0) {
  1120. for (int i = 0; i < mesh.numTriangles; ++i) {
  1121. if (TriangleAABB(mesh.triangles[i], aabb)) {
  1122. return true;
  1123. }
  1124. }
  1125. }
  1126. else {
  1127. std::list<BVHNode*> toProcess;
  1128. toProcess.push_front(mesh.accelerator);
  1129. // Recursivley walk the BVH tree
  1130. while (!toProcess.empty()) {
  1131. BVHNode* iterator = *(toProcess.begin());
  1132. toProcess.erase(toProcess.begin());
  1133. if (iterator->numTriangles >= 0) {
  1134. // Iterate trough all triangles of the node
  1135. for (int i = 0; i < iterator->numTriangles; ++i) {
  1136. // Triangle indices in BVHNode index the mesh
  1137. if (TriangleAABB(mesh.triangles[iterator->triangles[i]], aabb)) {
  1138. return true;
  1139. }
  1140. }
  1141. }
  1142. if (iterator->children != 0) {
  1143. for (int i = 8 - 1; i >= 0; --i) {
  1144. // Only push children whos bounds intersect the test geometry
  1145. if (AABBAABB(iterator->children[i].bounds, aabb)) {
  1146. toProcess.push_front(&iterator->children[i]);
  1147. }
  1148. }
  1149. }
  1150. }
  1151. }
  1152. return false;
  1153. }
  1154. bool Linetest(const Mesh& mesh, const Line& line) {
  1155. if (mesh.accelerator == 0) {
  1156. for (int i = 0; i < mesh.numTriangles; ++i) {
  1157. if (Linetest(mesh.triangles[i], line)) {
  1158. return true;
  1159. }
  1160. }
  1161. }
  1162. else {
  1163. std::list<BVHNode*> toProcess;
  1164. toProcess.push_front(mesh.accelerator);
  1165. // Recursivley walk the BVH tree
  1166. while (!toProcess.empty()) {
  1167. BVHNode* iterator = *(toProcess.begin());
  1168. toProcess.erase(toProcess.begin());
  1169. if (iterator->numTriangles >= 0) {
  1170. // Iterate trough all triangles of the node
  1171. for (int i = 0; i < iterator->numTriangles; ++i) {
  1172. // Triangle indices in BVHNode index the mesh
  1173. if (Linetest(mesh.triangles[iterator->triangles[i]], line)) {
  1174. return true;
  1175. }
  1176. }
  1177. }
  1178. if (iterator->children != 0) {
  1179. for (int i = 8 - 1; i >= 0; --i) {
  1180. // Only push children whos bounds intersect the test geometry
  1181. if (Linetest(iterator->children[i].bounds, line)) {
  1182. toProcess.push_front(&iterator->children[i]);
  1183. }
  1184. }
  1185. }
  1186. }
  1187. }
  1188. return false;
  1189. }
  1190. bool MeshSphere(const Mesh& mesh, const Sphere& sphere) {
  1191. if (mesh.accelerator == 0) {
  1192. for (int i = 0; i < mesh.numTriangles; ++i) {
  1193. if (TriangleSphere(mesh.triangles[i], sphere)) {
  1194. return true;
  1195. }
  1196. }
  1197. }
  1198. else {
  1199. std::list<BVHNode*> toProcess;
  1200. toProcess.push_front(mesh.accelerator);
  1201. // Recursivley walk the BVH tree
  1202. while (!toProcess.empty()) {
  1203. BVHNode* iterator = *(toProcess.begin());
  1204. toProcess.erase(toProcess.begin());
  1205. if (iterator->numTriangles >= 0) {
  1206. // Iterate trough all triangles of the node
  1207. for (int i = 0; i < iterator->numTriangles; ++i) {
  1208. // Triangle indices in BVHNode index the mesh
  1209. if (TriangleSphere(mesh.triangles[iterator->triangles[i]], sphere)) {
  1210. return true;
  1211. }
  1212. }
  1213. }
  1214. if (iterator->children != 0) {
  1215. for (int i = 8 - 1; i >= 0; --i) {
  1216. // Only push children whos bounds intersect the test geometry
  1217. if (SphereAABB(sphere, iterator->children[i].bounds)) {
  1218. toProcess.push_front(&iterator->children[i]);
  1219. }
  1220. }
  1221. }
  1222. }
  1223. }
  1224. return false;
  1225. }
  1226. bool MeshOBB(const Mesh& mesh, const OBB& obb) {
  1227. if (mesh.accelerator == 0) {
  1228. for (int i = 0; i < mesh.numTriangles; ++i) {
  1229. if (TriangleOBB(mesh.triangles[i], obb)) {
  1230. return true;
  1231. }
  1232. }
  1233. }
  1234. else {
  1235. std::list<BVHNode*> toProcess;
  1236. toProcess.push_front(mesh.accelerator);
  1237. // Recursivley walk the BVH tree
  1238. while (!toProcess.empty()) {
  1239. BVHNode* iterator = *(toProcess.begin());
  1240. toProcess.erase(toProcess.begin());
  1241. if (iterator->numTriangles >= 0) {
  1242. // Iterate trough all triangles of the node
  1243. for (int i = 0; i < iterator->numTriangles; ++i) {
  1244. // Triangle indices in BVHNode index the mesh
  1245. if (TriangleOBB(mesh.triangles[iterator->triangles[i]], obb)) {
  1246. return true;
  1247. }
  1248. }
  1249. }
  1250. if (iterator->children != 0) {
  1251. for (int i = 8 - 1; i >= 0; --i) {
  1252. // Only push children whos bounds intersect the test geometry
  1253. if (AABBOBB(iterator->children[i].bounds, obb)) {
  1254. toProcess.push_front(&iterator->children[i]);
  1255. }
  1256. }
  1257. }
  1258. }
  1259. }
  1260. return false;
  1261. }
  1262. bool MeshPlane(const Mesh& mesh, const Plane& plane) {
  1263. if (mesh.accelerator == 0) {
  1264. for (int i = 0; i < mesh.numTriangles; ++i) {
  1265. if (TrianglePlane(mesh.triangles[i], plane)) {
  1266. return true;
  1267. }
  1268. }
  1269. }
  1270. else {
  1271. std::list<BVHNode*> toProcess;
  1272. toProcess.push_front(mesh.accelerator);
  1273. // Recursivley walk the BVH tree
  1274. while (!toProcess.empty()) {
  1275. BVHNode* iterator = *(toProcess.begin());
  1276. toProcess.erase(toProcess.begin());
  1277. if (iterator->numTriangles >= 0) {
  1278. // Iterate trough all triangles of the node
  1279. for (int i = 0; i < iterator->numTriangles; ++i) {
  1280. // Triangle indices in BVHNode index the mesh
  1281. if (TrianglePlane(mesh.triangles[iterator->triangles[i]], plane)) {
  1282. return true;
  1283. }
  1284. }
  1285. }
  1286. if (iterator->children != 0) {
  1287. for (int i = 8 - 1; i >= 0; --i) {
  1288. // Only push children whos bounds intersect the test geometry
  1289. if (AABBPlane(iterator->children[i].bounds, plane)) {
  1290. toProcess.push_front(&iterator->children[i]);
  1291. }
  1292. }
  1293. }
  1294. }
  1295. }
  1296. return false;
  1297. }
  1298. bool MeshTriangle(const Mesh& mesh, const Triangle& triangle) {
  1299. if (mesh.accelerator == 0) {
  1300. for (int i = 0; i < mesh.numTriangles; ++i) {
  1301. if (TriangleTriangle(mesh.triangles[i], triangle)) {
  1302. return true;
  1303. }
  1304. }
  1305. }
  1306. else {
  1307. std::list<BVHNode*> toProcess;
  1308. toProcess.push_front(mesh.accelerator);
  1309. // Recursivley walk the BVH tree
  1310. while (!toProcess.empty()) {
  1311. BVHNode* iterator = *(toProcess.begin());
  1312. toProcess.erase(toProcess.begin());
  1313. if (iterator->numTriangles >= 0) {
  1314. // Iterate trough all triangles of the node
  1315. for (int i = 0; i < iterator->numTriangles; ++i) {
  1316. // Triangle indices in BVHNode index the mesh
  1317. if (TriangleTriangle(mesh.triangles[iterator->triangles[i]], triangle)) {
  1318. return true;
  1319. }
  1320. }
  1321. }
  1322. if (iterator->children != 0) {
  1323. for (int i = 8 - 1; i >= 0; --i) {
  1324. // Only push children whos bounds intersect the test geometry
  1325. if (TriangleAABB(triangle, iterator->children[i].bounds)) {
  1326. toProcess.push_front(&iterator->children[i]);
  1327. }
  1328. }
  1329. }
  1330. }
  1331. }
  1332. return false;
  1333. }
  1334. float Raycast(const Mesh& mesh, const Ray& ray) {
  1335. return MeshRay(mesh, ray);
  1336. }
  1337. float Raycast(const Model& mesh, const Ray& ray) {
  1338. return ModelRay(mesh, ray);
  1339. }
  1340. float MeshRay(const Mesh& mesh, const Ray& ray) {
  1341. if (mesh.accelerator == 0) {
  1342. for (int i = 0; i < mesh.numTriangles; ++i) {
  1343. RaycastResult raycast;
  1344. Raycast(mesh.triangles[i], ray, &raycast);
  1345. float result = raycast.t;
  1346. if (result >= 0) {
  1347. return result;
  1348. }
  1349. }
  1350. }
  1351. else {
  1352. std::list<BVHNode*> toProcess;
  1353. toProcess.push_front(mesh.accelerator);
  1354. // Recursivley walk the BVH tree
  1355. while (!toProcess.empty()) {
  1356. BVHNode* iterator = *(toProcess.begin());
  1357. toProcess.erase(toProcess.begin());
  1358. if (iterator->numTriangles >= 0) {
  1359. // Iterate trough all triangles of the node
  1360. for (int i = 0; i < iterator->numTriangles; ++i) {
  1361. // Triangle indices in BVHNode index the mesh
  1362. RaycastResult raycast;
  1363. Raycast(mesh.triangles[iterator->triangles[i]], ray, &raycast);
  1364. float r = raycast.t;
  1365. if (r >= 0) {
  1366. return r;
  1367. }
  1368. }
  1369. }
  1370. if (iterator->children != 0) {
  1371. for (int i = 8 - 1; i >= 0; --i) {
  1372. // Only push children whos bounds intersect the test geometry
  1373. RaycastResult raycast;
  1374. Raycast(iterator->children[i].bounds, ray, &raycast);
  1375. if (raycast.t >= 0) {
  1376. toProcess.push_front(&iterator->children[i]);
  1377. }
  1378. }
  1379. }
  1380. }
  1381. }
  1382. return -1;
  1383. }
  1384. bool TrianglePlane(const Triangle& t, const Plane& p) {
  1385. float side1 = PlaneEquation(t.a, p);
  1386. float side2 = PlaneEquation(t.b, p);
  1387. float side3 = PlaneEquation(t.c, p);
  1388. // On Plane
  1389. if (CMP(side1, 0) && CMP(side2, 0) && CMP(side3, 0)) {
  1390. return true;
  1391. }
  1392. // Triangle in front of plane
  1393. if (side1 > 0 && side2 > 0 && side3 > 0) {
  1394. return false;
  1395. }
  1396. // Triangle behind plane
  1397. if (side1 < 0 && side2 < 0 && side3 < 0) {
  1398. return false;
  1399. }
  1400. return true; // Intersection
  1401. }
  1402. void Model::SetContent(Mesh* mesh) {
  1403. content = mesh;
  1404. if (content != 0) {
  1405. vec3 min = mesh->vertices[0];
  1406. vec3 max = mesh->vertices[0];
  1407. for (int i = 1; i < mesh->numTriangles * 3; ++i) {
  1408. min.x = fminf(mesh->vertices[i].x, min.x);
  1409. min.y = fminf(mesh->vertices[i].y, min.y);
  1410. min.z = fminf(mesh->vertices[i].z, min.z);
  1411. max.x = fmaxf(mesh->vertices[i].x, max.x);
  1412. max.y = fmaxf(mesh->vertices[i].y, max.y);
  1413. max.z = fmaxf(mesh->vertices[i].z, max.z);
  1414. }
  1415. bounds = FromMinMax(min, max);
  1416. }
  1417. }
  1418. mat4 GetWorldMatrix(const Model& model) {
  1419. mat4 translation = Translation(model.position);
  1420. mat4 rotation = Rotation(model.rotation.x, model.rotation.y, model.rotation.z);
  1421. mat4 localMat = /* Scale * */ rotation * translation;
  1422. mat4 parentMat;
  1423. if (model.parent != 0) {
  1424. parentMat = GetWorldMatrix(*model.parent);
  1425. }
  1426. return localMat * parentMat;
  1427. }
  1428. OBB GetOBB(const Model& model) {
  1429. mat4 world = GetWorldMatrix(model);
  1430. AABB aabb = model.GetBounds();
  1431. OBB obb;
  1432. obb.size = aabb.size;
  1433. obb.position = MultiplyPoint(aabb.position, world);
  1434. obb.orientation = Cut(world, 3, 3);
  1435. return obb;
  1436. }
  1437. float ModelRay(const Model& model, const Ray& ray) {
  1438. mat4 world = GetWorldMatrix(model);
  1439. mat4 inv = Inverse(world);
  1440. Ray local;
  1441. local.origin = MultiplyPoint(ray.origin, inv);
  1442. local.direction = MultiplyVector(ray.direction, inv);
  1443. local.NormalizeDirection();
  1444. if (model.GetMesh() != 0) {
  1445. return MeshRay(*(model.GetMesh()), local);
  1446. }
  1447. return -1;
  1448. }
  1449. bool Linetest(const Model& model, const Line& line) {
  1450. mat4 world = GetWorldMatrix(model);
  1451. mat4 inv = Inverse(world);
  1452. Line local;
  1453. local.start = MultiplyPoint(line.start, inv);
  1454. local.end = MultiplyPoint(line.end, inv);
  1455. if (model.GetMesh() != 0) {
  1456. return Linetest(*(model.GetMesh()), local);
  1457. }
  1458. return false;
  1459. }
  1460. bool ModelSphere(const Model& model, const Sphere& sphere) {
  1461. mat4 world = GetWorldMatrix(model);
  1462. mat4 inv = Inverse(world);
  1463. Sphere local;
  1464. local.position = MultiplyPoint(sphere.position, inv);
  1465. if (model.GetMesh() != 0) {
  1466. return MeshSphere(*(model.GetMesh()), local);
  1467. }
  1468. return false;
  1469. }
  1470. bool ModelAABB(const Model& model, const AABB& aabb) {
  1471. mat4 world = GetWorldMatrix(model);
  1472. mat4 inv = Inverse(world);
  1473. OBB local;
  1474. local.size = aabb.size;
  1475. local.position = MultiplyPoint(aabb.position, inv);
  1476. local.orientation = Cut(inv, 3, 3);
  1477. if (model.GetMesh() != 0) {
  1478. return MeshOBB(*(model.GetMesh()), local);
  1479. }
  1480. return false;
  1481. }
  1482. bool ModelOBB(const Model& model, const OBB& obb) {
  1483. mat4 world = GetWorldMatrix(model);
  1484. mat4 inv = Inverse(world);
  1485. OBB local;
  1486. local.size = obb.size;
  1487. local.position = MultiplyPoint(obb.position, inv);
  1488. local.orientation = obb.orientation * Cut(inv, 3, 3);
  1489. if (model.GetMesh() != 0) {
  1490. return MeshOBB(*(model.GetMesh()), local);
  1491. }
  1492. return false;
  1493. }
  1494. bool ModelPlane(const Model& model, const Plane& plane) {
  1495. mat4 world = GetWorldMatrix(model);
  1496. mat4 inv = Inverse(world);
  1497. Plane local;
  1498. local.normal = MultiplyVector(plane.normal, inv);
  1499. local.distance = plane.distance;
  1500. if (model.GetMesh() != 0) {
  1501. return MeshPlane(*(model.GetMesh()), local);
  1502. }
  1503. return false;
  1504. }
  1505. bool ModelTriangle(const Model& model, const Triangle& triangle) {
  1506. mat4 world = GetWorldMatrix(model);
  1507. mat4 inv = Inverse(world);
  1508. Triangle local;
  1509. local.a = MultiplyPoint(triangle.a, inv);
  1510. local.b = MultiplyPoint(triangle.b, inv);
  1511. local.c = MultiplyPoint(triangle.c, inv);
  1512. if (model.GetMesh() != 0) {
  1513. return MeshTriangle(*(model.GetMesh()), local);
  1514. }
  1515. return false;
  1516. }
  1517. Point Intersection(Plane p1, Plane p2, Plane p3) {
  1518. /*return ((Cross(p2.normal, p3.normal) * -p1.distance) +
  1519. (Cross(p3.normal, p1.normal) * -p2.distance) +
  1520. (Cross(p1.normal, p2.normal) * -p3.distance)) /
  1521. (Dot(p1.normal, Cross(p2.normal, p3.normal)));*/
  1522. #if 1
  1523. mat3 D(
  1524. p1.normal.x, p2.normal.x, p3.normal.x,
  1525. p1.normal.y, p2.normal.y, p3.normal.y,
  1526. p1.normal.z, p2.normal.z, p3.normal.z
  1527. );
  1528. vec3 A(-p1.distance, -p2.distance, -p3.distance);
  1529. mat3 Dx = D, Dy = D, Dz = D;
  1530. Dx._11 = A.x; Dx._12 = A.y; Dx._13 = A.z;
  1531. Dy._21 = A.x; Dy._22 = A.y; Dy._23 = A.z;
  1532. Dz._31 = A.x; Dz._32 = A.y; Dz._33 = A.z;
  1533. float detD = Determinant(D);
  1534. if (CMP(detD, 0)) {
  1535. return Point();
  1536. }
  1537. float detDx = Determinant(Dx);
  1538. float detDy = Determinant(Dy);
  1539. float detDz = Determinant(Dz);
  1540. return Point(detDx / detD, detDy / detD, detDz / detD);
  1541. #else
  1542. vec3 m1(p1.normal.x, p2.normal.x, p3.normal.x);
  1543. vec3 m2(p1.normal.y, p2.normal.y, p3.normal.y);
  1544. vec3 m3(p1.normal.z, p2.normal.z, p3.normal.z);
  1545. vec3 d(-p1.distance, -p2.distance, -p3.distance);
  1546. vec3 u = Cross(m2, m3);
  1547. vec3 v = Cross(m1, d);
  1548. float denom = Dot(m1, u);
  1549. if (CMP(denom, 0.0f)) {
  1550. return Point();
  1551. }
  1552. Point result;
  1553. result.x = Dot(d, u) / denom;
  1554. result.y = Dot(m3, v) / denom;
  1555. result.z = -Dot(m2, v) / denom;
  1556. return result;
  1557. #endif
  1558. }
  1559. void GetCorners(const Frustum& f, vec3* outCorners) {
  1560. outCorners[0] = Intersection(f._near, f.top, f.left);
  1561. outCorners[1] = Intersection(f._near, f.top, f.right);
  1562. outCorners[2] = Intersection(f._near, f.bottom, f.left);
  1563. outCorners[3] = Intersection(f._near, f.bottom, f.right);
  1564. outCorners[4] = Intersection(f._far, f.top, f.left);
  1565. outCorners[5] = Intersection(f._far, f.top, f.right);
  1566. outCorners[6] = Intersection(f._far, f.bottom, f.left);
  1567. outCorners[7] = Intersection(f._far, f.bottom, f.right);
  1568. }
  1569. bool Intersects(const Frustum& f, const Point& p) {
  1570. for (int i = 0; i < 6; ++i) {
  1571. vec3 normal = f.planes[i].normal;
  1572. float dist = f.planes[i].distance;
  1573. float side = Dot(p, normal) + dist;
  1574. if (side < 0.0f) {
  1575. return false;
  1576. }
  1577. }
  1578. return true;
  1579. }
  1580. bool Intersects(const Frustum& f, const Sphere& s) {
  1581. for (int i = 0; i < 6; ++i) {
  1582. vec3 normal = f.planes[i].normal;
  1583. float dist = f.planes[i].distance;
  1584. float side = Dot(s.position, normal) + dist;
  1585. if (side < -s.radius) {
  1586. return false;
  1587. }
  1588. }
  1589. return true;
  1590. }
  1591. float Classify(const AABB& aabb, const Plane& plane) {
  1592. // maximum extent in direction of plane normal
  1593. float r = fabsf(aabb.size.x * plane.normal.x)
  1594. + fabsf(aabb.size.y * plane.normal.y)
  1595. + fabsf(aabb.size.z * plane.normal.z);
  1596. // signed distance between box center and plane
  1597. //float d = plane.Test(mCenter);
  1598. float d = Dot(plane.normal, aabb.position) + plane.distance;
  1599. // return signed distance
  1600. if (fabsf(d) < r) {
  1601. return 0.0f;
  1602. }
  1603. else if (d < 0.0f) {
  1604. return d + r;
  1605. }
  1606. return d - r;
  1607. }
  1608. float Classify(const OBB& obb, const Plane& plane) {
  1609. vec3 normal = MultiplyVector(plane.normal, obb.orientation);
  1610. // maximum extent in direction of plane normal
  1611. float r = fabsf(obb.size.x * normal.x)
  1612. + fabsf(obb.size.y * normal.y)
  1613. + fabsf(obb.size.z * normal.z);
  1614. // signed distance between box center and plane
  1615. //float d = plane.Test(mCenter);
  1616. float d = Dot(plane.normal, obb.position) + plane.distance;
  1617. // return signed distance
  1618. if (fabsf(d) < r) {
  1619. return 0.0f;
  1620. }
  1621. else if (d < 0.0f) {
  1622. return d + r;
  1623. }
  1624. return d - r;
  1625. }
  1626. bool Intersects(const Frustum& f, const OBB& obb) {
  1627. for (int i = 0; i < 6; ++i) {
  1628. float side = Classify(obb, f.planes[i]);
  1629. if (side < 0) {
  1630. return false;
  1631. }
  1632. }
  1633. return true;
  1634. }
  1635. bool Intersects(const Frustum& f, const AABB& aabb) {
  1636. for (int i = 0; i < 6; ++i) {
  1637. float side = Classify(aabb, f.planes[i]);
  1638. if (side < 0) {
  1639. return false;
  1640. }
  1641. }
  1642. return true;
  1643. }
  1644. vec3 Unproject(const vec3& viewportPoint, const vec2& viewportOrigin, const vec2& viewportSize, const mat4& view, const mat4& projection) {
  1645. // Step 1, Normalize the input vector to the view port
  1646. float normalized[4] = {
  1647. (viewportPoint.x - viewportOrigin.x) / viewportSize.x,
  1648. (viewportPoint.y - viewportOrigin.y) / viewportSize.y,
  1649. viewportPoint.z,
  1650. 1.0f
  1651. };
  1652. // Step 2, Translate into NDC space
  1653. float ndcSpace[4] = {
  1654. normalized[0], normalized[1],
  1655. normalized[2], normalized[3]
  1656. };
  1657. // X Range: -1 to 1
  1658. ndcSpace[0] = ndcSpace[0] * 2.0f - 1.0f;
  1659. // Y Range: -1 to 1, our Y axis is flipped!
  1660. ndcSpace[1] = 1.0f - ndcSpace[1] * 2.0f;
  1661. // Z Range: 0 to 1
  1662. if (ndcSpace[2] < 0.0f) {
  1663. ndcSpace[2] = 0.0f;
  1664. }
  1665. if (ndcSpace[2] > 1.0f) {
  1666. ndcSpace[2] = 1.0f;
  1667. }
  1668. // Step 3, NDC to Eye Space
  1669. mat4 invProjection = Inverse(projection);
  1670. float eyeSpace[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1671. // eyeSpace = MultiplyPoint(ndcSpace, invProjection);
  1672. Multiply(eyeSpace, ndcSpace, 1, 4, invProjection.asArray, 4, 4);
  1673. // Step 4, Eye Space to World Space
  1674. mat4 invView = Inverse(view);
  1675. float worldSpace[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1676. // worldSpace = MultiplyPoint(eyeSpace, invView);
  1677. Multiply(worldSpace, eyeSpace, 1, 4, invView.asArray, 4, 4);
  1678. // Step 5, Undo perspective divide!
  1679. if (!CMP(worldSpace[3], 0.0f)) {
  1680. worldSpace[0] /= worldSpace[3];
  1681. worldSpace[1] /= worldSpace[3];
  1682. worldSpace[2] /= worldSpace[3];
  1683. }
  1684. // Return the resulting world space point
  1685. return vec3(worldSpace[0], worldSpace[1], worldSpace[2]);
  1686. }
  1687. Ray GetPickRay(const vec2& viewportPoint, const vec2& viewportOrigin, const vec2& viewportSize, const mat4& view, const mat4& projection) {
  1688. vec3 nearPoint(viewportPoint.x, viewportPoint.y, 0.0f);
  1689. vec3 farPoint(viewportPoint.x, viewportPoint.y, 1.0f);
  1690. vec3 pNear = Unproject(nearPoint, viewportOrigin, viewportSize, view, projection);
  1691. vec3 pFar = Unproject(farPoint, viewportOrigin, viewportSize, view, projection);
  1692. vec3 normal = Normalized(pFar - pNear);
  1693. vec3 origin = pNear;
  1694. return Ray(origin, normal);
  1695. }
  1696. // Chapter 15
  1697. void ResetCollisionManifold(CollisionManifold* result) {
  1698. if (result != 0) {
  1699. result->colliding = false;
  1700. result->normal = vec3(0, 0, 1);
  1701. result->depth = FLT_MAX;
  1702. if (result->contacts.size() > 0) {
  1703. result->contacts.clear();
  1704. }
  1705. }
  1706. }
  1707. std::vector<Point> GetVertices(const OBB& obb) {
  1708. std::vector<vec3> v;
  1709. v.resize(8);
  1710. vec3 C = obb.position; // OBB Center
  1711. vec3 E = obb.size; // OBB Extents
  1712. const float* o = obb.orientation.asArray;
  1713. vec3 A[] = { // OBB Axis
  1714. vec3(o[0], o[1], o[2]),
  1715. vec3(o[3], o[4], o[5]),
  1716. vec3(o[6], o[7], o[8]),
  1717. };
  1718. v[0] = C + A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  1719. v[1] = C - A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  1720. v[2] = C + A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  1721. v[3] = C + A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  1722. v[4] = C - A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  1723. v[5] = C + A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  1724. v[6] = C - A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  1725. v[7] = C - A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  1726. return v;
  1727. }
  1728. std::vector<Line> GetEdges(const OBB& obb) {
  1729. std::vector<Line> result;
  1730. result.reserve(12);
  1731. std::vector<Point> v = GetVertices(obb);
  1732. int index[][2] = { // Indices of edges
  1733. { 6, 1 },{ 6, 3 },{ 6, 4 },{ 2, 7 },{ 2, 5 },{ 2, 0 },
  1734. { 0, 1 },{ 0, 3 },{ 7, 1 },{ 7, 4 },{ 4, 5 },{ 5, 3 }
  1735. };
  1736. for (int j = 0; j < 12; ++j) {
  1737. result.push_back(Line(
  1738. v[index[j][0]], v[index[j][1]]
  1739. ));
  1740. }
  1741. return result;
  1742. }
  1743. std::vector<Plane> GetPlanes(const OBB& obb) {
  1744. vec3 c = obb.position; // OBB Center
  1745. vec3 e = obb.size; // OBB Extents
  1746. const float* o = obb.orientation.asArray;
  1747. vec3 a[] = { // OBB Axis
  1748. vec3(o[0], o[1], o[2]),
  1749. vec3(o[3], o[4], o[5]),
  1750. vec3(o[6], o[7], o[8]),
  1751. };
  1752. std::vector<Plane> result;
  1753. result.resize(6);
  1754. result[0] = Plane(a[0] , Dot(a[0], (c + a[0] * e.x)));
  1755. result[1] = Plane(a[0] * -1.0f, -Dot(a[0], (c - a[0] * e.x)));
  1756. result[2] = Plane(a[1] , Dot(a[1], (c + a[1] * e.y)));
  1757. result[3] = Plane(a[1] * -1.0f, -Dot(a[1], (c - a[1] * e.y)));
  1758. result[4] = Plane(a[2] , Dot(a[2], (c + a[2] * e.z)));
  1759. result[5] = Plane(a[2] * -1.0f, -Dot(a[2], (c - a[2] * e.z)));
  1760. return result;
  1761. }
  1762. bool ClipToPlane(const Plane& plane, const Line& line, Point* outPoint) {
  1763. vec3 ab = line.end - line.start;
  1764. float nA = Dot(plane.normal, line.start);
  1765. float nAB = Dot(plane.normal, ab);
  1766. if (CMP(nAB, 0)) {
  1767. return false;
  1768. }
  1769. float t = (plane.distance - nA) / nAB;
  1770. if (t >= 0.0f && t <= 1.0f) {
  1771. if (outPoint != 0) {
  1772. *outPoint = line.start + ab * t;
  1773. }
  1774. return true;
  1775. }
  1776. return false;
  1777. }
  1778. std::vector<Point> ClipEdgesToOBB(const std::vector<Line>& edges, const OBB& obb) {
  1779. std::vector<Point> result;
  1780. result.reserve(edges.size() * 3);
  1781. Point intersection;
  1782. std::vector<Plane>& planes = GetPlanes(obb);
  1783. for (int i = 0; i < planes.size(); ++i) {
  1784. for (int j = 0; j < edges.size(); ++j) {
  1785. if (ClipToPlane(planes[i], edges[j], &intersection)) {
  1786. if (PointInOBB(intersection, obb)) {
  1787. result.push_back(intersection);
  1788. }
  1789. }
  1790. }
  1791. }
  1792. return result;
  1793. }
  1794. float PenetrationDepth(const OBB& o1, const OBB& o2, const vec3& axis, bool* outShouldFlip) {
  1795. Interval i1 = GetInterval(o1, Normalized(axis));
  1796. Interval i2 = GetInterval(o2, Normalized(axis));
  1797. if (!((i2.min <= i1.max) && (i1.min <= i2.max))) {
  1798. return 0.0f; // No penerattion
  1799. }
  1800. float len1 = i1.max - i1.min;
  1801. float len2 = i2.max - i2.min;
  1802. float min = fminf(i1.min, i2.min);
  1803. float max = fmaxf(i1.max, i2.max);
  1804. float length = max - min;
  1805. if (outShouldFlip != 0) {
  1806. *outShouldFlip = (i2.min < i1.min);
  1807. }
  1808. return (len1 + len2) - length;
  1809. }
  1810. CollisionManifold FindCollisionFeatures(const OBB& A, const OBB& B) {
  1811. CollisionManifold result; // Will return result of intersection!
  1812. ResetCollisionManifold(&result);
  1813. Sphere s1(A.position, Magnitude(A.size));
  1814. Sphere s2(B.position, Magnitude(B.size));
  1815. if (!SphereSphere(s1, s2)) {
  1816. return result;
  1817. }
  1818. const float* o1 = A.orientation.asArray;
  1819. const float* o2 = B.orientation.asArray;
  1820. vec3 test[15] = {
  1821. vec3(o1[0], o1[1], o1[2]),
  1822. vec3(o1[3], o1[4], o1[5]),
  1823. vec3(o1[6], o1[7], o1[8]),
  1824. vec3(o2[0], o2[1], o2[2]),
  1825. vec3(o2[3], o2[4], o2[5]),
  1826. vec3(o2[6], o2[7], o2[8])
  1827. };
  1828. for (int i = 0; i < 3; ++i) { // Fill out rest of axis
  1829. test[6 + i * 3 + 0] = Cross(test[i], test[0]);
  1830. test[6 + i * 3 + 1] = Cross(test[i], test[1]);
  1831. test[6 + i * 3 + 2] = Cross(test[i], test[2]);
  1832. }
  1833. vec3* hitNormal = 0;
  1834. bool shouldFlip;
  1835. for (int i = 0; i < 15; ++i) {
  1836. if (test[i].x < 0.000001f) test[i].x = 0.0f;
  1837. if (test[i].y < 0.000001f) test[i].y = 0.0f;
  1838. if (test[i].z < 0.000001f) test[i].z = 0.0f;
  1839. if (MagnitudeSq(test[i])< 0.001f) {
  1840. continue;
  1841. }
  1842. float depth = PenetrationDepth(A, B, test[i], &shouldFlip);
  1843. if (depth <= 0.0f) {
  1844. return result;
  1845. }
  1846. else if (depth < result.depth) {
  1847. if (shouldFlip) {
  1848. test[i] = test[i] * -1.0f;
  1849. }
  1850. result.depth = depth;
  1851. hitNormal = &test[i];
  1852. }
  1853. }
  1854. if (hitNormal == 0) {
  1855. return result;
  1856. }
  1857. vec3 axis = Normalized(*hitNormal);
  1858. std::vector<Point> c1 = ClipEdgesToOBB(GetEdges(B), A);
  1859. std::vector<Point> c2 = ClipEdgesToOBB(GetEdges(A), B);
  1860. result.contacts.reserve(c1.size() + c2.size());
  1861. result.contacts.insert(result.contacts.end(), c1.begin(), c1.end());
  1862. result.contacts.insert(result.contacts.end(), c2.begin(), c2.end());
  1863. Interval i = GetInterval(A, axis);
  1864. float distance = (i.max - i.min)* 0.5f - result.depth * 0.5f;
  1865. vec3 pointOnPlane = A.position + axis * distance;
  1866. for (int i = result.contacts.size() - 1; i >= 0; --i) {
  1867. vec3 contact = result.contacts[i];
  1868. result.contacts[i] = contact + (axis * Dot(axis, pointOnPlane - contact));
  1869. // This bit is in the "There is more" section of the book
  1870. for (int j = result.contacts.size() - 1; j > i; --j) {
  1871. if (MagnitudeSq(result.contacts[j] - result.contacts[i]) < 0.0001f) {
  1872. result.contacts.erase(result.contacts.begin() + j);
  1873. break;
  1874. }
  1875. }
  1876. }
  1877. result.colliding = true;
  1878. result.normal = axis;
  1879. return result;
  1880. }
  1881. CollisionManifold FindCollisionFeatures(const Sphere& A, const Sphere& B) {
  1882. CollisionManifold result; // Will return result of intersection!
  1883. ResetCollisionManifold(&result);
  1884. float r = A.radius + B.radius;
  1885. vec3 d = B.position - A.position;
  1886. if (MagnitudeSq(d) - r * r > 0 || MagnitudeSq(d) == 0.0f) {
  1887. return result;
  1888. }
  1889. Normalize(d);
  1890. result.colliding = true;
  1891. result.normal = d;
  1892. result.depth = fabsf(Magnitude(d) - r) * 0.5f;
  1893. // dtp - Distance to intersection point
  1894. float dtp = A.radius - result.depth;
  1895. Point contact = A.position + d * dtp;
  1896. result.contacts.push_back(contact);
  1897. return result;
  1898. }
  1899. CollisionManifold FindCollisionFeatures(const OBB& A, const Sphere& B) {
  1900. CollisionManifold result; // Will return result of intersection!
  1901. ResetCollisionManifold(&result);
  1902. Point closestPoint = ClosestPoint(A, B.position);
  1903. float distanceSq = MagnitudeSq(closestPoint - B.position);
  1904. if (distanceSq > B.radius * B.radius) {
  1905. return result;
  1906. }
  1907. vec3 normal;
  1908. if (CMP(distanceSq, 0.0f)) {
  1909. if (CMP(MagnitudeSq(closestPoint - A.position), 0.0f)) {
  1910. return result;
  1911. }
  1912. // Closest point is at the center of the sphere
  1913. normal = Normalized(closestPoint - A.position);
  1914. }
  1915. else {
  1916. normal = Normalized(B.position - closestPoint);
  1917. }
  1918. Point outsidePoint = B.position - normal * B.radius;
  1919. float distance = Magnitude(closestPoint - outsidePoint);
  1920. result.colliding = true;
  1921. result.contacts.push_back(closestPoint + (outsidePoint - closestPoint) * 0.5f);
  1922. result.normal = normal;
  1923. result.depth = distance * 0.5f;
  1924. return result;
  1925. }

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/520600
推荐阅读
  

闽ICP备14008679号