00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef NVBLASTINTERNALCOMMON_H
00030 #define NVBLASTINTERNALCOMMON_H
00031 #include "NvBlastExtAuthoringTypes.h"
00032 #include "NvBlastPxSharedHelpers.h"
00033 #include <PxVec2.h>
00034 #include <PxVec3.h>
00035 #include <PxPlane.h>
00036 #include <PxBounds3.h>
00037 #include <PxMath.h>
00038 #include <algorithm>
00039
00040 namespace Nv
00041 {
00042 namespace Blast
00043 {
00044
00048 struct EdgeWithParent
00049 {
00050 uint32_t s, e;
00051 uint32_t parent;
00052 EdgeWithParent() : s(0), e(0), parent(0) {}
00053 EdgeWithParent(uint32_t s, uint32_t e, uint32_t p) : s(s), e(e), parent(p) {}
00054 };
00055
00056
00060 struct EdgeComparator
00061 {
00062 bool operator()(const EdgeWithParent& a, const EdgeWithParent& b) const
00063 {
00064 if (a.parent == b.parent)
00065 {
00066 if (a.s == b.s)
00067 {
00068 return a.e < b.e;
00069 }
00070 else
00071 {
00072 return a.s < b.s;
00073 }
00074 }
00075 else
00076 {
00077 return a.parent < b.parent;
00078 }
00079 }
00080 };
00081
00082 inline bool operator<(const Edge& a, const Edge& b)
00083 {
00084 if (a.s == b.s)
00085 return a.e < b.e;
00086 else
00087 return a.s < b.s;
00088 }
00089
00093 enum ProjectionDirections
00094 {
00095 YZ_PLANE = 1 << 1,
00096 XY_PLANE = 1 << 2,
00097 ZX_PLANE = 1 << 3,
00098
00099 OPPOSITE_WINDING = 1 << 4
00100 };
00101
00105 NV_FORCE_INLINE ProjectionDirections getProjectionDirection(const physx::PxVec3& normal)
00106 {
00107 float maxv = std::max(std::abs(normal.x), std::max(std::abs(normal.y), std::abs(normal.z)));
00108 ProjectionDirections retVal;
00109 if (maxv == std::abs(normal.x))
00110 {
00111 retVal = YZ_PLANE;
00112 if (normal.x < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING);
00113 return retVal;
00114 }
00115 if (maxv == std::abs(normal.y))
00116 {
00117 retVal = ZX_PLANE;
00118 if (normal.y > 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING);
00119 return retVal;
00120 }
00121 retVal = XY_PLANE;
00122 if (normal.z < 0) retVal = (ProjectionDirections)((int)retVal | (int)OPPOSITE_WINDING);
00123 return retVal;
00124 }
00125
00126
00130 NV_FORCE_INLINE physx::PxVec2 getProjectedPoint(const physx::PxVec3& point, ProjectionDirections dir)
00131 {
00132 if (dir & YZ_PLANE)
00133 {
00134 return physx::PxVec2(point.y, point.z);
00135 }
00136 if (dir & ZX_PLANE)
00137 {
00138 return physx::PxVec2(point.x, point.z);
00139 }
00140 return physx::PxVec2(point.x, point.y);
00141 }
00142
00143 NV_FORCE_INLINE physx::PxVec2 getProjectedPoint(const NvcVec3& point, ProjectionDirections dir)
00144 {
00145 return getProjectedPoint((const physx::PxVec3&)point, dir);
00146 }
00147
00151 NV_FORCE_INLINE physx::PxVec2 getProjectedPointWithWinding(const physx::PxVec3& point, ProjectionDirections dir)
00152 {
00153 if (dir & YZ_PLANE)
00154 {
00155 if (dir & OPPOSITE_WINDING)
00156 {
00157 return physx::PxVec2(point.z, point.y);
00158 }
00159 else
00160 return physx::PxVec2(point.y, point.z);
00161 }
00162 if (dir & ZX_PLANE)
00163 {
00164 if (dir & OPPOSITE_WINDING)
00165 {
00166 return physx::PxVec2(point.z, point.x);
00167 }
00168 return physx::PxVec2(point.x, point.z);
00169 }
00170 if (dir & OPPOSITE_WINDING)
00171 {
00172 return physx::PxVec2(point.y, point.x);
00173 }
00174 return physx::PxVec2(point.x, point.y);
00175 }
00176
00177
00178
00179 #define MAXIMUM_EXTENT 1000 * 1000 * 1000
00180 #define BBOX_TEST_EPS 1e-5f
00181
00185 NV_INLINE bool weakBoundingBoxIntersection(const physx::PxBounds3& aBox, const physx::PxBounds3& bBox)
00186 {
00187 if (std::max(aBox.minimum.x, bBox.minimum.x) > std::min(aBox.maximum.x, bBox.maximum.x) + BBOX_TEST_EPS)
00188 return false;
00189 if (std::max(aBox.minimum.y, bBox.minimum.y) > std::min(aBox.maximum.y, bBox.maximum.y) + BBOX_TEST_EPS)
00190 return false;
00191 if (std::max(aBox.minimum.z, bBox.minimum.z) > std::min(aBox.maximum.z, bBox.maximum.z) + BBOX_TEST_EPS)
00192 return false;
00193 return true;
00194 }
00195
00196
00197
00201 NV_INLINE bool getPlaneSegmentIntersection(const physx::PxPlane& pl, const physx::PxVec3& a, const physx::PxVec3& b,
00202 physx::PxVec3& result)
00203 {
00204 float div = (b - a).dot(pl.n);
00205 if (physx::PxAbs(div) < 0.0001f)
00206 {
00207 if (pl.contains(a))
00208 {
00209 result = a;
00210 return true;
00211 }
00212 else
00213 {
00214 return false;
00215 }
00216 }
00217 float t = (-a.dot(pl.n) - pl.d) / div;
00218 if (t < 0.0f || t > 1.0f)
00219 {
00220 return false;
00221 }
00222 result = (b - a) * t + a;
00223 return true;
00224 }
00225
00226
00227 #define POS_COMPARISON_OFFSET 1e-5f
00228 #define NORM_COMPARISON_OFFSET 1e-3f
00229
00232 struct VrtComp
00233 {
00234 bool operator()(const Vertex& a, const Vertex& b) const
00235 {
00236 if (a.p.x + POS_COMPARISON_OFFSET < b.p.x) return true;
00237 if (a.p.x - POS_COMPARISON_OFFSET > b.p.x) return false;
00238 if (a.p.y + POS_COMPARISON_OFFSET < b.p.y) return true;
00239 if (a.p.y - POS_COMPARISON_OFFSET > b.p.y) return false;
00240 if (a.p.z + POS_COMPARISON_OFFSET < b.p.z) return true;
00241 if (a.p.z - POS_COMPARISON_OFFSET > b.p.z) return false;
00242
00243 if (a.n.x + NORM_COMPARISON_OFFSET < b.n.x) return true;
00244 if (a.n.x - NORM_COMPARISON_OFFSET > b.n.x) return false;
00245 if (a.n.y + NORM_COMPARISON_OFFSET < b.n.y) return true;
00246 if (a.n.y - NORM_COMPARISON_OFFSET > b.n.y) return false;
00247 if (a.n.z + NORM_COMPARISON_OFFSET < b.n.z) return true;
00248 if (a.n.z - NORM_COMPARISON_OFFSET > b.n.z) return false;
00249
00250
00251 if (a.uv[0].x + NORM_COMPARISON_OFFSET < b.uv[0].x) return true;
00252 if (a.uv[0].x - NORM_COMPARISON_OFFSET > b.uv[0].x) return false;
00253 if (a.uv[0].y + NORM_COMPARISON_OFFSET < b.uv[0].y) return true;
00254 return false;
00255 };
00256 };
00257
00261 struct VrtPositionComparator
00262 {
00263 bool operator()(const NvcVec3& a, const NvcVec3& b) const
00264 {
00265 if (a.x + POS_COMPARISON_OFFSET < b.x) return true;
00266 if (a.x - POS_COMPARISON_OFFSET > b.x) return false;
00267 if (a.y + POS_COMPARISON_OFFSET < b.y) return true;
00268 if (a.y - POS_COMPARISON_OFFSET > b.y) return false;
00269 if (a.z + POS_COMPARISON_OFFSET < b.z) return true;
00270 if (a.z - POS_COMPARISON_OFFSET > b.z) return false;
00271 return false;
00272 };
00273 bool operator()(const Vertex& a, const Vertex& b) const
00274 {
00275 return operator()(a.p, b.p);
00276 };
00277 };
00278
00279
00280 NV_INLINE float calculateCollisionHullVolume(const CollisionHull& hull)
00281 {
00282 if (hull.pointsCount == 0)
00283 {
00284 return 0.0f;
00285 }
00286
00287
00288 NvcVec3 centroid = { 0.0f, 0.0f, 0.0f };
00289 for (uint32_t i = 0; i < hull.pointsCount; ++i)
00290 {
00291 centroid = centroid + hull.points[i];
00292 }
00293 centroid = centroid / hull.pointsCount;
00294
00295 float volume = 0.0f;
00296
00297 for (uint32_t i = 0; i < hull.polygonDataCount; ++i)
00298 {
00299 const HullPolygon& poly = hull.polygonData[i];
00300 if (poly.vertexCount < 3)
00301 {
00302 continue;
00303 }
00304 const uint32_t i0 = hull.indices[poly.indexBase];
00305 uint32_t i1 = hull.indices[poly.indexBase + 1];
00306 for (uint32_t j = 2; j < poly.vertexCount; ++j)
00307 {
00308 const uint32_t i2 = hull.indices[poly.indexBase + j];
00309 const NvcVec3 a = hull.points[i0] - centroid;
00310 const NvcVec3 b = hull.points[i1] - centroid;
00311 const NvcVec3 c = hull.points[i2] - centroid;
00312 volume +=
00313 (a.x * b.y * c.z - a.x * b.z * c.y - a.y * b.x * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x);
00314 i1 = i2;
00315 }
00316 }
00317 return (1.0f / 6.0f) * std::abs(volume);
00318 }
00319
00320 }
00321 }
00322
00323 #endif