RavEngine
Loading...
Searching...
No Matches
GuCookingGrbTriangleMesh.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef GU_COOKING_GRB_TRIANGLE_MESH_H
30#define GU_COOKING_GRB_TRIANGLE_MESH_H
31
32#include "foundation/PxPlane.h"
33#include "foundation/PxSort.h"
34#include "GuMeshData.h"
35#include "GuTriangle.h"
36#include "GuEdgeList.h"
37#include "cooking/PxCooking.h"
38#include "CmRadixSort.h"
39
40//#define CHECK_OLD_CODE_VS_NEW_CODE
41
42namespace physx
43{
44namespace Gu
45{
46PX_ALIGN_PREFIX(16)
47struct uint4
48{
49 unsigned int x, y, z, w;
50}
51PX_ALIGN_SUFFIX(16);
52
53
54// TODO avoroshilov: remove duplicate definitions
55static const PxU32 BOUNDARY = 0xffffffff;
56static const PxU32 NONCONVEX_FLAG = 0x80000000;
57
58#ifdef CHECK_OLD_CODE_VS_NEW_CODE
59
60struct EdgeTriLookup
61{
62 PxU32 edgeId0, edgeId1;
63 PxU32 triId;
64
65 bool operator < (const EdgeTriLookup& edge1) const
66 {
67 return edgeId0 < edge1.edgeId0 || (edgeId0 == edge1.edgeId0 && edgeId1 < edge1.edgeId1);
68 }
69
70 bool operator <=(const EdgeTriLookup& edge1) const
71 {
72 return edgeId0 < edge1.edgeId0 || (edgeId0 == edge1.edgeId0 && edgeId1 <= edge1.edgeId1);
73 }
74};
75
76static PxU32 binarySearch(const EdgeTriLookup* __restrict data, const PxU32 numElements, const EdgeTriLookup& value)
77{
78 PxU32 left = 0;
79 PxU32 right = numElements;
80
81 while ((right - left) > 1)
82 {
83 const PxU32 pos = (left + right) / 2;
84 const EdgeTriLookup& element = data[pos];
85 if (element <= value)
86 {
87 left = pos;
88 }
89 else
90 {
91 right = pos;
92 }
93 }
94
95 return left;
96}
97
98// slightly different behavior from collide2: boundary edges are filtered out
99
100static PxU32 findAdjacent(const PxVec3* triVertices, const PxVec3* triNormals, const IndexedTriangle32* triIndices,
101 PxU32 nbTris, PxU32 i0, PxU32 i1, const PxPlane& plane,
102 EdgeTriLookup* triLookups, PxU32 triangleIndex)
103{
104 PxU32 result = BOUNDARY;
105 PxReal bestCos = -FLT_MAX;
106
107 EdgeTriLookup lookup;
108 lookup.edgeId0 = PxMin(i0, i1);
109 lookup.edgeId1 = PxMax(i0, i1);
110
111 PxU32 startIndex = binarySearch(triLookups, nbTris * 3, lookup);
112
113 for (PxU32 a = startIndex; a > 0; --a)
114 {
115 if (triLookups[a - 1].edgeId0 == lookup.edgeId0 && triLookups[a - 1].edgeId1 == lookup.edgeId1)
116 startIndex = a - 1;
117 else
118 break;
119 }
120
121 for (PxU32 a = startIndex; a < nbTris * 3; ++a)
122 {
123 const EdgeTriLookup& edgeTri = triLookups[a];
124
125 if (edgeTri.edgeId0 != lookup.edgeId0 || edgeTri.edgeId1 != lookup.edgeId1)
126 break;
127
128 if (edgeTri.triId == triangleIndex)
129 continue;
130
131 const IndexedTriangle32& triIdx = triIndices[edgeTri.triId];
132 const PxU32 vIdx0 = triIdx.mRef[0];
133 const PxU32 vIdx1 = triIdx.mRef[1];
134 const PxU32 vIdx2 = triIdx.mRef[2];
135
136 const PxU32 other = vIdx0 + vIdx1 + vIdx2 - (i0 + i1);
137
138 const PxReal c = plane.n.dot(triNormals[edgeTri.triId]);
139
140 if (plane.distance(triVertices[other]) >= 0 && c > 0.f)
141 return NONCONVEX_FLAG | edgeTri.triId;
142
143 if (c>bestCos)
144 {
145 bestCos = c;
146 result = edgeTri.triId;
147 }
148 }
149
150 return result;
151}
152#endif
153
154static PxU32 findAdjacent(const PxVec3* triVertices, const PxVec3* triNormals, const IndexedTriangle32* triIndices, const PxU32* faceByEdge, PxU32 nbTris, PxU32 i0, PxU32 i1, const PxPlane& plane, PxU32 triangleIndex)
155{
156 PxU32 result = BOUNDARY;
157 PxReal bestCos = -FLT_MAX;
158
159 for(PxU32 i=0; i<nbTris; i++)
160 {
161 const PxU32 candidateTriIndex = faceByEdge[i];
162 if(triangleIndex==candidateTriIndex)
163 continue;
164
165 const IndexedTriangle32& triIdx = triIndices[candidateTriIndex];
166 const PxU32 vIdx0 = triIdx.mRef[0];
167 const PxU32 vIdx1 = triIdx.mRef[1];
168 const PxU32 vIdx2 = triIdx.mRef[2];
169
170 const PxU32 other = vIdx0 + vIdx1 + vIdx2 - (i0 + i1);
171
172 const PxReal c = plane.n.dot(triNormals[candidateTriIndex]);
173
174 if(plane.distance(triVertices[other]) >= 0 && c > 0.f)
175 return NONCONVEX_FLAG | candidateTriIndex;
176
177 if(c>bestCos)
178 {
179 bestCos = c;
180 result = candidateTriIndex;
181 }
182 }
183
184 return result;
185}
186
187static void buildAdjacencies(uint4* triAdjacencies, PxVec3* tempNormalsPerTri_prealloc, const PxVec3* triVertices, const IndexedTriangle32* triIndices, PxU32 nbTris)
188{
189#ifdef CHECK_OLD_CODE_VS_NEW_CODE
190 {
191 EdgeTriLookup* edgeLookups = PX_ALLOCATE(EdgeTriLookup, (nbTris * 3), "edgeLookups");
192
193 for (PxU32 i = 0; i < nbTris; i++)
194 {
195 const IndexedTriangle32& triIdx = triIndices[i];
196 const PxU32 vIdx0 = triIdx.mRef[0];
197 const PxU32 vIdx1 = triIdx.mRef[1];
198 const PxU32 vIdx2 = triIdx.mRef[2];
199
200 tempNormalsPerTri_prealloc[i] = (triVertices[vIdx1] - triVertices[vIdx0]).cross(triVertices[vIdx2] - triVertices[vIdx0]).getNormalized();
201
202 edgeLookups[i * 3].edgeId0 = PxMin(vIdx0, vIdx1);
203 edgeLookups[i * 3].edgeId1 = PxMax(vIdx0, vIdx1);
204 edgeLookups[i * 3].triId = i;
205
206 edgeLookups[i * 3 + 1].edgeId0 = PxMin(vIdx1, vIdx2);
207 edgeLookups[i * 3 + 1].edgeId1 = PxMax(vIdx1, vIdx2);
208 edgeLookups[i * 3 + 1].triId = i;
209
210 edgeLookups[i * 3 + 2].edgeId0 = PxMin(vIdx0, vIdx2);
211 edgeLookups[i * 3 + 2].edgeId1 = PxMax(vIdx0, vIdx2);
212 edgeLookups[i * 3 + 2].triId = i;
213 }
214
215 PxSort<EdgeTriLookup>(edgeLookups, PxU32(nbTris * 3));
216
217 for (PxU32 i = 0; i < nbTris; i++)
218 {
219 const IndexedTriangle32& triIdx = triIndices[i];
220 const PxU32 vIdx0 = triIdx.mRef[0];
221 const PxU32 vIdx1 = triIdx.mRef[1];
222 const PxU32 vIdx2 = triIdx.mRef[2];
223
224 const PxPlane triPlane(triVertices[vIdx0], tempNormalsPerTri_prealloc[i]);
225 uint4 triAdjIdx;
226
227 triAdjIdx.x = findAdjacent(triVertices, tempNormalsPerTri_prealloc, triIndices, nbTris, vIdx0, vIdx1, triPlane, edgeLookups, i);
228 triAdjIdx.y = findAdjacent(triVertices, tempNormalsPerTri_prealloc, triIndices, nbTris, vIdx1, vIdx2, triPlane, edgeLookups, i);
229 triAdjIdx.z = findAdjacent(triVertices, tempNormalsPerTri_prealloc, triIndices, nbTris, vIdx2, vIdx0, triPlane, edgeLookups, i);
230 triAdjIdx.w = 0;
231
232 triAdjacencies[i] = triAdjIdx;
233 }
234
235 PX_FREE(edgeLookups);
236 }
237#endif
238
239 if(1)
240 {
241 EDGELISTCREATE create;
242 create.NbFaces = nbTris;
243 create.DFaces = triIndices->mRef;
244 create.WFaces = NULL;
245 create.FacesToEdges = true;
246 create.EdgesToFaces = true;
247 // PT: important: do NOT set the vertices, it triggers computation of edge flags that we don't need
248 //create.Verts = triVertices;
249 EdgeList edgeList;
250 if(edgeList.init(create))
251 {
252 for(PxU32 i=0; i<nbTris; i++)
253 {
254 const IndexedTriangle32& triIdx = triIndices[i];
255 const PxU32 vIdx0 = triIdx.mRef[0];
256 const PxU32 vIdx1 = triIdx.mRef[1];
257 const PxU32 vIdx2 = triIdx.mRef[2];
258
259 tempNormalsPerTri_prealloc[i] = (triVertices[vIdx1] - triVertices[vIdx0]).cross(triVertices[vIdx2] - triVertices[vIdx0]).getNormalized();
260 }
261
262 const EdgeTriangleData* edgeTriangleData = edgeList.getEdgeTriangles();
263 const EdgeDescData* edgeToTriangle = edgeList.getEdgeToTriangles();
264 const PxU32* faceByEdge = edgeList.getFacesByEdges();
265 PX_ASSERT(edgeList.getNbFaces()==nbTris);
266
267 for(PxU32 i=0; i<nbTris; i++)
268 {
269 const IndexedTriangle32& triIdx = triIndices[i];
270 const PxU32 vIdx0 = triIdx.mRef[0];
271 const PxU32 vIdx1 = triIdx.mRef[1];
272 const PxU32 vIdx2 = triIdx.mRef[2];
273
274 const PxPlane triPlane(triVertices[vIdx0], tempNormalsPerTri_prealloc[i]);
275
276 const EdgeTriangleData& edgeTri = edgeTriangleData[i];
277 const EdgeDescData& edgeData0 = edgeToTriangle[edgeTri.mLink[0] & MSH_EDGE_LINK_MASK];
278 const EdgeDescData& edgeData1 = edgeToTriangle[edgeTri.mLink[1] & MSH_EDGE_LINK_MASK];
279 const EdgeDescData& edgeData2 = edgeToTriangle[edgeTri.mLink[2] & MSH_EDGE_LINK_MASK];
280
281 uint4 triAdjIdx;
282 triAdjIdx.x = findAdjacent(triVertices, tempNormalsPerTri_prealloc, triIndices, faceByEdge + edgeData0.Offset, edgeData0.Count, vIdx0, vIdx1, triPlane, i);
283 triAdjIdx.y = findAdjacent(triVertices, tempNormalsPerTri_prealloc, triIndices, faceByEdge + edgeData1.Offset, edgeData1.Count, vIdx1, vIdx2, triPlane, i);
284 triAdjIdx.z = findAdjacent(triVertices, tempNormalsPerTri_prealloc, triIndices, faceByEdge + edgeData2.Offset, edgeData2.Count, vIdx2, vIdx0, triPlane, i);
285 triAdjIdx.w = 0;
286
287#ifdef CHECK_OLD_CODE_VS_NEW_CODE
288 PX_ASSERT(triAdjacencies[i].x == triAdjIdx.x);
289 PX_ASSERT(triAdjacencies[i].y == triAdjIdx.y);
290 PX_ASSERT(triAdjacencies[i].z == triAdjIdx.z);
291#endif
292 triAdjacencies[i] = triAdjIdx;
293 }
294 }
295 }
296}
297
298}
299}
300
301#endif
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
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 T PxMax(T a, T b)
The return value is the greater of the two specified values.
Definition PxMath.h:72
PX_CUDA_CALLABLE PX_FORCE_INLINE T PxMin(T a, T b)
The return value is the lesser of the two specified values.
Definition PxMath.h:88
Definition GuCookingGrbTriangleMesh.h:48