1 | // |
2 | // Redistribution and use in source and binary forms, with or without |
3 | // modification, are permitted provided that the following conditions |
4 | // are met: |
5 | // * Redistributions of source code must retain the above copyright |
6 | // notice, this list of conditions and the following disclaimer. |
7 | // * Redistributions in binary form must reproduce the above copyright |
8 | // notice, this list of conditions and the following disclaimer in the |
9 | // documentation and/or other materials provided with the distribution. |
10 | // * Neither the name of NVIDIA CORPORATION nor the names of its |
11 | // contributors may be used to endorse or promote products derived |
12 | // from this software without specific prior written permission. |
13 | // |
14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | // |
26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. |
27 | // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. |
28 | // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. |
29 | |
30 | #include "geometry/PxTriangleMesh.h" |
31 | #include "geomutils/GuContactBuffer.h" |
32 | |
33 | #include "GuVecBox.h" |
34 | #include "GuVecConvexHull.h" |
35 | #include "GuVecConvexHullNoScale.h" |
36 | #include "GuVecTriangle.h" |
37 | #include "GuGeometryUnion.h" |
38 | #include "GuContactMethodImpl.h" |
39 | #include "GuHeightField.h" |
40 | #include "GuPCMContactConvexCommon.h" |
41 | #include "GuPCMContactMeshCallback.h" |
42 | |
43 | using namespace physx; |
44 | using namespace Gu; |
45 | using namespace physx::shdfnd::aos; |
46 | |
47 | namespace physx |
48 | { |
49 | |
50 | struct PCMSphereVsHeightfieldContactGenerationCallback : PCMHeightfieldContactGenerationCallback<PCMSphereVsHeightfieldContactGenerationCallback> |
51 | { |
52 | |
53 | public: |
54 | PCMSphereVsMeshContactGeneration mGeneration; |
55 | |
56 | PCMSphereVsHeightfieldContactGenerationCallback( |
57 | const Ps::aos::Vec3VArg sphereCenter, |
58 | const Ps::aos::FloatVArg sphereRadius, |
59 | const Ps::aos::FloatVArg contactDistance, |
60 | const Ps::aos::FloatVArg replaceBreakingThreshold, |
61 | |
62 | const PsTransformV& sphereTransform, |
63 | const PsTransformV& heightfieldTransform, |
64 | const PxTransform& heightfieldTransform1, |
65 | Gu::MultiplePersistentContactManifold& multiManifold, |
66 | Gu::ContactBuffer& contactBuffer, |
67 | Ps::InlineArray<PxU32, LOCAL_CONTACTS_SIZE>* deferredContacts, |
68 | Gu::HeightFieldUtil& hfUtil |
69 | |
70 | |
71 | ) : |
72 | PCMHeightfieldContactGenerationCallback<PCMSphereVsHeightfieldContactGenerationCallback>(hfUtil, heightfieldTransform1), |
73 | mGeneration(sphereCenter, sphereRadius, contactDistance, replaceBreakingThreshold, sphereTransform, |
74 | heightfieldTransform, multiManifold, contactBuffer, deferredContacts) |
75 | { |
76 | } |
77 | |
78 | template<PxU32 CacheSize> |
79 | void processTriangleCache(Gu::TriangleCache<CacheSize>& cache) |
80 | { |
81 | mGeneration.processTriangleCache<CacheSize, PCMSphereVsMeshContactGeneration>(cache); |
82 | } |
83 | |
84 | }; |
85 | |
86 | |
87 | bool Gu::pcmContactSphereHeightField(GU_CONTACT_METHOD_ARGS) |
88 | { |
89 | PX_UNUSED(renderOutput); |
90 | |
91 | const PxSphereGeometry& shapeSphere = shape0.get<const PxSphereGeometry>(); |
92 | const PxHeightFieldGeometryLL& shapeHeight = shape1.get<const PxHeightFieldGeometryLL>(); |
93 | |
94 | Gu::MultiplePersistentContactManifold& multiManifold = cache.getMultipleManifold(); |
95 | |
96 | const QuatV q0 = QuatVLoadA(v: &transform0.q.x); |
97 | const Vec3V p0 = V3LoadA(f: &transform0.p.x); |
98 | |
99 | const QuatV q1 = QuatVLoadA(v: &transform1.q.x); |
100 | const Vec3V p1 = V3LoadA(f: &transform1.p.x); |
101 | |
102 | const FloatV sphereRadius = FLoad(f: shapeSphere.radius); |
103 | const FloatV contactDist = FLoad(f: params.mContactDistance); |
104 | |
105 | const PsTransformV sphereTransform(p0, q0);//sphere transform |
106 | const PsTransformV heightfieldTransform(p1, q1);//height feild |
107 | const PsTransformV curTransform = heightfieldTransform.transformInv(src: sphereTransform); |
108 | |
109 | |
110 | // We must be in local space to use the cache |
111 | |
112 | if(multiManifold.invalidate(curRTrans: curTransform, minMargin: sphereRadius, ratio: FLoad(f: 0.02f))) |
113 | { |
114 | multiManifold.mNumManifolds = 0; |
115 | multiManifold.setRelativeTransform(curTransform); |
116 | |
117 | const FloatV replaceBreakingThreshold = FMul(a: sphereRadius, b: FLoad(f: 0.001f)); |
118 | Gu::HeightFieldUtil hfUtil(shapeHeight); |
119 | const PxVec3 sphereCenterShape1Space = transform1.transformInv(input: transform0.p); |
120 | const Vec3V sphereCenter = V3LoadU(f: sphereCenterShape1Space); |
121 | PxReal inflatedRadius = shapeSphere.radius + params.mContactDistance; |
122 | PxVec3 inflatedRadiusV(inflatedRadius); |
123 | |
124 | PxBounds3 bounds(sphereCenterShape1Space - inflatedRadiusV, sphereCenterShape1Space + inflatedRadiusV); |
125 | |
126 | Ps::InlineArray<PxU32, LOCAL_CONTACTS_SIZE> delayedContacts; |
127 | |
128 | PCMSphereVsHeightfieldContactGenerationCallback blockCallback( |
129 | sphereCenter, |
130 | sphereRadius, |
131 | contactDist, |
132 | replaceBreakingThreshold, |
133 | sphereTransform, |
134 | heightfieldTransform, |
135 | transform1, |
136 | multiManifold, |
137 | contactBuffer, |
138 | &delayedContacts, |
139 | hfUtil); |
140 | |
141 | hfUtil.overlapAABBTriangles(transform1, bounds, flags: 0, callback: &blockCallback); |
142 | |
143 | blockCallback.mGeneration.generateLastContacts(); |
144 | blockCallback.mGeneration.processContacts(GU_SPHERE_MANIFOLD_CACHE_SIZE, isNotLastPatch: false); |
145 | } |
146 | else |
147 | { |
148 | const PsMatTransformV aToB(curTransform); |
149 | const FloatV projectBreakingThreshold = FMul(a: sphereRadius, b: FLoad(f: 0.05f)); |
150 | const FloatV refereshDistance = FAdd(a: sphereRadius, b: contactDist); |
151 | multiManifold.refreshManifold(relTra: aToB, projectBreakingThreshold, contactDist: refereshDistance); |
152 | |
153 | } |
154 | |
155 | return multiManifold.addManifoldContactsToContactBuffer(contactBuffer, trA: sphereTransform, trB: heightfieldTransform, radius: sphereRadius); |
156 | } |
157 | |
158 | |
159 | } |
160 | |