text: /*
   * Copyright (c) 2008-2015, NVIDIA CORPORATION.  All rights reserved.
   *
   * NVIDIA CORPORATION and its licensors retain all intellectual property
   * and proprietary rights in and to this software, 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.
   */
  // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
  // Copyright (c) 2001-2004 NovodeX AG. All rights reserved.  
  
  
  #ifndef PX_VEHICLE_WHEELS_H
  #define PX_VEHICLE_WHEELS_H
  /** \addtogroup vehicle
    @{
  */
  
  #include "PxFiltering.h"
  #include "foundation/PxSimpleTypes.h"
  #include "vehicle/PxVehicleShaders.h"
  #include "vehicle/PxVehicleComponents.h"
  #include "common/PxBase.h"
  #include "PxRigidDynamic.h"
  
  #ifndef PX_DOXYGEN
  namespace physx
  {
  #endif
  
  class PxVehicleWheels4SimData;
  class PxVehicleWheels4DynData;
  class PxVehicleTireForceCalculator;
  class PxShape;
  class PxPhysics;
  class PxMaterial;
  
  /**
  \brief Data structure describing configuration data of a vehicle with up to 20 wheels.
  */
  
  class PxVehicleWheelsSimData
  {
  //= ATTENTION! =====================================================================================
  // Changing the data layout of this class breaks the binary serialization format.  See comments for 
  // PX_BINARY_SERIAL_VERSION.  If a modification is required, please adjust the getBinaryMetaData 
  // function.  If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
  // accordingly.
  //==================================================================================================
  public:
  
  	friend class PxVehicleWheels;
  	friend class PxVehicleNoDrive;
  	friend class PxVehicleDrive4W;
  	friend class PxVehicleDriveTank;
  	friend class PxVehicleUpdate;
  
  	/**
  	\brief Allocate a PxVehicleWheelsSimData instance for with nbWheels.
  	@see free
  	*/
  	static PxVehicleWheelsSimData* allocate(const PxU32 nbWheels);
  
  	/**
  	\brief Setup with mass information that can be applied to the default values of the suspensions, wheels, and tires
  	set in their respective constructors.
  
  	\param chassisMass is the mass of the chassis.
  
  	\note This function assumes that the suspensions equally share the load of the chassis mass.  It also
  	assumes that the suspension will have a particular natural frequency and damping ratio that is typical
  	of a standard car.  If either of these assumptions is broken then each suspension will need to 
  	be individually configured with custom strength, damping rate, and sprung mass.
  
  	@see allocate
  	*/
  	void setChassisMass(const PxF32 chassisMass);
  
  	/**
  	\brief Free a PxVehicleWheelsSimData instance 
  	@see allocate
  	*/
  	void free();
  
  	/**
  	\brief Copy wheel simulation data.
  	\note The number of wheels on both instances of PxVehicleWheelsSimData must match.
  	*/
  	PxVehicleWheelsSimData& operator=(const PxVehicleWheelsSimData& src);
  
  	/**
  	\brief Copy the data of a single wheel unit (wheel, suspension, tire) from srcWheel of src to trgWheel.
  	\param[in] src is the data to be copied.
  	\param[in] srcWheel is the wheel whose data will be copied from src.
  	\param[in] trgWheel is the wheel that will be assigned the copied data.
  	*/
  	void copy(const PxVehicleWheelsSimData& src, const PxU32 srcWheel, const PxU32 trgWheel);
  
  	/**
  	\brief Return the number of wheels 
  	@see allocate
  	*/
  	PxU32 getNbWheels() const {return mNbActiveWheels;}
  
  	/**
  	\brief Return the suspension data of the idth wheel
  	*/
  	const PxVehicleSuspensionData& getSuspensionData(const PxU32 id) const;
  		
  	/**
  	\brief Return the wheel data of the idth wheel
  	*/
  	const PxVehicleWheelData& getWheelData(const PxU32 id) const;
  
  	/**
  	\brief Return the tire data of the idth wheel
  	*/
  	const PxVehicleTireData& getTireData(const PxU32 id) const;
  	
  	/**
  	\brief Return the direction of travel of the suspension of the idth wheel
  	*/
  	const PxVec3& getSuspTravelDirection(const PxU32 id) const;
  
  	/**
  	\brief Return the application point of the suspension force of the suspension of the idth wheel as an offset from the rigid body center of mass.
  	\note Specified relative to the center of mass of the rigid body
  	*/
  	const PxVec3& getSuspForceAppPointOffset(const PxU32 id) const;
  
  	/**
  	\brief Return the application point of the tire force of the tire of the idth wheel as an offset from the rigid body center of mass.
  	\note Specified relative to the centre of mass of the rigid body
  	*/
  	const PxVec3& getTireForceAppPointOffset(const PxU32 id) const;
  		
  	/**
  	\brief Return the offset from the rigid body centre of mass to the centre of the idth wheel.
  	*/
  	const PxVec3& getWheelCentreOffset(const PxU32 id) const;	
  
  	/**
  	\brief Return the wheel mapping for the ith wheel.  
  	
  	\note The return value is the element in the array of 
  	shapes of the vehicle's PxRigidDynamic that corresponds to the ith wheel.  A return value of -1 means
  	that the wheel is not mapped to a PxShape.
  
  	@see PxRigidActor.getShapes
  	*/
  	PxI32 getWheelShapeMapping(const PxU32 wheelId) const;
  
  	/**
  	\brief Return the scene query filter data used by the specified suspension line
  	*/
  	const PxFilterData& getSceneQueryFilterData(const PxU32 suspId) const;
  	
  	/**
  	\brief Return the data that describes the filtering of the tire load to produce smoother handling at large time-steps.
  	*/
  	PX_FORCE_INLINE const PxVehicleTireLoadFilterData& getTireLoadFilterData() const 
  	{
  		return mNormalisedLoadFilter;
  	}
  
  	/**
  	\brief Set the suspension data of the idth wheel
  	\param[in] id is the wheel index.
  	\param[in] susp is the suspension data to be applied.
  	*/
  	void setSuspensionData(const PxU32 id, const PxVehicleSuspensionData& susp);
  
  	/**
  	\brief Set the wheel data of the idth wheel
  	\param[in] id is the wheel index.
  	\param[in] wheel is the wheel data to be applied.
  	*/
  	void setWheelData(const PxU32 id, const PxVehicleWheelData& wheel);
  
  	/**
  	\brief Set the tire data of the idth wheel
  	\param[in] id is the wheel index.
  	\param[in] tire is the tire data to be applied.
  	*/
  	void setTireData(const PxU32 id, const PxVehicleTireData& tire);
  
  	/**
  	\brief Set the direction of travel of the suspension of the idth wheel
  	\param[in] id is the wheel index
  	\param[in] dir is the suspension travel direction to be applied.
  	*/
  	void setSuspTravelDirection(const PxU32 id, const PxVec3& dir);
  	
  	/**
  	\brief Set the application point of the suspension force of the suspension of the idth wheel.
  	\param[in] id is the wheel index
  	\param[in] offset is the offset from the rigid body center of mass to the application point of the suspension force.
  	\note Specified relative to the centre of mass of the rigid body
  	*/
  	void setSuspForceAppPointOffset(const PxU32 id, const PxVec3& offset);									
  	
  	/**
  	\brief Set the application point of the tire force of the tire of the idth wheel.
  	\param[in] id is the wheel index
  	\param[in] offset is the offset from the rigid body center of mass to the application point of the tire force.
  	\note Specified relative to the centre of mass of the rigid body
  	*/
  	void setTireForceAppPointOffset(const PxU32 id, const PxVec3& offset);
  
  	/**
  	\brief Set the offset from the rigid body centre of mass to the centre of the idth wheel.
  	\param[in] id is the wheel index
  	\param[in] offset is the offset from the rigid body center of mass to the center of the wheel at rest.
  	\note Specified relative to the centre of mass of the rigid body
  	*/
  	void setWheelCentreOffset(const PxU32 id, const PxVec3& offset);	
  
  	/**
  	\brief Set mapping between wheel id and position of corresponding wheel shape in the list of actor shapes.
  	
  	\note This mapping is used to pose the correct wheel shapes with the latest wheel rotation angle, steer angle, and suspension travel
  	while allowing arbitrary ordering of the wheel shapes in the actor's list of shapes.
  	
  	\note Use setWheelShapeMapping(i,-1) to register that there is no wheel shape corresponding to the ith wheel
  	
  	\note Set setWheelShapeMapping(i,k) to register that the ith wheel corresponds to the kth shape in the actor's list of shapes.
  	
  	\note The default values correspond to setWheelShapeMapping(i,i) for all wheels.
  	
  	\note Calling this function will also pose the relevant PxShape at the rest position of the wheel.
  
  	\param wheelId is the wheel index
  
  	\param shapeId is the shape index.
  	
  	@see PxVehicleUpdates, PxVehicleDrive4W::setup, PxVehicleDriveTank::setup, PxVehicleNoDrive::setup, setSceneQueryFilterData, PxRigidActor::getShapes
  	*/
  	void setWheelShapeMapping(const PxU32 wheelId, const PxI32 shapeId);
  
  	/**
  	\brief Set the scene query filter data that will be used for raycasts along the travel
  	direction of the specified suspension. The default value is PxFilterData(0,0,0,0)
  	\param suspId is the wheel index
  	\param sqFilterData is the raycast filter data for the suspension raycast.
  	@see setWheelShapeMapping
  	*/
  	void setSceneQueryFilterData(const PxU32 suspId, const PxFilterData& sqFilterData);
  
  	/**
  	\brief Set the data that describes the filtering of the tire load to produce smoother handling at large timesteps.
  	\param tireLoadFilter is the smoothing function data.
  	*/
  	void setTireLoadFilterData(const PxVehicleTireLoadFilterData& tireLoadFilter);
  
  	/**
  	\brief Disable a wheel so that zero suspension forces and zero tire forces are applied to the rigid body from this wheel.
  
  	\note If the vehicle has a differential (PxVehicleNW/PxVehicle4W) then the differential (PxVehicleDifferentialNWData/PxVehicleDifferential4WData)
  	needs to be configured so that no drive torque is delivered to the disabled wheel.
  	
  	\note If the vehicle is of type PxVehicleNoDrive then zero drive torque must be applied to the disabled wheel.
  	
  	\note For tanks (PxVehicleDriveTank) any drive torque that could be delivered to the wheel through the tank differential will be 
  	re-directed to the remaining enabled wheels.
  
  	@see enableWheel
  	@see PxVehicleDifferentialNWData::setDrivenWheel
  	@see PxVehicleDifferential4WData::mFrontLeftRightSplit, PxVehicleDifferential4WData::mRearLeftRightSplit, PxVehicleDifferential4WData::mType
  	@see PxVehicleNoDrive::setDriveTorque
  	@see PxVehicle4WEnable3WTadpoleMode, PxVehicle4WEnable3WDeltaMode
  
  	\note If a PxShape is associated with the disabled wheel then the association must be broken by calling setWheelShapeMapping(wheelId, -1). 
  	@see setWheelShapeMapping
  
  	\note A wheel that is disabled must also simultaneously be given zero wheel rotation speed.
  	@see PxVehicleWheelsDynData::setWheelRotationSpeed
  
  	\note Care must be taken with the sprung mass supported by the remaining enabled wheels.  Depending on the desired effect, the mass of the rigid body 
  	might need to be distributed among the remaining enabled wheels and suspensions.
  
  	\param[in] wheel is the wheel index.
  	*/
  	void disableWheel(const PxU32 wheel);
  
  	/**
  	\brief Enable a wheel so that suspension forces and tire forces are applied to the rigid body.
  	All wheels are enabled by default and remain enabled until they are disabled.
  	\param[in] wheel is the wheel index.
  	@see disableWheel
  	*/
  	void enableWheel(const PxU32 wheel);
  
  	/**
  	\brief Test if a wheel has been disabled.
  	\param[in] wheel is the wheel index.
  	*/
  	bool getIsWheelDisabled(const PxU32 wheel) const;
  
  	/**
  	\brief Set the number of vehicle sub-steps that will be performed when the vehicle's longitudinal 
  	speed is below and above a threshold longitudinal speed.
  	
  	\note More sub-steps provides better stability but with greater computational cost.
  	
  	\note Typically, vehicles require more sub-steps at very low forward speeds.
  	
  	\note The threshold longitudinal speed has a default value of 5 metres per second.  If metres are not the chosen scale
  	then setSubStepCount will need to be called with an equivalent or modified value in the adopted scale.
  	
  	\note The sub-step count below the threshold longitudinal speed has a default of 3.
  	
  	\note The sub-step count above the threshold longitudinal speed has a default of 1.
  	
  	\note Each sub-step has time advancement equal to the time-step passed to PxVhicleUpdates divided by the number of required sub-steps.
  	
  	\note The contact planes of the most recent suspension line raycast are reused across all sub-steps.
  	
  	\note Each sub-step computes tire and suspension forces and then advances a velocity, angular velocity and transform.
  	
  	\note At the end of all sub-steps the vehicle actor is given the velocity and angular velocity that would move the actor from its start transform prior
  	to the first sub-step to the transform computed at the end of the last substep, assuming it doesn't collide with anything along the way in the next PhysX SDK update.
  	
  	\note The global pose of the actor is left unchanged throughout the sub-steps.
  
  	\param[in] thresholdLongitudinalSpeed is a threshold speed that is used to categorize vehicle speed as low speed or high speed.
  	\param[in] lowForwardSpeedSubStepCount is the number of sub-steps performed in PxVehicleUpates for vehicles that have longitudinal speed lower than thresholdLongitudinalSpeed.
  	\param[in] highForwardSpeedSubStepCount is the number of sub-steps performed in PxVehicleUpdates for vehicles that have longitudinal speed graeter than thresholdLongitudinalSpeed.
  	*/
  	void setSubStepCount(const PxReal thresholdLongitudinalSpeed, const PxU32 lowForwardSpeedSubStepCount, const PxU32 highForwardSpeedSubStepCount);
  
  	/**
  	\brief Set the minimum denominator used in the longitudinal slip calculation.
  
  	\note The longitudinal slip has a theoretical value of (w*r - vz)/|vz|, where w is the angular speed of the wheel; r is the radius of the wheel; 
  	and vz is the component of rigid body velocity (computed at the wheel base) that lies along the longitudinal wheel direction. The term |vz|
  	normalizes the slip, while preserving the sign of the longitudinal tire slip.   The difficulty here is that when |vz| approaches zero the 
  	longitudinal slip approaches infinity. A solution to this problem is to replace the denominator (|vz|) with a value that never falls below a chosen threshold. 
  	The longitudinal slip is then calculated with (w*r - vz)/PxMax(|vz|, minLongSlipDenominator).
  
  	\note The default value is 4 metres per second.  If metres are not the chosen scale	then setSubStepCount will need to be called with an equivalent or 
  	modified value in the adopted scale.
  
  	\note Adjust this value upwards if a vehicle has difficulty coming to rest.
  
  	\note Decreasing the timestep (or increasing the number of sub-steps at low longitudinal speed with setSubStepCount) should allow stable stable 
  	behavior with smaller values of minLongSlipDenominator.
  	*/
  	void setMinLongSlipDenominator(const PxReal minLongSlipDenominator);
  
  private:
  
  	/**
  	\brief Graph to filter normalised load
  	@see setTireLoadFilterData, getTireLoadFilterData
  	*/
  	PxVehicleTireLoadFilterData mNormalisedLoadFilter;
  
  	/**
  	\brief Wheels data organised in blocks of 4 wheels.
  	*/
  	PxVehicleWheels4SimData* mWheels4SimData;
  
  	/**
  	\brief Number of blocks of 4 wheels.
  	*/
  	PxU32 mNbWheels4;
  
  	/**
  	\brief Number of actual wheels (<=(mNbWheels4*4))
  	*/
  	PxU32 mNbActiveWheels;
  
  	/**
  	\brief Which of the mNbActiveWheels are active or disabled?
  	The default is that all mNbActiveWheels wheels are active.
  	*/
  	PxU32 mActiveWheelsBitmapBuffer[((PX_MAX_NB_WHEELS + 31) & ~31) >> 5];
  
  	/**
  	\brief Threshold longitudinal speed used to decide whether to use 
  	mLowForwardSpeedSubStepCount or mHighForwardSpeedSubStepCount as the 
  	number of sub-steps that will be peformed.
  	*/
  	PxF32 mThresholdLongitudinalSpeed;
  
  	/**
  	\brief Number of sub-steps that will be performed if the longitudinal speed
  	of the vehicle is smaller than mThresholdLongitudinalSpeed.
  	*/
  	PxU32 mLowForwardSpeedSubStepCount;
  
  	/**
  	\brief Number of sub-steps that will be performed if the longitudinal speed
  	of the vehicle is greater than or equal to mThresholdLongitudinalSpeed.
  	*/
  	PxU32 mHighForwardSpeedSubStepCount;
  
  	/**
  	\brief Minimum long slip denominator
  	*/
  	PxF32 mMinLongSlipDenominator;
  
  #if defined(PX_P64)
  	PxU32 mPad[3];
  #endif
  
  
  	/**
  	\brief Test if wheel simulation data has been setup with legal values.
  	*/
  	bool isValid() const;
  
  
  //serialization
  public:
  	PxVehicleWheelsSimData(const PxEMPTY&) : mNormalisedLoadFilter(PxEmpty) {}
  	static void getBinaryMetaData(PxOutputStream& stream);
  	PxU32 getNbWheels4() const { return mNbWheels4; }	
  	PxU32 getNbSuspensionData() const { return mNbActiveWheels; }
  	PxU32 getNbWheelData() const {	return mNbActiveWheels; }	
  	PxU32 getNbSuspTravelDirection() const	{ return mNbActiveWheels; }
  	PxU32 getNbTireData() const	{ return mNbActiveWheels;	}	
  	PxU32 getNbSuspForceAppPointOffset() const	{ return mNbActiveWheels;	}
  	PxU32 getNbTireForceAppPointOffset() const	{ return mNbActiveWheels;	}
  	PxU32 getNbWheelCentreOffset() const { return mNbActiveWheels;	}
  	PxU32 getNbWheelShapeMapping() const { return mNbActiveWheels; }
  	PxU32 getNbSceneQueryFilterData() const { return mNbActiveWheels; }
  	PxF32 getMinLongSlipDenominator() const {return mMinLongSlipDenominator;}
  	void setThresholdLongSpeed(const PxF32 f) {mThresholdLongitudinalSpeed = f;}
  	PxF32 getThresholdLongSpeed() const {return mThresholdLongitudinalSpeed;}
  	void setLowForwardSpeedSubStepCount(const PxU32 f) {mLowForwardSpeedSubStepCount = f;}
  	PxU32 getLowForwardSpeedSubStepCount() const {return mLowForwardSpeedSubStepCount;}
  	void setHighForwardSpeedSubStepCount(const PxU32 f) {mHighForwardSpeedSubStepCount = f;}
  	PxU32 getHighForwardSpeedSubStepCount() const {return mHighForwardSpeedSubStepCount;}
  	void setWheelEnabledState(const PxU32 wheel, const bool state) {if(state) {enableWheel(wheel);} else {disableWheel(wheel);}}
  	bool getWheelEnabledState(const PxU32 wheel) const {return !getIsWheelDisabled(wheel);}
  	PxU32 getNbWheelEnabledState() const {return mNbActiveWheels;}
  	PxVehicleWheelsSimData(){}
  	~PxVehicleWheelsSimData(){}
  //~serialization
  };
  PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheelsSimData) & 15));
  
  /**
  \brief Data structure with instanced dynamics data for wheels
  */
  class PxVehicleWheelsDynData
  {
  //= ATTENTION! =====================================================================================
  // Changing the data layout of this class breaks the binary serialization format.  See comments for 
  // PX_BINARY_SERIAL_VERSION.  If a modification is required, please adjust the getBinaryMetaData 
  // function.  If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
  // accordingly.
  //==================================================================================================
  public:
  
  	friend class PxVehicleWheels;
  	friend class PxVehicleDrive4W;
  	friend class PxVehicleDriveTank;
  	friend class PxVehicleUpdate;
  
  	PxVehicleWheelsDynData(){}
  	~PxVehicleWheelsDynData(){}
  
  	/**
  	\brief Set all wheels to their rest state.
  	@see setup
  	*/
  	void setToRestState();
  
  	/**
  	\brief Set the tire force shader function
  	\param[in] tireForceShaderFn is the shader function that will be used to compute tire forces.
  	*/
  	void setTireForceShaderFunction(PxVehicleComputeTireForce tireForceShaderFn);
  
  	/**
  	\brief Set the tire force shader data for a specific tire
  	\param[in] tireId is the wheel index
  	\param[in] tireForceShaderData is the data describing the tire.
  	*/
  	void setTireForceShaderData(const PxU32 tireId, const void* tireForceShaderData);
  
  	/**
  	\brief Get the tire force shader data for a specific tire
  	*/
  	const void* getTireForceShaderData(const PxU32 tireId) const;
  
  	/**
  	\brief Set the wheel rotation speed (radians per second) about the rolling axis for the specified wheel.
  	\param[in] wheelIdx is the wheel index
  	\param[in] speed is the rotation speed to be applied to the wheel.
  	*/
  	void setWheelRotationSpeed(const PxU32 wheelIdx, const PxReal speed);
  
  	/**
  	\brief Return the rotation speed about the rolling axis of a specified wheel .
  	*/
  	PxReal getWheelRotationSpeed(const PxU32 wheelIdx) const;
  	
  	/**
  	\brief Set the wheel rotation angle (radians) about the rolling axis of the specified wheel.
  	\param[in] wheelIdx is the wheel index
  	\param[in] angle is the rotation angle to be applied to the wheel.
  	*/
  	void setWheelRotationAngle(const PxU32 wheelIdx, const PxReal angle);
  
  	/**
  	\brief Return the rotation angle about the rolling axis for the the specified wheel.
  	*/
  	PxReal getWheelRotationAngle(const PxU32 wheelIdx) const;
  
  	/**
  	\brief Set the user data pointer for the specified wheel
  	It has a default value of NULL.
  	\param[in] tireIdx is the wheel index
  	\param[in] userData is the data to be associated with the wheel.
  	*/
  	void setUserData(const PxU32 tireIdx, void* userData);
  
  	/**
  	\brief Get the user data pointer that was set for the specified wheel
  	*/
  	void* getUserData(const PxU32 tireIdx) const;
  
  	/**
  	\brief Copy the dynamics data of a single wheel unit (wheel, suspension, tire) from srcWheel of src to trgWheel.
  	\param[in] src is the data to be copied.
  	\param[in] srcWheel is the wheel whose data will be copied from src.
  	\param[in] trgWheel is the wheel that will be assigned the copied data.
  	*/
  	void copy(const PxVehicleWheelsDynData& src, const PxU32 srcWheel, const PxU32 trgWheel);
  
  private:
  
      /**
  	\brief Dynamics data arranged in blocks of 4 wheels.
  	*/
  	PxVehicleWheels4DynData* mWheels4DynData;
  
  	/**
  	\brief Test if wheel dynamics data have legal values.
  	*/
  	bool isValid() const;
  
  	/**
  	\brief Shader data and function for tire force calculations.
  	*/
  	PxVehicleTireForceCalculator* mTireForceCalculators;
  	
  	/**
  	\brief A userData pointer can be stored for each wheel.
  	@see setUserData, getUserData
  	*/
  	void** mUserDatas;
  
  	/**
  	\brief Number of blocks of 4 wheels.
  	*/
  	PxU32 mNbWheels4;
  
  	/**
  	\brief Number of wheels (mNbActiveWheels <= (mNbWheels4*4))
  	*/
  	PxU32 mNbActiveWheels;
  
  	PxU32 mPad[3];
  
  
  //serialization
  public:
  	static void getBinaryMetaData(PxOutputStream& stream);	
  	PxU32 getNbWheelRotationSpeed() const {	return mNbActiveWheels; }
  	PxU32 getNbWheelRotationAngle() const {	return mNbActiveWheels; }	
  	PxVehicleWheels4DynData* getWheel4DynData() const { return mWheels4DynData; }
  //~serialization
  };
  PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheelsDynData) & 15));
  
  /**
  \brief Data structure with instanced dynamics data and configuration data of a vehicle with just wheels
  @see PxVehicleDrive, PxVehicleDrive4W, PxVehicleDriveTank
  */
  class PxVehicleWheels : public PxBase
  {
  //= ATTENTION! =====================================================================================
  // Changing the data layout of this class breaks the binary serialization format.  See comments for 
  // PX_BINARY_SERIAL_VERSION.  If a modification is required, please adjust the getBinaryMetaData 
  // function.  If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
  // accordingly.
  //==================================================================================================
  public:
  
  	friend class PxVehicleUpdate;
  	friend class PxVehicleConstraintShader;
  
  	/**
  	\brief Return the type of vehicle 
  	@see PxVehicleTypes
  	*/
  	PX_FORCE_INLINE PxU32 getVehicleType() const {return mType;}
  
  	/**
  	\brief Get non-const ptr to PxRigidDynamic instance that is the vehicle's physx representation
  	*/
  	PX_FORCE_INLINE PxRigidDynamic* getRigidDynamicActor() {return mActor;}
  
  	/**
  	\brief Get const ptr to PxRigidDynamic instance that is the vehicle's physx representation
  	*/
  	PX_FORCE_INLINE const PxRigidDynamic* getRigidDynamicActor() const {return mActor;}
  	
  	/**
  	\brief Compute the rigid body velocity component along the forward vector of the rigid body transform.
  	@see PxVehicleSetBasisVectors
  	*/
  	PxReal computeForwardSpeed() const;
  
  	/**
  	\brief Compute the rigid body velocity component along the right vector of the rigid body transform.
  	@see PxVehicleSetBasisVectors
  	*/
  	PxReal computeSidewaysSpeed() const;
  
  	/**
  	\brief Data describing the setup of all the wheels/suspensions/tires.
  	*/
  	PxVehicleWheelsSimData mWheelsSimData;
  
  	/**
  	\brief Data describing the dynamic state of all wheels/suspension/tires.
  	*/
  	PxVehicleWheelsDynData mWheelsDynData;	
  
  protected:
  
  	/**
  	\brief Set all wheels to their rest state
  	*/
  	void setToRestState();
  
  	/**
  	\brief Test that all configuration and instanced dynamics data is valid.
  	*/
  	bool isValid() const;
  
  	/**
  	@see PxVehicleDrive4W::allocate, PxVehicleDriveTank::allocate
  	*/
  	static PxU32 computeByteSize(const PxU32 nbWheels4);
  
  	/**
  	@see PxVehicleDrive4W::allocate, PxVehicleDriveTank::allocate
  	*/
  	static PxU8* patchupPointers(PxVehicleWheels* veh, PxU8* ptr, const PxU32 nbWheels4, const PxU32 nbWheels, bool renew = true);
  
  	/**
  	\brief Deallocate a PxVehicleWheels instance.
  	@see PxVehicleDrive4W::free, PxVehicleDriveTank::free
  	*/
  	void free();
  
  	/**
  	@see PxVehicleDrive4W::setup, PxVehicleDriveTank::setup
  	*/
  	void setup
  		(PxPhysics* physics, PxRigidDynamic* vehActor, 
  		 const PxVehicleWheelsSimData& wheelsData,
  		 const PxU32 nbDrivenWheels, const PxU32 nbNonDrivenWheels);
  	
  	/**
  	\brief The rigid body actor that represents the vehicle in the PhysX SDK.
  	*/
  	PxRigidDynamic* mActor;
  
  private:
  
  	/**
  	\brief Count the number of constraint connectors that have hit their callback when deleting a vehicle.
  	Can only delete the vehicle's memory when all constraint connectors have hit their callback.
  	*/
  	PxU32 mNbNonDrivenWheels;
  	
  	PxU8 mOnConstraintReleaseCounter;
  
  protected:
  
  	/**
  	\brief Vehicle type (eVehicleDriveTypes)
  	*/
  	PxU8 mType;
  		
  #if defined(PX_P64)
  	PxU8 mPad[14];
  #else
  	PxU8 mPad[14];
  #endif
  
  //serialization
  public:
  	virtual		void			requires(PxProcessPxBaseCallback& c);
  	virtual		const char*		getConcreteTypeName() const				{	return "PxVehicleWheels"; }
  	virtual		bool			isKindOf(const char* name)	const		{	return !strcmp("PxVehicleWheels", name) || PxBase::isKindOf(name); }
  	virtual		void			exportExtraData(PxSerializationContext&);	
  				void			importExtraData(PxDeserializationContext&);
  				void			resolveReferences(PxDeserializationContext&);
  	static		void			getBinaryMetaData(PxOutputStream& stream);
  	PX_FORCE_INLINE PxU32 getNbNonDrivenWheels() const { return mNbNonDrivenWheels; }
  	PxVehicleWheels(PxType concreteType, PxBaseFlags baseFlags) : PxBase(concreteType, baseFlags) {}
  	PxVehicleWheels(PxBaseFlags baseFlags) : PxBase(baseFlags), mWheelsSimData(PxEmpty) {}
  	virtual ~PxVehicleWheels() {}
  	virtual void release() { free(); }
  //~serialization
  };
  PX_COMPILE_TIME_ASSERT(0==(sizeof(PxVehicleWheels) & 15));
  
  #ifndef PX_DOXYGEN
  } // namespace physx
  #endif
  
  /** @} */
  #endif //PX_VEHICLE_WHEELS_H
  