aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp')
-rw-r--r--PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp857
1 files changed, 857 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp b/PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp
new file mode 100644
index 00000000..cb731d1a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXVehicle/src/PxVehicleWheels.cpp
@@ -0,0 +1,857 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "PxVehicleWheels.h"
+#include "PxVehicleSuspWheelTire4.h"
+#include "PxVehicleSuspLimitConstraintShader.h"
+#include "PxVehicleDefaults.h"
+#include "PxRigidDynamic.h"
+#include "PxShape.h"
+#include "PsUtilities.h"
+#include "CmPhysXCommon.h"
+#include "CmBitMap.h"
+#include "PxPhysics.h"
+#include "PsIntrinsics.h"
+#include "PsFoundation.h"
+
+namespace physx
+{
+
+extern PxVec3 gRight;
+extern PxVec3 gUp;
+extern PxVec3 gForward;
+
+PxF32 gThresholdLongSpeed=5.0f;
+PxU32 gLowLongSpeedSubstepCount=3;
+PxU32 gHighLongSpeedSubstepCount=1;
+PxF32 gMinLongSlipDenominator=4.0f;
+
+extern PxF32 gToleranceScaleLength;
+
+
+PxU32 PxVehicleWheelsSimData::computeByteSize(const PxU32 numWheels)
+{
+ const PxU32 numWheels4 =(((numWheels + 3) & ~3) >> 2);
+ const PxU32 byteSize = sizeof(PxVehicleWheels4SimData)*numWheels4 + sizeof(PxVehicleAntiRollBarData)*2*numWheels4;
+ return byteSize;
+}
+
+PxU8* PxVehicleWheelsSimData::patchUpPointers(const PxU32 numWheels, PxVehicleWheelsSimData* simData, PxU8* ptrIn)
+{
+ const PxU32 numWheels4 =(((numWheels + 3) & ~3) >> 2);
+ PxU8* ptr = ptrIn;
+ simData->mWheels4SimData = reinterpret_cast<PxVehicleWheels4SimData*>(ptr);
+ ptr += sizeof(PxVehicleWheels4SimData)*numWheels4;
+ simData->mAntiRollBars = reinterpret_cast<PxVehicleAntiRollBarData*>(ptr);
+ ptr += sizeof(PxVehicleAntiRollBarData)*numWheels4*2;
+ PX_ASSERT((ptrIn + computeByteSize(numWheels)) == ptr);
+ return ptr;
+}
+
+PxVehicleWheelsSimData::PxVehicleWheelsSimData(const PxU32 numWheels)
+{
+ const PxU32 numWheels4 =(((numWheels + 3) & ~3) >> 2);
+
+ //Set numWheels
+ mNbWheels4 = numWheels4;
+ mNbActiveWheels = numWheels;
+
+ //Set numAntiRollBars to zero.
+ mNbAntiRollBars4 = 2*numWheels4;
+ mNbActiveAntiRollBars = 0;
+
+ //Placement new for wheels4
+ for(PxU32 i=0;i<numWheels4;i++)
+ {
+ new(&mWheels4SimData[i]) PxVehicleWheels4SimData();
+ }
+
+ //Placement new for anti-roll bars
+ for(PxU32 i=0;i<numWheels4*2;i++)
+ {
+ new(&mAntiRollBars[i]) PxVehicleAntiRollBarData();
+ }
+
+ //Placement new for tire load filter data.
+ new(&mNormalisedLoadFilter) PxVehicleTireLoadFilterData();
+
+ //Enable used wheels, disabled unused wheels.
+ PxMemZero(mActiveWheelsBitmapBuffer, sizeof(PxU32) * (((PX_MAX_NB_WHEELS + 31) & ~31) >> 5));
+ for(PxU32 i=0;i<numWheels;i++)
+ {
+ //Enabled used wheel.
+ enableWheel(i);
+ setWheelShapeMapping(i,PxI32(i));
+ setSceneQueryFilterData(i, PxFilterData());
+ }
+ for(PxU32 i=numWheels;i<numWheels4*4;i++)
+ {
+ //Disable unused wheel.
+ disableWheel(i);
+ setWheelShapeMapping(i,-1);
+ setSceneQueryFilterData(i, PxFilterData());
+ }
+
+ //Default values for substep count computation.
+ mThresholdLongitudinalSpeed = gThresholdLongSpeed*gToleranceScaleLength;
+ mLowForwardSpeedSubStepCount = gLowLongSpeedSubstepCount;
+ mHighForwardSpeedSubStepCount = gHighLongSpeedSubstepCount;
+ mMinLongSlipDenominator = gMinLongSlipDenominator*gToleranceScaleLength;
+}
+
+PxVehicleWheelsSimData* PxVehicleWheelsSimData::allocate(const PxU32 numWheels)
+{
+ //Byte size
+ const PxU32 byteSize = sizeof(PxVehicleWheelsSimData) + computeByteSize(numWheels);
+
+ //Allocate
+ PxU8* ptrStart = static_cast<PxU8*>(PX_ALLOC(byteSize, "PxVehicleWheelsSimData"));
+
+ //Patchup pointers
+ PxU8* ptr = ptrStart;
+ PxVehicleWheelsSimData* simData = reinterpret_cast<PxVehicleWheelsSimData*>(ptr);
+ ptr += sizeof(PxVehicleWheelsSimData);
+ ptr = patchUpPointers(numWheels, simData, ptr);
+ PX_ASSERT((ptrStart+ byteSize) == ptr);
+
+ //Constructor.
+ new(simData) PxVehicleWheelsSimData(numWheels);
+
+ //Finished.
+ return simData;
+}
+
+void PxVehicleWheelsSimData::setChassisMass(const PxF32 chassisMass)
+{
+
+ //Target spring natural frequency = 9.66
+ //Target spring damping ratio = 0.62
+ const PxF32 mult=1.0f/(1.0f*mNbActiveWheels);
+ const PxF32 sprungMass=chassisMass*mult;
+ const PxF32 w0=9.66f;
+ const PxF32 r=0.62f;
+ for(PxU32 i=0;i<mNbActiveWheels;i++)
+ {
+ PxVehicleSuspensionData susp=getSuspensionData(i);
+ susp.mSprungMass=sprungMass;
+ susp.mSpringStrength=w0*w0*sprungMass;
+ susp.mSpringDamperRate=r*2*sprungMass*w0;
+ setSuspensionData(i,susp);
+ }
+}
+
+void PxVehicleWheelsSimData::free()
+{
+ for(PxU32 i=0;i<mNbWheels4;i++)
+ {
+ mWheels4SimData[i].~PxVehicleWheels4SimData();
+ }
+
+ PX_FREE(this);
+}
+
+PxVehicleWheelsSimData& PxVehicleWheelsSimData::operator=(const PxVehicleWheelsSimData& src)
+{
+ PX_CHECK_MSG(mNbActiveWheels == src.mNbActiveWheels, "target PxVehicleSuspWheelTireNSimData must match the number of wheels in src");
+
+ for(PxU32 i=0;i<src.mNbWheels4;i++)
+ {
+ mWheels4SimData[i] = src.mWheels4SimData[i];
+ }
+
+ mNbActiveAntiRollBars = src.mNbActiveAntiRollBars;
+ for(PxU32 i=0; i<src.mNbActiveAntiRollBars; i++)
+ {
+ mAntiRollBars[i] = src.mAntiRollBars[i];
+ }
+
+ mNormalisedLoadFilter = src.mNormalisedLoadFilter;
+
+ mThresholdLongitudinalSpeed = src.mThresholdLongitudinalSpeed;
+ mLowForwardSpeedSubStepCount = src.mLowForwardSpeedSubStepCount;
+ mHighForwardSpeedSubStepCount = src.mHighForwardSpeedSubStepCount;
+ mMinLongSlipDenominator = src.mMinLongSlipDenominator;
+
+ PxMemCopy(mActiveWheelsBitmapBuffer, src.mActiveWheelsBitmapBuffer, sizeof(PxU32)* (((PX_MAX_NB_WHEELS + 31) & ~31) >> 5));
+
+ return *this;
+}
+
+void PxVehicleWheelsSimData::copy(const PxVehicleWheelsSimData& src, const PxU32 srcWheel, const PxU32 wheel)
+{
+ PX_CHECK_AND_RETURN(srcWheel < src.mNbActiveWheels, "Illegal src wheel");
+ PX_CHECK_AND_RETURN(wheel < mNbActiveWheels, "Illegal target wheel");
+
+ setSuspensionData(wheel,src.getSuspensionData(srcWheel));
+ setWheelData(wheel,src.getWheelData(srcWheel));
+ setTireData(wheel,src.getTireData(srcWheel));
+ setSuspTravelDirection(wheel,src.getSuspTravelDirection(srcWheel));
+ setSuspForceAppPointOffset(wheel,src.getSuspForceAppPointOffset(srcWheel));
+ setTireForceAppPointOffset(wheel,src.getTireForceAppPointOffset(srcWheel));
+ setWheelCentreOffset(wheel,src.getWheelCentreOffset(srcWheel));
+ setWheelShapeMapping(wheel, src.getWheelShapeMapping(srcWheel));
+ setSceneQueryFilterData(wheel, src.getSceneQueryFilterData(srcWheel));
+ if(src.getIsWheelDisabled(srcWheel))
+ disableWheel(wheel);
+ else
+ enableWheel(wheel);
+}
+
+bool PxVehicleWheelsSimData::isValid() const
+{
+ for(PxU32 i=0;i<mNbWheels4-1;i++)
+ {
+ mWheels4SimData[i].isValid(0);
+ mWheels4SimData[i].isValid(1);
+ mWheels4SimData[i].isValid(2);
+ mWheels4SimData[i].isValid(3);
+ }
+ const PxU32 numInLastBlock = 4 - (4*mNbWheels4 - mNbActiveWheels);
+ for(PxU32 i=0;i<numInLastBlock;i++)
+ {
+ mWheels4SimData[mNbWheels4-1].isValid(i);
+ }
+
+ PX_CHECK_AND_RETURN_VAL(mNormalisedLoadFilter.isValid(), "Invalid PxVehicleWheelsSimData.mNormalisedLoadFilter", false);
+ return true;
+}
+
+void PxVehicleWheelsSimData::disableWheel(const PxU32 wheel)
+{
+ PX_CHECK_AND_RETURN(wheel < 4*mNbWheels4, "PxVehicleWheelsSimData::disableWheel - Illegal wheel");
+
+ Cm::BitMap bm;
+ bm.setWords(mActiveWheelsBitmapBuffer, ((PX_MAX_NB_WHEELS + 31) & ~31) >> 5);
+ bm.reset(wheel);
+}
+
+void PxVehicleWheelsSimData::enableWheel(const PxU32 wheel)
+{
+ PX_CHECK_AND_RETURN(wheel < 4*mNbWheels4, "PxVehicleWheelsSimData::disableWheel - Illegal wheel");
+
+ Cm::BitMap bm;
+ bm.setWords(mActiveWheelsBitmapBuffer, ((PX_MAX_NB_WHEELS + 31) & ~31) >> 5);
+ bm.set(wheel);
+}
+
+bool PxVehicleWheelsSimData::getIsWheelDisabled(const PxU32 wheel) const
+{
+ PX_CHECK_AND_RETURN_VAL(wheel < 4*mNbWheels4, "PxVehicleWheelsSimData::getIsWheelDisabled - Illegal wheel", false);
+ Cm::BitMap bm;
+ bm.setWords(const_cast<PxU32*>(mActiveWheelsBitmapBuffer), ((PX_MAX_NB_WHEELS + 31) & ~31) >> 5);
+ return (bm.test(wheel) ? false : true);
+}
+
+const PxVehicleSuspensionData& PxVehicleWheelsSimData::getSuspensionData(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getSuspensionData - Illegal wheel");
+ return mWheels4SimData[id>>2].getSuspensionData(id & 3);
+}
+
+const PxVehicleWheelData& PxVehicleWheelsSimData::getWheelData(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getWheelData - Illegal wheel");
+ return mWheels4SimData[id>>2].getWheelData(id & 3);
+}
+
+const PxVehicleTireData& PxVehicleWheelsSimData::getTireData(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getTireData - Illegal wheel");
+ return mWheels4SimData[id>>2].getTireData(id & 3);
+}
+
+const PxVec3& PxVehicleWheelsSimData::getSuspTravelDirection(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getSuspTravelDirection - Illegal wheel");
+ return mWheels4SimData[id>>2].getSuspTravelDirection(id & 3);
+}
+
+const PxVec3& PxVehicleWheelsSimData::getSuspForceAppPointOffset(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getSuspForceAppPointOffset - Illegal wheel");
+ return mWheels4SimData[id>>2].getSuspForceAppPointOffset(id & 3);
+}
+
+const PxVec3& PxVehicleWheelsSimData::getTireForceAppPointOffset(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getTireForceAppPointOffset - Illegal wheel");
+ return mWheels4SimData[id>>2].getTireForceAppPointOffset(id & 3);
+}
+
+const PxVec3& PxVehicleWheelsSimData::getWheelCentreOffset(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getWheelCentreOffset - Illegal wheel");
+ return mWheels4SimData[id>>2].getWheelCentreOffset(id & 3);
+}
+
+PxI32 PxVehicleWheelsSimData::getWheelShapeMapping(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getWheelShapeMapping - Illegal wheel");
+ return mWheels4SimData[id>>2].getWheelShapeMapping(id & 3);
+}
+
+const PxFilterData& PxVehicleWheelsSimData::getSceneQueryFilterData(const PxU32 id) const
+{
+ PX_CHECK_MSG(id < 4*mNbWheels4, "PxVehicleWheelsSimData::getSceneQueryFilterData - Illegal wheel");
+ return mWheels4SimData[id>>2].getSceneQueryFilterData(id & 3);
+}
+
+const PxVehicleAntiRollBarData& PxVehicleWheelsSimData::getAntiRollBarData(const PxU32 antiRollId) const
+{
+ PX_CHECK_MSG(antiRollId < mNbActiveAntiRollBars, "PxVehicleWheelsSimData::getAntiRollBarData - Illegal anti-roll bar");
+ return mAntiRollBars[antiRollId];
+}
+
+void PxVehicleWheelsSimData::setSuspensionData(const PxU32 id, const PxVehicleSuspensionData& susp)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setSuspensionData - Illegal wheel");
+ mWheels4SimData[id>>2].setSuspensionData(id & 3, susp);
+}
+
+void PxVehicleWheelsSimData::setWheelData(const PxU32 id, const PxVehicleWheelData& wheel)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setWheelData - Illegal wheel");
+ mWheels4SimData[id>>2].setWheelData(id & 3, wheel);
+}
+
+void PxVehicleWheelsSimData::setTireData(const PxU32 id, const PxVehicleTireData& tire)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setTireData - Illegal wheel");
+ mWheels4SimData[id>>2].setTireData(id & 3, tire);
+}
+
+void PxVehicleWheelsSimData::setSuspTravelDirection(const PxU32 id, const PxVec3& dir)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setSuspTravelDirection - Illegal wheel");
+ mWheels4SimData[id>>2].setSuspTravelDirection(id & 3, dir);
+}
+
+void PxVehicleWheelsSimData::setSuspForceAppPointOffset(const PxU32 id, const PxVec3& offset)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setSuspForceAppPointOffset - Illegal wheel");
+ mWheels4SimData[id>>2].setSuspForceAppPointOffset(id & 3, offset);
+}
+
+void PxVehicleWheelsSimData::setTireForceAppPointOffset(const PxU32 id, const PxVec3& offset)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setTireForceAppPointOffset - Illegal wheel");
+ mWheels4SimData[id>>2].setTireForceAppPointOffset(id & 3, offset);
+}
+
+void PxVehicleWheelsSimData::setWheelCentreOffset(const PxU32 id, const PxVec3& offset)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setWheelCentreOffset - Illegal wheel");
+ mWheels4SimData[id>>2].setWheelCentreOffset(id & 3, offset);
+}
+
+void PxVehicleWheelsSimData::setWheelShapeMapping(const PxU32 id, const PxI32 shapeId)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setWheelShapeMapping - Illegal wheel");
+ mWheels4SimData[id>>2].setWheelShapeMapping(id & 3, shapeId);
+}
+
+void PxVehicleWheelsSimData::setSceneQueryFilterData(const PxU32 id, const PxFilterData& sqFilterData)
+{
+ PX_CHECK_AND_RETURN(id < 4*mNbWheels4, "PxVehicleWheelsSimData::setSceneQueryFilterData - Illegal wheel");
+ mWheels4SimData[id>>2].setSceneQueryFilterData(id & 3, sqFilterData);
+}
+
+void PxVehicleWheelsSimData::setTireLoadFilterData(const PxVehicleTireLoadFilterData& tireLoadFilter)
+{
+ PX_CHECK_AND_RETURN(tireLoadFilter.mMaxNormalisedLoad>tireLoadFilter.mMinNormalisedLoad, "Illegal graph points");
+ PX_CHECK_AND_RETURN(tireLoadFilter.mMaxFilteredNormalisedLoad>0, "Max filtered load must be greater than zero");
+ mNormalisedLoadFilter=tireLoadFilter;
+ mNormalisedLoadFilter.mDenominator=1.0f/(mNormalisedLoadFilter.mMaxNormalisedLoad-mNormalisedLoadFilter.mMinNormalisedLoad);
+}
+
+PxU32 PxVehicleWheelsSimData::addAntiRollBarData(const PxVehicleAntiRollBarData& antiRollBar)
+{
+ PX_CHECK_AND_RETURN_VAL(antiRollBar.isValid(), "Illegal antiRollBar", 0xffffffff)
+ PX_CHECK_AND_RETURN_VAL(antiRollBar.mWheel0 < mNbActiveWheels, "Illegal wheel0", 0xffffffff);
+ PX_CHECK_AND_RETURN_VAL(antiRollBar.mWheel1 < mNbActiveWheels, "Illegal wheel1", 0xffffffff);
+
+ //If the anti-roll pair already exists then modify it.
+ for(PxU32 i = 0; i < mNbActiveAntiRollBars; i++)
+ {
+ if( ((mAntiRollBars[i].mWheel0 == antiRollBar.mWheel0) && (mAntiRollBars[i].mWheel1 == antiRollBar.mWheel1)) ||
+ ((mAntiRollBars[i].mWheel1 == antiRollBar.mWheel0) && (mAntiRollBars[i].mWheel0 == antiRollBar.mWheel1)) )
+ {
+ mAntiRollBars[i].mStiffness = antiRollBar.mStiffness;
+ return i;
+ }
+ }
+
+ //Check we have space for an extra anti-roll bar.
+ PX_CHECK_AND_RETURN_VAL(mNbActiveAntiRollBars < 2*mNbWheels4, "The buffer of anti-roll bars is full", 0xffffffff);
+
+ //Add a new anti-roll bar.
+ const PxU32 id = mNbActiveAntiRollBars;
+ mAntiRollBars[mNbActiveAntiRollBars] = antiRollBar;
+ mNbActiveAntiRollBars++;
+
+ //Finished.
+ return id;
+}
+
+//Only used for serialization.
+void PxVehicleWheelsSimData::setAntiRollBarData(const PxU32 id, const PxVehicleAntiRollBarData& antiRoll)
+{
+ PX_UNUSED(id);
+ addAntiRollBarData(antiRoll);
+}
+
+void PxVehicleWheelsSimData::setSubStepCount(const PxReal thresholdLongitudinalSpeed, const PxU32 lowForwardSpeedSubStepCount, const PxU32 highForwardSpeedSubStepCount)
+{
+ PX_CHECK_AND_RETURN(thresholdLongitudinalSpeed>=0, "thresholdLongitudinalSpeed must be greater than or equal to zero.");
+ PX_CHECK_AND_RETURN(lowForwardSpeedSubStepCount>0, "lowForwardSpeedSubStepCount must be greater than zero.");
+ PX_CHECK_AND_RETURN(highForwardSpeedSubStepCount>0, "highForwardSpeedSubStepCount must be greater than zero.");
+
+ mThresholdLongitudinalSpeed=thresholdLongitudinalSpeed;
+ mLowForwardSpeedSubStepCount=lowForwardSpeedSubStepCount;
+ mHighForwardSpeedSubStepCount=highForwardSpeedSubStepCount;
+}
+
+void PxVehicleWheelsSimData::setMinLongSlipDenominator(const PxReal minLongSlipDenominator)
+{
+ PX_CHECK_AND_RETURN(minLongSlipDenominator>0, "minLongSlipDenominator must be greater than or equal to zero.");
+ mMinLongSlipDenominator=minLongSlipDenominator;
+}
+
+
+
+/////////////////////////////
+
+PxU32 PxVehicleWheelsDynData::computeByteSize(const PxU32 numWheels)
+{
+ const PxU32 numWheels4 =(((numWheels + 3) & ~3) >> 2);
+ const PxU32 byteSize =
+ sizeof(PxVehicleWheels4DynData)*numWheels4 +
+ sizeof(PxVehicleTireForceCalculator) + sizeof(void*)*4*numWheels4 +
+ sizeof(void*)*4*numWheels4 +
+ sizeof(PxVehicleConstraintShader)*numWheels4;
+ return byteSize;
+}
+
+PxU8* PxVehicleWheelsDynData::patchUpPointers(const PxU32 numWheels, PxVehicleWheelsDynData* dynData, PxU8* ptrIn)
+{
+ const PxU32 numWheels4 =(((numWheels + 3) & ~3) >> 2);
+ PxU8* ptr = ptrIn;
+ dynData->mWheels4DynData = reinterpret_cast<PxVehicleWheels4DynData*>(ptr);
+ ptr += sizeof(PxVehicleWheels4DynData)*numWheels4;
+ dynData->mTireForceCalculators = reinterpret_cast<PxVehicleTireForceCalculator*>(ptr);
+ ptr += sizeof(PxVehicleTireForceCalculator);
+ dynData->mTireForceCalculators->mShaderData = reinterpret_cast<const void**>(ptr);
+ ptr += sizeof(void*)*4*numWheels4;
+ dynData->mUserDatas = reinterpret_cast<void**>(ptr);
+ ptr += sizeof(void*)*4*numWheels4;
+ for(PxU32 i=0;i<numWheels4;i++)
+ {
+ PxVehicleConstraintShader* shader = new(ptr) PxVehicleConstraintShader();
+ dynData->mWheels4DynData[i].setVehicleConstraintShader(shader);
+ ptr += sizeof(PxVehicleConstraintShader);
+ }
+
+ PX_ASSERT((ptrIn + computeByteSize(numWheels)) == ptr);
+ return ptr;
+}
+
+PxVehicleWheelsDynData::PxVehicleWheelsDynData(const PxU32 numWheels)
+{
+ const PxU32 numWheels4 =(((numWheels + 3) & ~3) >> 2);
+
+ mNbWheels4=numWheels4;
+ mNbActiveWheels=numWheels;
+
+ //Placement new for wheels4
+ for(PxU32 i=0;i<numWheels4;i++)
+ {
+ new(&mWheels4DynData[i]) PxVehicleWheels4DynData();
+ }
+
+ //Initialise tire calculator
+ for(PxU32 i=0;i<4*numWheels4;i++)
+ {
+ mTireForceCalculators->mShaderData[i]=NULL;
+ }
+ new(mTireForceCalculators) PxVehicleTireForceCalculator;
+
+ //Initialise user data
+ for(PxU32 i=0;i<4*numWheels4;i++)
+ {
+ mUserDatas[i]=NULL;
+ }
+}
+
+bool PxVehicleWheelsDynData::isValid() const
+{
+ for(PxU32 i=0;i<mNbWheels4;i++)
+ {
+ PX_CHECK_AND_RETURN_VAL(mWheels4DynData[i].isValid(), "Invalid PxVehicleSuspWheelTireNDynData.mSuspWheelTire4DynData[i]", false);
+ }
+ return true;
+}
+
+void PxVehicleWheelsDynData::setToRestState()
+{
+ //Set susp/wheel/tires to rest state.
+ const PxU32 numSuspWheelTire4=mNbWheels4;
+ for(PxU32 i=0;i<numSuspWheelTire4;i++)
+ {
+ mWheels4DynData[i].setToRestState();
+ }
+}
+
+void PxVehicleWheelsDynData::setTireForceShaderFunction(PxVehicleComputeTireForce tireForceShaderFn)
+{
+ mTireForceCalculators->mShader=tireForceShaderFn;
+}
+
+void PxVehicleWheelsDynData::setTireForceShaderData(const PxU32 tireId, const void* tireForceShaderData)
+{
+ PX_CHECK_AND_RETURN(tireId < mNbActiveWheels, "PxVehicleWheelsDynData::setTireForceShaderData - Illegal tire");
+ mTireForceCalculators->mShaderData[tireId]=tireForceShaderData;
+}
+
+const void* PxVehicleWheelsDynData::getTireForceShaderData(const PxU32 tireId) const
+{
+ PX_CHECK_AND_RETURN_VAL(tireId < mNbActiveWheels, "PxVehicleWheelsDynData::getTireForceShaderData - Illegal tire", NULL);
+ return mTireForceCalculators->mShaderData[tireId];
+}
+
+void PxVehicleWheelsDynData::setWheelRotationSpeed(const PxU32 wheelIdx, const PxReal speed)
+{
+ PX_CHECK_AND_RETURN(wheelIdx < mNbActiveWheels, "PxVehicleWheelsDynData::setWheelRotationSpeed - Illegal wheel");
+ PxVehicleWheels4DynData& suspWheelTire4=mWheels4DynData[(wheelIdx>>2)];
+ suspWheelTire4.mWheelSpeeds[wheelIdx & 3] = speed;
+ suspWheelTire4.mCorrectedWheelSpeeds[wheelIdx & 3] = speed;
+}
+
+PxReal PxVehicleWheelsDynData::getWheelRotationSpeed(const PxU32 wheelIdx) const
+{
+ PX_CHECK_AND_RETURN_VAL(wheelIdx < mNbActiveWheels, "PxVehicleWheelsDynData::getWheelRotationSpeed - Illegal wheel", 0.0f);
+ const PxVehicleWheels4DynData& suspWheelTire4=mWheels4DynData[(wheelIdx>>2)];
+ return suspWheelTire4.mCorrectedWheelSpeeds[wheelIdx & 3];
+}
+
+void PxVehicleWheelsDynData::setWheelRotationAngle(const PxU32 wheelIdx, const PxReal angle)
+{
+ PX_CHECK_AND_RETURN(wheelIdx < mNbActiveWheels, "PxVehicleWheelsDynData::setWheelRotationAngle - Illegal wheel");
+ PxVehicleWheels4DynData& suspWheelTire4=mWheels4DynData[(wheelIdx>>2)];
+ suspWheelTire4.mWheelRotationAngles[wheelIdx & 3] = angle;
+}
+
+PxReal PxVehicleWheelsDynData::getWheelRotationAngle(const PxU32 wheelIdx) const
+{
+ PX_CHECK_AND_RETURN_VAL(wheelIdx < mNbActiveWheels, "PxVehicleWheelsDynData::getWheelRotationAngle - Illegal wheel", 0.0f);
+ const PxVehicleWheels4DynData& suspWheelTire4=mWheels4DynData[(wheelIdx>>2)];
+ return suspWheelTire4.mWheelRotationAngles[wheelIdx & 3];
+}
+
+void PxVehicleWheels::setToRestState()
+{
+ //Set the rigid body to rest and clear all the accumulated forces and impulses.
+ if(!(mActor->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
+ {
+ mActor->setLinearVelocity(PxVec3(0,0,0));
+ mActor->setAngularVelocity(PxVec3(0,0,0));
+ mActor->clearForce(PxForceMode::eACCELERATION);
+ mActor->clearForce(PxForceMode::eVELOCITY_CHANGE);
+ mActor->clearTorque(PxForceMode::eACCELERATION);
+ mActor->clearTorque(PxForceMode::eVELOCITY_CHANGE);
+ }
+
+ //Set the wheels to rest state.
+ mWheelsDynData.setToRestState();
+}
+
+bool PxVehicleWheels::isValid() const
+{
+ PX_CHECK_AND_RETURN_VAL(mWheelsSimData.isValid(), "invalid mWheelsSimData", false);
+ PX_CHECK_AND_RETURN_VAL(mWheelsDynData.isValid(), "invalid mWheelsDynData", false);
+ return true;
+}
+
+PxU32 PxVehicleWheels::computeByteSize(const PxU32 numWheels)
+{
+ const PxU32 byteSize =
+ PxVehicleWheelsSimData::computeByteSize(numWheels) +
+ PxVehicleWheelsDynData::computeByteSize(numWheels);
+ return byteSize;
+}
+
+PxU8* PxVehicleWheels::patchupPointers(const PxU32 numWheels, PxVehicleWheels* vehWheels, PxU8* ptrIn)
+{
+ PxU8* ptr = ptrIn;
+ ptr = PxVehicleWheelsSimData::patchUpPointers(numWheels, &vehWheels->mWheelsSimData, ptr);
+ ptr = PxVehicleWheelsDynData::patchUpPointers(numWheels, &vehWheels->mWheelsDynData, ptr);
+ PX_ASSERT((ptrIn + computeByteSize(numWheels)) == ptr);
+ return ptr;
+}
+
+void PxVehicleWheels::init(const PxU32 numWheels)
+{
+ new(&mWheelsSimData) PxVehicleWheelsSimData(numWheels);
+ new(&mWheelsDynData) PxVehicleWheelsDynData(numWheels);
+
+ for(PxU32 i = 0; i < mWheelsSimData.mNbWheels4; i++)
+ {
+ new(&mWheelsDynData.mWheels4DynData[i].getVehicletConstraintShader()) PxVehicleConstraintShader(this);
+ }
+
+ mOnConstraintReleaseCounter = Ps::to8(mWheelsSimData.mNbWheels4);
+}
+
+void PxVehicleWheels::free()
+{
+ PX_CHECK_AND_RETURN(mWheelsSimData.mNbWheels4>0, "Cars with zero wheels are illegal");
+
+ const PxU32 numSuspWheelTire4 = mWheelsSimData.mNbWheels4;
+
+ for(PxU32 i=0;i<numSuspWheelTire4;i++)
+ {
+ mWheelsDynData.mWheels4DynData[i].getVehicletConstraintShader().release();
+ }
+}
+
+static PxConstraintShaderTable t =
+ {
+ PxVehicleConstraintShader::vehicleSuspLimitConstraintSolverPrep,
+ 0,
+ PxVehicleConstraintShader::visualiseConstraint,
+ PxConstraintFlag::Enum(0)
+ };
+
+void PxVehicleWheels::setup
+(PxPhysics* physics, PxRigidDynamic* vehActor,
+ const PxVehicleWheelsSimData& wheelsData,
+ const PxU32 numDrivenWheels, const PxU32 numNonDrivenWheels)
+{
+ mNbNonDrivenWheels = numNonDrivenWheels;
+
+ PX_CHECK_AND_RETURN(wheelsData.getNbWheels() == mWheelsSimData.getNbWheels(), "PxVehicleWheels::setup - vehicle must be setup with same number of wheels as wheelsData");
+ PX_CHECK_AND_RETURN(vehActor, "PxVehicleWheels::setup - vehActor is null ptr : you need to instantiate an empty PxRigidDynamic for the vehicle");
+ PX_CHECK_AND_RETURN(wheelsData.isValid(), "PxVehicleWheels::setup -invalid wheelsData");
+ PX_UNUSED(numDrivenWheels);
+
+#if PX_CHECKED
+ PxF32 totalSprungMass=0.0f;
+ for(PxU32 i=0;i<(numDrivenWheels+numNonDrivenWheels);i++)
+ {
+ totalSprungMass+=wheelsData.getSuspensionData(i).mSprungMass;
+ }
+ PX_CHECK_MSG(PxAbs((vehActor->getMass()-totalSprungMass)/vehActor->getMass()) < 0.01f, "Sum of suspension sprung masses doesn't match actor mass");
+#endif
+
+ //Copy the simulation data.
+ mWheelsSimData=wheelsData;
+
+ //Set the actor pointer.
+ mActor=vehActor;
+
+ //Set all the sq result ptrs to null.
+ const PxU32 numSuspWheelTire4=wheelsData.mNbWheels4;
+ for(PxU32 i=0;i<numSuspWheelTire4;i++)
+ {
+ mWheelsDynData.mWheels4DynData[i].mRaycastResults=NULL;
+ mWheelsDynData.mWheels4DynData[i].mSweepResults=NULL;
+ }
+
+ //Set up the suspension limits constraints.
+ for(PxU32 i=0;i<numSuspWheelTire4;i++)
+ {
+ PxVehicleConstraintShader& shader=mWheelsDynData.mWheels4DynData[i].getVehicletConstraintShader();
+ for(PxU32 j=0;j<4;j++)
+ {
+ shader.mData.mSuspLimitData.mCMOffsets[j]=wheelsData.mWheels4SimData[i].getSuspForceAppPointOffset(j);
+ shader.mData.mSuspLimitData.mDirs[j]=wheelsData.mWheels4SimData[i].getSuspTravelDirection(j);
+ shader.mData.mSuspLimitData.mErrors[j]=0.0f;
+ shader.mData.mSuspLimitData.mActiveFlags[j]=false;
+
+ shader.mData.mStickyTireForwardData.mCMOffsets[j]=PxVec3(0,0,0);
+ shader.mData.mStickyTireForwardData.mDirs[j]=PxVec3(0,0,0);
+ shader.mData.mStickyTireForwardData.mTargetSpeeds[j]=0.0f;
+ shader.mData.mStickyTireForwardData.mActiveFlags[j]=false;
+
+ shader.mData.mStickyTireSideData.mCMOffsets[j]=PxVec3(0,0,0);
+ shader.mData.mStickyTireSideData.mDirs[j]=PxVec3(0,0,0);
+ shader.mData.mStickyTireSideData.mTargetSpeeds[j]=0.0f;
+ shader.mData.mStickyTireSideData.mActiveFlags[j]=false;
+ }
+
+
+ shader.mConstraint=physics->createConstraint(vehActor, NULL, shader, t, sizeof(PxVehicleConstraintShader::VehicleConstraintData));
+ shader.mConstraint->markDirty();
+ }
+
+ //Set up the shader data ptrs.
+ for(PxU32 i=0;i<wheelsData.mNbActiveWheels;i++)
+ {
+ mWheelsDynData.setTireForceShaderData(i,&mWheelsSimData.getTireData(i));
+ }
+
+ //Disable the unused wheels.
+ for(PxU32 i=wheelsData.mNbActiveWheels;i<4*mWheelsSimData.mNbWheels4;i++)
+ {
+ mWheelsSimData.disableWheel(i);
+ }
+
+ //Pose the wheels that are mapped to shapes so that all shapes are at the rest pose.
+ for(PxU32 i=0;i<wheelsData.mNbActiveWheels;i++)
+ {
+ const PxI32 shapeId = mWheelsSimData.getWheelShapeMapping(i);
+ if(-1!=shapeId)
+ {
+ PX_CHECK_AND_RETURN(PxU32(shapeId) < mActor->getNbShapes(), "Illegal wheel shape mapping, shape does not exist on actor");
+
+ //Compute the shape local pose
+ const PxTransform chassisCMOffset=mActor->getCMassLocalPose();
+ PxTransform wheelOffset=chassisCMOffset;
+ wheelOffset.p+=mWheelsSimData.getWheelCentreOffset(i);
+ //Pose the shape.
+ PxShape* shapeBuffer[1];
+ mActor->getShapes(shapeBuffer,1,PxU32(shapeId));
+ shapeBuffer[0]->setLocalPose(wheelOffset);
+ }
+ }
+}
+
+void PxVehicleWheels::requires(PxProcessPxBaseCallback& c)
+{
+ c.process(*mActor);
+
+ for(PxU32 i=0;i<mWheelsSimData.mNbWheels4;i++)
+ {
+ c.process(*mWheelsDynData.mWheels4DynData[i].getVehicletConstraintShader().getPxConstraint());
+ }
+}
+
+static PxConstraint* resolveConstraintPtr(PxDeserializationContext& context,
+ PxConstraint* old,
+ PxConstraintConnector* connector,
+ PxConstraintShaderTable &shaders)
+{
+ context.translatePxBase(old);
+ PxConstraint* new_nx = static_cast<PxConstraint*>(old);
+ new_nx->setConstraintFunctions(*connector, shaders);
+ return new_nx;
+}
+
+void PxVehicleWheels::resolveReferences(PxDeserializationContext& context)
+{
+ context.translatePxBase(mActor);
+
+ for(PxU32 i=0;i<mWheelsSimData.mNbWheels4;i++)
+ {
+ PxVehicleConstraintShader& shader=mWheelsDynData.mWheels4DynData[i].getVehicletConstraintShader();
+ shader.setPxConstraint(resolveConstraintPtr(context,shader.getPxConstraint(), shader.getConnector(), t));
+ }
+
+ //Set up the shader data ptrs.
+ for(PxU32 i=0;i<mWheelsSimData.mNbActiveWheels;i++)
+ {
+ mWheelsDynData.setTireForceShaderData(i,&mWheelsSimData.getTireData(i));
+ }
+}
+
+PxReal PxVehicleWheels::computeForwardSpeed() const
+{
+ const PxTransform vehicleChassisTrnsfm=mActor->getGlobalPose().transform(mActor->getCMassLocalPose());
+ return mActor->getLinearVelocity().dot(vehicleChassisTrnsfm.q.rotate(gForward));
+}
+
+PxReal PxVehicleWheels::computeSidewaysSpeed() const
+{
+ const PxTransform vehicleChassisTrnsfm=mActor->getGlobalPose().transform(mActor->getCMassLocalPose());
+ return mActor->getLinearVelocity().dot(vehicleChassisTrnsfm.q.rotate(gRight));
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+void PxVehicleWheelsDynData::setUserData(const PxU32 tireIdx, void* userData)
+{
+ PX_CHECK_AND_RETURN(tireIdx < mNbActiveWheels, "PxVehicleWheelsDynData::setUserData - Illegal wheel");
+ mUserDatas[tireIdx]=userData;
+}
+
+void* PxVehicleWheelsDynData::getUserData(const PxU32 tireIdx) const
+{
+ PX_CHECK_AND_RETURN_VAL(tireIdx < mNbActiveWheels, "PxVehicleWheelsDynData::setUserData - Illegal wheel", NULL);
+ return mUserDatas[tireIdx];
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+void PxVehicleWheelsDynData::copy(const PxVehicleWheelsDynData& src, const PxU32 srcWheel, const PxU32 trgWheel)
+{
+ PX_CHECK_AND_RETURN(srcWheel < src.mNbActiveWheels, "PxVehicleWheelsDynData::copy - Illegal src wheel");
+ PX_CHECK_AND_RETURN(trgWheel < mNbActiveWheels, "PxVehicleWheelsDynData::copy - Illegal trg wheel");
+
+ const PxVehicleWheels4DynData& src4 = src.mWheels4DynData[(srcWheel>>2)];
+ PxVehicleWheels4DynData& trg4 = mWheels4DynData[(trgWheel>>2)];
+
+ trg4.mWheelSpeeds[trgWheel & 3] = src4.mWheelSpeeds[srcWheel & 3];
+ trg4.mCorrectedWheelSpeeds[trgWheel & 3] = src4.mCorrectedWheelSpeeds[srcWheel & 3];
+ trg4.mTireLowForwardSpeedTimers[trgWheel & 3] = src4.mTireLowForwardSpeedTimers[srcWheel & 3];
+ trg4.mTireLowSideSpeedTimers[trgWheel & 3] = src4.mTireLowSideSpeedTimers[srcWheel & 3];
+ trg4.mWheelRotationAngles[trgWheel & 3] = src4.mWheelRotationAngles[srcWheel & 3];
+
+ if(src4.mRaycastResults)
+ {
+ const PxVehicleWheels4DynData::SuspLineRaycast& suspLineRaycastSrc = reinterpret_cast<const PxVehicleWheels4DynData::SuspLineRaycast&>(src4.mQueryOrCachedHitResults);
+ PxVehicleWheels4DynData::SuspLineRaycast& suspLineRaycastTrg = reinterpret_cast<PxVehicleWheels4DynData::SuspLineRaycast&>(trg4.mQueryOrCachedHitResults);
+
+ suspLineRaycastTrg.mStarts[trgWheel & 3] = suspLineRaycastSrc.mStarts[srcWheel & 3];
+ suspLineRaycastTrg.mDirs[trgWheel & 3] = suspLineRaycastSrc.mDirs[srcWheel & 3];
+ suspLineRaycastTrg.mLengths[trgWheel & 3] = suspLineRaycastSrc.mLengths[srcWheel & 3];
+ }
+ else if(src4.mSweepResults)
+ {
+ const PxVehicleWheels4DynData::SuspLineSweep& suspLineSweepSrc = reinterpret_cast<const PxVehicleWheels4DynData::SuspLineSweep&>(src4.mQueryOrCachedHitResults);
+ PxVehicleWheels4DynData::SuspLineSweep& suspLineSweepTrg = reinterpret_cast<PxVehicleWheels4DynData::SuspLineSweep&>(trg4.mQueryOrCachedHitResults);
+
+ suspLineSweepTrg.mStartPose[trgWheel & 3] = suspLineSweepSrc.mStartPose[srcWheel & 3];
+ suspLineSweepTrg.mDirs[trgWheel & 3] = suspLineSweepSrc.mDirs[srcWheel & 3];
+ suspLineSweepTrg.mLengths[trgWheel & 3] = suspLineSweepSrc.mLengths[srcWheel & 3];
+ }
+ else
+ {
+ const PxVehicleWheels4DynData::CachedSuspLineSceneQuerytHitResult& cachedHitResultSrc = reinterpret_cast<const PxVehicleWheels4DynData::CachedSuspLineSceneQuerytHitResult&>(src4.mQueryOrCachedHitResults);
+ PxVehicleWheels4DynData::CachedSuspLineSceneQuerytHitResult& cachedHitResultTrg = reinterpret_cast<PxVehicleWheels4DynData::CachedSuspLineSceneQuerytHitResult&>(trg4.mQueryOrCachedHitResults);
+
+ cachedHitResultTrg.mPlanes[trgWheel & 3] = cachedHitResultSrc.mPlanes[srcWheel & 3];
+ cachedHitResultTrg.mFrictionMultipliers[trgWheel & 3] = cachedHitResultSrc.mFrictionMultipliers[srcWheel & 3];
+ cachedHitResultTrg.mCounts[trgWheel & 3] = cachedHitResultSrc.mCounts[srcWheel & 3];
+ cachedHitResultTrg.mDistances[trgWheel & 3] = cachedHitResultSrc.mDistances[srcWheel & 3];
+ }
+}
+
+
+} //namespace physx
+