882 lines
32 KiB
C++
882 lines
32 KiB
C++
//
|
|
// 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-2019 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 "vehicle/PxVehicleWheels.h"
|
|
#include "PxRigidDynamic.h"
|
|
#include "PxShape.h"
|
|
#include "PxPhysics.h"
|
|
|
|
#include "PxVehicleSuspWheelTire4.h"
|
|
#include "PxVehicleSuspLimitConstraintShader.h"
|
|
#include "PxVehicleDefaults.h"
|
|
#include "CmPhysXCommon.h"
|
|
#include "CmBitMap.h"
|
|
#include "PsUtilities.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;
|
|
|
|
mFlags = 0;
|
|
}
|
|
|
|
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;
|
|
|
|
mFlags = src.mFlags;
|
|
|
|
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;
|
|
}
|
|
|
|
void PxVehicleWheelsSimData::setFlags(PxVehicleWheelsSimFlags flags)
|
|
{
|
|
mFlags = flags;
|
|
}
|
|
|
|
PxVehicleWheelsSimFlags PxVehicleWheelsSimData::getFlags() const
|
|
{
|
|
return PxVehicleWheelsSimFlags(mFlags);
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
void PxVehicleWheels::onConstraintRelease()
|
|
{
|
|
mOnConstraintReleaseCounter--;
|
|
if (0 == mOnConstraintReleaseCounter)
|
|
{
|
|
PX_FREE(this);
|
|
}
|
|
}
|
|
|
|
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::requiresObjects(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
|
|
|