

Physx之解决三角形顶点相近卡住的问题
source link: http://pkxpp.github.io/2019/11/13/PhysX之解决三角形顶点相近卡住的问题/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

[TOC]
今天遇到一个问题,角色卡在一个模型边上,在PVD看模型也比较正常,一直调试跟踪,最终找到了问题所在。
原因
1.问题出在最后一个sweepCapsuleTriangles函数里面,代码如下:
#ifdef __SPU__ Vec3V dummy1, dummy2; FloatV result = distanceSegmentTriangleSquared( V3LoadU(capsule.p0), V3LoadU(capsule.p1), V3LoadU(p0), V3LoadU(p1), V3LoadU(p2), dummy1, dummy2); PxReal dist2 = FStore(result); #else // AP: switching to SIMD version produced -25% regression in Sweep*SphereHfld PxReal dist2 = distanceSegmentTriangleSquared(capsule.p0, segmentExtent, p0, p1 - p0, p2 - p0); #endif if (dist2<=r2) { hitIndex = i; t = 0.0f; normal = -unitDir; outFlags = PxHitFlag::eDISTANCE|PxHitFlag::eNORMAL; _triNormal = denormalizedNormal.getNormalized(); return true; }
当p0、p1和p2有有两个点相同的时候,会导致p1-p0和p2-p0其中一个向量为0,得到的dist2为负无穷大,所以就会执行代码中的条件语句。最终结果是move函数移动成功了,但是只移动了0的位移,表现上就是一直卡在那个地方。
- 至于顶点一样的情况,其实并不是完全一样,而是有很小的差异。再加上浮点数运算会丢失精度,这个很小的差异被抹掉了,所以到上面代码的时候就出现相同的点了。
计算的代码位置(没看太明白):
PX_FORCE_INLINE void Gu::TriangleMesh::computeWorldTriangle(PxTriangle& worldTri, PxTriangleID triangleIndex, const Cm::Matrix34& worldMatrix, PxU32* PX_RESTRICT vertexIndices, PxU32* PX_RESTRICT adjacencyIndices) const { PxU32 vref0, vref1, vref2; if(mMesh.has16BitIndices()) { const Gu::TriangleT<PxU16>& T = ((const Gu::TriangleT<PxU16>*)getTrianglesFast())[triangleIndex]; vref0 = T.v[0]; vref1 = T.v[1]; vref2 = T.v[2]; } else { const Gu::TriangleT<PxU32>& T = ((const Gu::TriangleT<PxU32>*)getTrianglesFast())[triangleIndex]; vref0 = T.v[0]; vref1 = T.v[1]; vref2 = T.v[2]; } const PxVec3* PX_RESTRICT vertices = getVerticesFast(); worldTri.verts[0] = worldMatrix.transform(vertices[vref0]); worldTri.verts[1] = worldMatrix.transform(vertices[vref1]); worldTri.verts[2] = worldMatrix.transform(vertices[vref2]); if(vertexIndices) { vertexIndices[0] = vref0; vertexIndices[1] = vref1; vertexIndices[2] = vref2; } if(adjacencyIndices) { if(mMesh.getAdjacencies()) { adjacencyIndices[0] = mMesh.getAdjacencies()[triangleIndex*3 + 0]; adjacencyIndices[1] = mMesh.getAdjacencies()[triangleIndex*3 + 1]; adjacencyIndices[2] = mMesh.getAdjacencies()[triangleIndex*3 + 2]; } else { adjacencyIndices[0] = 0xffffffff; adjacencyIndices[1] = 0xffffffff; adjacencyIndices[2] = 0xffffffff; } } }
- 问题数据
出现问题的时候,断点的数据如下:
vertices[vref0] = {x = -4.10000086, y = -0.200000167, z = -3.56512594} vertices[vref1] = {x = -4.10000086, y = -0.200000077, z = -3.56512594} vertices[vref2] = {x = -4.10000086, y = -0.200000212, z = -4.10000229} worldMatrix.transform.base3 = {x=72.3379974 y=4.76143503 z=18.5843773 } // 得到这个三角形前两个点完全一样 worldTri.verts[0] = { x = 68.237990, y = 4.56143475, z = 15.0192509} worldTri.verts[1] = { x = 68.237990, y = 4.56143475, z = 15.0192509} worldTri.verts[2] = { x = 68.237990, y = 4.56143475, z = 14.4843750}
简单来说就是:
4.76143503 + -0.200000167 = 4.56143475 4.76143503 + -0.200000077 = 4.56143475
至于为什么请参考另外一篇文章[1] 为什单精度浮点数的有效位时7位
解决
-
1.把顶点传到PhysX之前,先检查一遍。可以删掉重新组织Vertex和Index,我简单处理的方法是把两个顶点很近的时候,标记为同一个索引,这样的三角形比较容易标识
if (fMinDist <= 1e-5) { // set the same index, and then cooking will process it. eREMOVE_DUPLICATED_TRIANGLES pIndices[3 * i + nIndexIndex1] = pIndices[3 * i + nIndexIndex2]; }
- 2.PhysxCooking的参数增加去重的Flag,这样上面的三角形就会被PhysX剔除,从而就解决了这样的问题:如下
physx::PxCookingParams cookingParams(scale); cookingParams.buildTriangleAdjacencies = true; cookingParams.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES | PxMeshPreprocessingFlag::eREMOVE_UNREFERENCED_VERTICES | PxMeshPreprocessingFlag::eREMOVE_DUPLICATED_TRIANGLES);
参考
[1] 为什么单精度浮点数的精度是7位
Recommend
-
66
-
42
[TOC] 问题描述 有个楼梯的斜面的normal反了,结果会导致模型卡在这个楼梯走不出来,类似于一个封闭的盒子。因为模型现在改不了的缘故,所以就准备技术上先解决一下: 启用double-sided的功能。
-
43
@[toc] 把PhysX vehicle接到我们miniclient中,发现按w键,车子要好半天才启动起来~ 经历 1.各种修改数据,阻尼,弹簧啥的 参考[1] 结果:无果 2.跟源代码,查看数据 跟踪的一些数...
-
6
← 今日好价:联想小新Air15数学家严格证明:二维量子引力理论,真被物理学家“蒙”对了 →majer
-
7
上海本轮疫情和深圳疫情起点时间相近,为何深圳较快的控制住了疫情?两地防控政策有何不同?据上海市卫健委通报:3月24日0—24时,上海新增本土新冠肺炎确诊病例29例和无症状感染者1580例;3月25日深圳市疫...
-
7
Flutter 在 iOS 模拟器中运行卡住问题解决 May 8th, 2022 当我们尝试在 iOS 模拟器运行 flutter run 可能会出现类似如下的卡住问题。 executing: xcrun simctl l...
-
3
英特尔酷睿i5-13400与i5-12600K性能相近,可能是今年最具有性价比的处理器
-
6
经典证明:等边三角形内一点到各顶点的距离长可构成一个三角形 浏览:3044次 出处信息 这是初中平...
-
9
国产系统上解决docker pull卡住的问题 ...
-
4
qemu-user-static 下 cgo go build 卡住的一次解决 ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK