// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // * Neither the name of NVIDIA CORPORATION nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. #ifndef __CONSTRAINT_PREP_SHARED_CUH__ #define __CONSTRAINT_PREP_SHARED_CUH__ #include "PxgBodySim.h" #include "PxgSolverBody.h" #include "PxgConstraint.h" #include "PxgConstraintPrep.h" #include "PxgSolverConstraintDesc.h" #include "PxgSolverCoreDesc.h" #include "DySolverConstraintTypes.h" #include "PxNodeIndex.h" #include "PxgArticulation.h" #include "PxgEdgeType.h" #include "PxgDynamicsConfiguration.h" #include "stdio.h" #include "utils.cuh" #include "PxgSolverFlags.h" #include "DyCpuGpu1dConstraint.h" #include "PxgPartitionNode.h" #define PXC_SAME_NORMAL 0.999f static __device__ physx::PxU32 computeRemapIndexRigidBody(bool isSecondBody, const physx::PxU32* const PX_RESTRICT partitionStartIndices, const physx::PxU32* const PX_RESTRICT partitionArticStartIndices, const physx::PxU32* const PX_RESTRICT partitionJointCounts, const physx::PxU32* const PX_RESTRICT partitionArticulationJointCounts, const physx::PartitionIndexData& indexData, physx::PxgSolverReferences* solverBodyReferences, physx::PxU32 currPartition, physx::PxU32 maxNbPartitions, const physx::PxU32 totalActiveBodyCount, const physx::PxU32 bodyId, const physx::PxU32 activeBodyOffset, const physx::PxU32 totalRigidBatches, const physx::PxU32 totalArticBatches, const physx::PxU32 nbElemsPerBody, const physx::PxU32 nbSlabs, const physx::PxU32 solverBodyOutputVelocityOffset //Only used for assert ) { using namespace physx; //Computes the remapped index for the rigid body being referenced by this constraint. //This is quite complicated. For rigid body constraints, there are up to 32 pairs of rigid bodies referenced //by each constraint batch. //Joints attached to articulations and articulation contacts are indexed similar to rigid bodies. The rigid //bodies for articulation constraints appear after the rigid body constraints in the list, prior to the accumulation buffer. const PxU32 partitionIndex = indexData.mPartitionIndex; //printf("indexData partitionIndex %i\n", partitionIndex); const PxU32 partitionEntryIndex = indexData.mPartitionEntryIndex; //printf("indexData partitionEntryIndex %i\n", partitionEntryIndex); PxU32 index; //printf("indexData type %i\n", indexData.mCType); switch (indexData.mCType) { case PxgEdgeType::eCONTACT_MANAGER: index = partitionStartIndices[partitionIndex] + partitionJointCounts[partitionIndex] + partitionEntryIndex / PXG_BATCH_SIZE; break; case PxgEdgeType::eCONSTRAINT: index = partitionStartIndices[partitionIndex] + partitionEntryIndex / PXG_BATCH_SIZE; break; case PxgEdgeType::eARTICULATION_CONTACT: index = totalRigidBatches + partitionArticStartIndices[partitionIndex] + partitionArticulationJointCounts[partitionIndex] + partitionEntryIndex / PXG_BATCH_SIZE; break; case PxgEdgeType::eARTICULATION_CONSTRAINT: index = totalRigidBatches + partitionArticStartIndices[partitionIndex] + partitionEntryIndex / PXG_BATCH_SIZE; break; default: break; } /*printf("Index is now = %i\n", index); printf("partitionJointCounts[%i] = %i\n", partitionIndex, partitionJointCounts[partitionIndex]); printf("partitionArticStartIndices[%i] = %i\n", partitionIndex, partitionArticStartIndices[partitionIndex]); printf("partitionArticulationJointCounts[%i] = %i\n", partitionIndex, partitionArticulationJointCounts[partitionIndex]); printf("partitionEntryIndex %i\n", partitionEntryIndex);*/ //if (!isArticulation) { //printf("Next is not an articulation constraint!!!\n"); const PxU32 batchMask = PXG_BATCH_SIZE - 1; index = (index*PXG_BATCH_SIZE * 2)*nbElemsPerBody + (partitionEntryIndex & batchMask); if (isSecondBody) index += PXG_BATCH_SIZE*nbElemsPerBody; } //else //{ // //printf("Next is an articulation constraint index = %i!!!\n", index); // //Make sure that there's the slot for index, index+32 // index = ((index & (~31))*nbElemsPerBody) + (index&31); // index += totalRigidBatches * PXG_BATCH_SIZE * 2* nbElemsPerBody; //} //printf("index %i Type = %i\n", index, indexData.mCType); if (bodyId >= activeBodyOffset) { //printf("bodyId>= activeBodyOffset\n"); if ((partitionIndex & (~(maxNbPartitions - 1))) != (currPartition & (~(maxNbPartitions - 1))) || partitionIndex <= currPartition) { //printf("recalculate slabId\n"); //We changed slabs, so we need to introduce a new solver reference PxU32 slabId = partitionIndex / maxNbPartitions; //printf("slabId %i bodyId %i activeBodyOffset%i \n", slabId, bodyId, activeBodyOffset); //PxU32 referenceId = slabId * totalActiveBodyCount + bodyId - activeBodyOffset; //PxU32 referenceId = slabId * totalActiveBodyCount + bodyId - activeBodyOffset; PxU32 referenceId = nbSlabs * (bodyId - activeBodyOffset) + slabId; /*printf("%i: slabId = %i, nbSlabs = %i, bodyId = %i, activeBodyOffset = %i, referenceId = %i\n", threadIdx.x, slabId, nbSlabs, bodyId, activeBodyOffset, referenceId);*/ solverBodyReferences[referenceId].mRemappedBodyIndex = index; referenceId = (referenceId&(~31))*nbElemsPerBody + (referenceId & 31); //printf("solverBodyReferences[%i].mRemappedBodyIndex %i\n", referenceId, solverBodyReferences[referenceId].mRemappedBodyIndex); //Change remap table so that outputs that need to be averaged are placed in a format that is suitable for coalesced loading! //There are totalBatches * 32 * 2 * 2 float4 velocity vectors for the solver, then nbSlabs * bodyCount * 2 float4 velocity vectors for averaging! index = (totalArticBatches + totalRigidBatches) * PXG_BATCH_SIZE * 2 * nbElemsPerBody + referenceId; //printf("TotalRigidBatches = %i, totalArticBatches = %i\n", totalRigidBatches, totalArticBatches); } } assert(index < solverBodyOutputVelocityOffset); return index; } static __device__ PX_FORCE_INLINE bool pointsAreClose(const physx::PxAlignedTransform& body1ToBody0, const float4& localAnchor0, const float4& localAnchor1, const float4& axis, float correlDist) { using namespace physx; const float4 body0PatchPoint1 = body1ToBody0.transform(localAnchor1); return PxAbs(dot3(localAnchor0 - body0PatchPoint1, axis))