29#ifndef GU_WINDING_NUMBER_T_H
30#define GU_WINDING_NUMBER_T_H
36#include "GuTriangle.h"
37#include "foundation/PxArray.h"
38#include "foundation/PxHashMap.h"
39#include "foundation/PxVec3.h"
41#include "GuAABBTreeQuery.h"
42#include "GuAABBTreeNode.h"
43#include "GuWindingNumberCluster.h"
49 using Triangle = Gu::IndexedTriangleT<PxI32>;
51 template<
typename R,
typename V3>
54 PxMat33 WeightedOuterProductSum;
64 template<
typename R,
typename V3>
65 PX_FORCE_INLINE R firstOrderClusterApproximation(
const V3& weightedCentroid,
const V3& weightedNormalSum,
66 const V3& evaluationPoint)
68 const V3 dir = weightedCentroid - evaluationPoint;
69 const R l = dir.magnitude();
70 return (R(0.25 / 3.141592653589793238462643383) / (l * l * l)) * weightedNormalSum.dot(dir);
72 template<
typename R,
typename V3>
75 return firstOrderClusterApproximation(c.WeightedCentroid, c.WeightedNormalSum, evaluationPoint);
79 template<
typename R,
typename V3>
80 PX_FORCE_INLINE R secondOrderClusterApproximation(
const V3& weightedCentroid,
const V3& weightedNormalSum,
81 const PxMat33& weightedOuterProductSum,
const V3& evaluationPoint)
83 const V3 dir = weightedCentroid - evaluationPoint;
84 const R l = dir.magnitude();
86 const R scaling = R(0.25 / 3.141592653589793238462643383) / (l2 * l);
87 const R firstOrder = scaling * weightedNormalSum.dot(dir);
89 const R scaling2 = -R(3.0) * scaling / l2;
90 const R m11 = scaling + scaling2 * dir.x * dir.x, m12 = scaling2 * dir.x * dir.y, m13 = scaling2 * dir.x * dir.z;
91 const R m21 = scaling2 * dir.y * dir.x, m22 = scaling + scaling2 * dir.y * dir.y, m23 = scaling2 * dir.y * dir.z;
92 const R m31 = scaling2 * dir.z * dir.x, m32 = scaling2 * dir.z * dir.y, m33 = scaling + scaling2 * dir.z * dir.z;
94 return firstOrder + (weightedOuterProductSum.column0.x * m11 + weightedOuterProductSum.column1.x * m12 + weightedOuterProductSum.column2.x * m13 +
95 weightedOuterProductSum.column0.y * m21 + weightedOuterProductSum.column1.y * m22 + weightedOuterProductSum.column2.y * m23 +
96 weightedOuterProductSum.column0.z * m31 + weightedOuterProductSum.column1.z * m32 + weightedOuterProductSum.column2.z * m33);
98 template<
typename R,
typename V3>
99 PX_FORCE_INLINE R clusterApproximation(
const SecondOrderClusterApproximationT<R, V3>& c,
const V3& evaluationPoint)
101 return secondOrderClusterApproximation(c.WeightedCentroid, c.WeightedNormalSum, c.WeightedOuterProductSum, evaluationPoint);
105 template<
typename R,
typename V3>
106 void approximateCluster(
const PxArray<PxI32>& triangleSet, PxU32 start, PxU32 end,
const PxU32* triangles,
const V3* points,
107 const PxArray<R>& triangleAreas,
const PxArray<V3>& triangleNormalsTimesTriangleArea,
const PxArray<V3>& triangleCentroids, ClusterApproximationT<R, V3>& cluster)
109 V3 weightedCentroid(0., 0., 0.);
111 V3 weightedNormalSum(0., 0., 0.);
113 for (PxU32 i = start; i < end; ++i)
115 PxI32 triId = triangleSet[i];
116 areaSum += triangleAreas[triId];
117 weightedCentroid += triangleCentroids[triId] * triangleAreas[triId];
118 weightedNormalSum += triangleNormalsTimesTriangleArea[triId];
120 weightedCentroid = weightedCentroid / areaSum;
123 for (PxU32 i = start; i < end; ++i)
125 PxI32 triId = triangleSet[i];
126 const PxU32* tri = &triangles[3 * triId];
127 R d2 = (weightedCentroid - points[tri[0]]).magnitudeSquared();
128 if (d2 > radiusSquared) radiusSquared = d2;
129 d2 = (weightedCentroid - points[tri[1]]).magnitudeSquared();
130 if (d2 > radiusSquared) radiusSquared = d2;
131 d2 = (weightedCentroid - points[tri[2]]).magnitudeSquared();
132 if (d2 > radiusSquared) radiusSquared = d2;
134 cluster = ClusterApproximationT<R, V3>(
PxSqrt(radiusSquared), areaSum, weightedCentroid, weightedNormalSum);
138 template<
typename R,
typename V3>
139 void approximateCluster(
const PxArray<PxI32>& triangleSet, PxU32 start, PxU32 end,
const PxU32* triangles,
const V3* points,
140 const PxArray<R>& triangleAreas,
const PxArray<V3>& triangleNormalsTimesTriangleArea,
const PxArray<V3>& triangleCentroids, SecondOrderClusterApproximationT<R, V3>& cluster)
142 V3 weightedCentroid(0., 0., 0.);
144 V3 weightedNormalSum(0., 0., 0.);
146 for (PxU32 i = start; i < end; ++i)
148 PxI32 triId = triangleSet[i];
149 areaSum += triangleAreas[triId];
150 weightedCentroid += triangleCentroids[triId] * triangleAreas[triId];
151 weightedNormalSum += triangleNormalsTimesTriangleArea[triId];
153 weightedCentroid = weightedCentroid / areaSum;
156 PxMat33 weightedOuterProductSum(PxZERO::PxZero);
157 for (PxU32 i = start; i < end; ++i)
159 PxI32 triId = triangleSet[i];
160 const PxU32* tri = &triangles[3 * triId];
161 R d2 = (weightedCentroid - points[tri[0]]).magnitudeSquared();
162 if (d2 > radiusSquared) radiusSquared = d2;
163 d2 = (weightedCentroid - points[tri[1]]).magnitudeSquared();
164 if (d2 > radiusSquared) radiusSquared = d2;
165 d2 = (weightedCentroid - points[tri[2]]).magnitudeSquared();
166 if (d2 > radiusSquared) radiusSquared = d2;
168 weightedOuterProductSum = weightedOuterProductSum +
PxMat33::outer(triangleCentroids[triId] - weightedCentroid, triangleNormalsTimesTriangleArea[triId]);
170 cluster = SecondOrderClusterApproximationT<R, V3>(
PxSqrt(radiusSquared), areaSum, weightedCentroid, weightedNormalSum, weightedOuterProductSum);
174 template<
typename R,
typename V3>
177 const R twoOver4PI = R(0.5 / 3.141592653589793238462643383);
183 const R la = a.magnitude(),
187 const R y = 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;
188 const R x = (la * lb * lc + (a.x * b.x + a.y * b.y + a.z * b.z) * lc +
189 (b.x * c.x + b.y * c.y + b.z * c.z) * la + (c.x * a.x + c.y * a.y + c.z * a.z) * lb);
190 return twoOver4PI *
PxAtan2(y, x);
198 Section(PxI32 s, PxI32 e) : start(s), end(e)
203 template<
typename R,
typename V3>
204 void precomputeClusterInformation(PxI32 nodeId,
const BVHNode* tree,
const PxU32* triangles,
const PxU32 numTriangles,
209 stack.pushBack(nodeId);
213 triIndices.
reserve(numTriangles);
214 infos.reserve(PxU32(1.2f*numTriangles));
216 while (stack.size() > 0)
218 nodeId = stack.popBack();
222 const BVHNode& node = tree[nodeId];
225 triIndices.
pushBack(node.getPrimitiveIndex());
230 stack.pushBack(-nodeId - 1);
231 stack.pushBack(node.getPosIndex());
232 stack.pushBack(node.getPosIndex() + 1);
236 Section trianglesA = returnStack.
popBack();
237 Section trianglesB = returnStack.
popBack();
238 Section sum(trianglesB.start, trianglesA.end);
240 nodeId = -nodeId - 1;
241 ClusterApproximationT<R, V3> c;
242 approximateCluster<R, V3>(triIndices, sum.start, sum.end, triangles, points, triangleAreas, triangleNormalsTimesTriangleArea, triangleCentroids, c);
243 infos.insert(PxU32(nodeId), c);
251 template<
typename R,
typename V3>
252 void precomputeClusterInformation(
const BVHNode* tree,
const PxU32* triangles,
const PxU32 numTriangles,
253 const V3* points, PxHashMap<PxU32, ClusterApproximationT<R, V3>>& result, PxI32 rootNodeIndex)
255 PxArray<R> triangleAreas;
256 triangleAreas.
resize(numTriangles);
257 PxArray<V3> triangleNormalsTimesTriangleArea;
258 triangleNormalsTimesTriangleArea.
resize(numTriangles);
259 PxArray<V3> triangleCentroids;
260 triangleCentroids.
resize(numTriangles);
262 for (PxU32 i = 0; i < numTriangles; ++i)
264 const PxU32* tri = &triangles[3 * i];
265 const V3& a = points[tri[0]];
266 const V3& b = points[tri[1]];
267 const V3& c = points[tri[2]];
268 triangleNormalsTimesTriangleArea[i] = (b - a).
cross(c - a) * R(0.5);
269 triangleAreas[i] = triangleNormalsTimesTriangleArea[i].magnitude();
270 triangleCentroids[i] = (a + b + c) * R(1.0 / 3.0);
274 precomputeClusterInformation(rootNodeIndex, tree, triangles, numTriangles, points, result, triangleAreas, triangleNormalsTimesTriangleArea, triangleCentroids);
277 template<
typename R,
typename V3>
281 R mWindingNumber = 0;
283 const PxU32* mTriangles;
287 R mDistanceThresholdBeta;
292 : mTriangles(triangles), mPoints(points), mClusters(clusters), mQueryPoint(queryPoint), mDistanceThresholdBeta(distanceThresholdBeta)
299 PX_ASSERT(node.getNbPrimitives() == 1);
300 const PxU32* tri = &mTriangles[3 * node.getPrimitiveIndex()];
301 mWindingNumber += evaluateExact<R, V3>(mPoints[tri[0]], mPoints[tri[1]], mPoints[tri[2]], mQueryPoint);
302 return Gu::TraversalControl::eDontGoDeeper;
305 const R distSquared = (mQueryPoint - cluster.WeightedCentroid).magnitudeSquared();
306 const R threshold = mDistanceThresholdBeta * cluster.Radius;
307 if (distSquared > threshold * threshold)
310 mWindingNumber += firstOrderClusterApproximation<R, V3>(cluster.WeightedCentroid, cluster.WeightedNormalSum, mQueryPoint);
311 return Gu::TraversalControl::eDontGoDeeper;
313 return Gu::TraversalControl::eGoDeeper;
320 template<
typename R,
typename V3>
322 const PxU32* triangles,
const V3* points)
325 traverseBVH<WindingNumberTraversalController<R, V3>>(tree, c);
326 return c.mWindingNumber;
Definition GuWindingNumberT.h:279
PX_NOINLINE void resize(const uint32_t size, const T &a=T())
Definition PxArray.h:637
PX_FORCE_INLINE uint32_t size() const
Definition PxArray.h:242
PX_FORCE_INLINE T & pushBack(const T &a)
Definition PxArray.h:296
PX_INLINE void reserve(const uint32_t capacity)
Definition PxArray.h:486
PX_INLINE T popBack()
Definition PxArray.h:311
Definition PxHashMap.h:78
PX_CUDA_CALLABLE static PX_INLINE const PxMat33T outer(const PxVec3T< float > &a, const PxVec3T< float > &b)
Computes the outer product of two vectors.
Definition PxMat33.h:194
3x3 matrix class
Definition PxMat33.h:91
GLM_FUNC_QUALIFIER vec< 3, T, Q > cross(vec< 3, T, Q > const &x, vec< 3, T, Q > const &y)
Definition func_geometric.inl:175
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAtan2(float x, float y)
Arctangent of (x/y) with correct sign. Returns angle between -PI and PI in radians Unit: Radians.
Definition PxMath.h:302
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxSqrt(float a)
Square root.
Definition PxMath.h:146
Definition SnippetImmediateMode.cpp:303
Definition GuAABBTreeNode.h:44
Definition GuWindingNumberCluster.h:42
Definition GuWindingNumberT.h:53
Definition GuWindingNumberT.h:194