Raycast Vehicle bounces while driving for unknown reasons

Post Reply
kcjsend2
Posts: 15
Joined: Wed Jun 30, 2021 9:10 am

Raycast Vehicle bounces while driving for unknown reasons

Post by kcjsend2 »

Hi.

As I wrote in Subject, Vehicle was running on a track made using btBvhTriangleMeshShape when it randomly bounces off like something got caught in a wheel.

I have already confirmed that there is no element in the mesh that can be caught in the wheel.

here's video link.
https://youtu.be/lYUlhcdB0iw

and here's how I create vehicle and control it.

Code: Select all


void PhysicsPlayer::BuildRigidBody(const std::shared_ptr<BulletWrapper>& physics)
{
	auto dynamicsWorld = physics->GetDynamicsWorld();

	mOOBB.Extents = { 10.0f, 4.0f, 14.0f };

	XMFLOAT3 vehicleExtents = mOOBB.Extents;
	XMFLOAT3 wheelExtents = mWheel[0]->GetBoundingBox().Extents;

	btTransform btCarTransform;
	btCarTransform.setIdentity();
	btCarTransform.setOrigin(btVector3(mPosition.x, mPosition.y, mPosition.z));

	LoadConvexHullShape(L"Models\\Car_Body_Convex_Hull.obj", physics);

	mBtRigidBody = physics->CreateRigidBody(1000.0f, btCarTransform, mBtCollisionShape);
	mVehicleRayCaster = std::make_shared<btDefaultVehicleRaycaster>(dynamicsWorld);
	mVehicle = std::make_shared<btRaycastVehicle>(mTuning, mBtRigidBody, mVehicleRayCaster.get());
	mBtRigidBody = mVehicle->getRigidBody();

	mBtRigidBody->setActivationState(DISABLE_DEACTIVATION);
	//mBtRigidBody->setGravity(btVector3(0, -20, 0));
	dynamicsWorld->addVehicle(mVehicle.get());

	mVehicle->setCoordinateSystem(0, 1, 2);

	btVector3 wheelDirectionCS0(0, -1, 0);
	btVector3 wheelAxleCS(-1, 0, 0);

	float wheelWidth = wheelExtents.x;
	float wheelRadius = wheelExtents.z;
	float wheelFriction = mWheelFriction;
	float suspensionStiffness = 20.f;
	float suspensionDamping = 2.3f;
	float suspensionCompression = 4.4f;
	float rollInfluence = 0.01f;  //1.0f;

	// 앞바퀴
	bool isFrontWheel = true;
	float connectionHeight = -0.9f;

	btVector3 connectionPointCS0(vehicleExtents.x - 2.5f, connectionHeight, vehicleExtents.z - 2.8f);
	mVehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, 0.6f, wheelRadius, mTuning, isFrontWheel);

	connectionPointCS0 = btVector3(-vehicleExtents.x + 2.5f, connectionHeight, vehicleExtents.z - 2.8f);
	mVehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, 0.6f, wheelRadius, mTuning, isFrontWheel);

	isFrontWheel = false;

	connectionPointCS0 = btVector3(vehicleExtents.x - 2.3f, connectionHeight, -vehicleExtents.z + 2.6f);
	mVehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, 0.6f, wheelRadius, mTuning, isFrontWheel);

	connectionPointCS0 = btVector3(-vehicleExtents.x + 2.3f, connectionHeight, -vehicleExtents.z + 2.6f);
	mVehicle->addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, 0.6f, wheelRadius, mTuning, isFrontWheel);

	for (int i = 0; i < mVehicle->getNumWheels(); i++)
	{
		btWheelInfo& wheel = mVehicle->getWheelInfo(i);
		wheel.m_suspensionStiffness = suspensionStiffness;
		wheel.m_wheelsDampingRelaxation = suspensionDamping;
		wheel.m_wheelsDampingCompression = suspensionCompression;
		wheel.m_frictionSlip = wheelFriction;
		wheel.m_rollInfluence = rollInfluence;
	}
}

class PhysicsPlayer : public Player
{
//Other functions and variables were excluded because they were not related to the bullet.
private:
	const float mWheelFriction = 10.0f;
	const float mWheelDriftFriction = 5.0f;

	std::shared_ptr<WheelObject> mWheel[4];
	btRaycastVehicle::btVehicleTuning mTuning;
	std::shared_ptr<btVehicleRaycaster> mVehicleRayCaster;
	std::shared_ptr<btRaycastVehicle> mVehicle;

	float mBoosterLeft = 0.0f;
	float mBoosterTime = 5.0f;

	float mEngineForce = 0.f;

	float mMaxEngineForce = 8000.f;
	float mMaxBackwardEngineForce = 10000.f;
	float mBoosterEngineForce = 300000.f;

	float mVehicleSteering = 0.f;
	float mSteeringIncrement = 5.0f;
	float mSteeringClamp = 0.6f;

	float mCurrentSpeed = 0.0f;
	float mMaxSpeed = 1000.0f;

	float mBreakingForce = 0.0f;

	float mFovCoefficient = 1.0f;

	int mItemNum = 0;
	float mDriftGauge = 0.0f;
};


void PhysicsPlayer::OnPreciseKeyInput(float Elapsed)
{
	if (mVehicle)
		mCurrentSpeed = mVehicle->getCurrentSpeedKmHour();

	mEngineForce = 0.0f;
	mBreakingForce = 10.0f;

	if (mBoosterLeft > 0.0f)
	{
		mMaxSpeed = 1500.0f;
		mBoosterLeft -= Elapsed;

		mRimLightOn = true;
	}

	if (mBoosterLeft < 0.0f)
	{
		mMaxSpeed = 1000.0f;
		mBoosterLeft = 0.0f;

		mRimLightOn = false;
	}

	if (mVehicleSteering > 0)
	{
		mVehicleSteering -= mSteeringIncrement * Elapsed;
		if (mVehicleSteering < 0)
		{
			mVehicleSteering = 0;
		}
	}

	else if (mVehicleSteering < 0)
	{
		mVehicleSteering += mSteeringIncrement * Elapsed;
		if (mVehicleSteering > 0)
		{
			mVehicleSteering = 0;
		}
	}

	if (GetAsyncKeyState(VK_LEFT) & 0x8000)
	{
		mVehicleSteering -= mSteeringIncrement * Elapsed;
		if (mVehicleSteering < -mSteeringClamp)
			mVehicleSteering = -mSteeringClamp;
	}
	if (GetAsyncKeyState(VK_RIGHT) & 0x8000)
	{
		mVehicleSteering += mSteeringIncrement * Elapsed;
		if (mVehicleSteering > mSteeringClamp)
			mVehicleSteering = mSteeringClamp;
	}
	if (GetAsyncKeyState(VK_UP) & 0x8000)
	{
		if (mCurrentSpeed < 0.0f)
			mBreakingForce = 150.0f;
		else if (mMaxSpeed > mCurrentSpeed)
			mEngineForce = mMaxEngineForce;
		else
		{
			mBreakingForce = 100.0f;
			mEngineForce = 0.0f;
		}
	}
	if (GetAsyncKeyState(VK_DOWN) & 0x8000)
	{
		if (mCurrentSpeed > 0.0f)
			mBreakingForce = 150.0f;
		else if (-mMaxSpeed < mCurrentSpeed)
			mEngineForce = -mMaxBackwardEngineForce;
		else
		{
			mBreakingForce = 100.0f;
			mEngineForce = 0.0f;
		}
	}
	if (GetAsyncKeyState('Z') & 0x8000/*&&mItemNum>0*/)
	{
		#ifdef STANDALONE
		if (mBoosterLeft == 0.0f)
			mBoosterLeft = mBoosterTime;
		#endif

		//mItemNum-=1;
	}
	// if (GetAsyncKeyState('X') & 0x8000/*&&mItemNum>0*/)
	//{
	//
	//}
	if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
	{		
		for (int i = 2; i < 4; ++i)
		{
			if (mVehicle) mVehicle->getWheelInfo(i).m_frictionSlip = mWheelDriftFriction;
		}

		float Epsilon = 50.0f / 180.0f;

		auto camLook = mCamera->GetLook();
		camLook.y = 0.0f;
		camLook = Vector3::Normalize(camLook);

		auto playerLook = mLook;
		playerLook.y = 0.0f;
		playerLook = Vector3::Normalize(playerLook);

		float angle = acos(Vector3::Dot(camLook, playerLook) / (Vector3::Length(camLook) * Vector3::Length(playerLook)));

		if (Epsilon < angle && mDriftGauge < 1.0f)
		{
			mDriftGauge += Elapsed / 2.0f;
		}
		if (mDriftGauge > 1.0f)
		{
			mDriftGauge = 0.0f;
			if (mItemNum < 2)
				mItemNum++;
		}
	}
	else
	{
		for (int i = 2; i < 4; ++i)
		{
			if(mVehicle) mVehicle->getWheelInfo(i).m_frictionSlip = mWheelFriction;
		}
	}

	if (mBoosterLeft && mMaxSpeed < mCurrentSpeed)
		mEngineForce = mBoosterEngineForce;

	for (int i = 0; i < 2; ++i)
	{
		if (mVehicle)
		{
			mVehicle->applyEngineForce(mEngineForce, i);
			mVehicle->setBrake(mBreakingForce, i);
		}
	}

	if (mVehicle)
	{
		int wheelIndex = 0;
		mVehicle->setSteeringValue(mVehicleSteering, wheelIndex);
		wheelIndex = 1;
		mVehicle->setSteeringValue(mVehicleSteering, wheelIndex);
	}
}

void PhysicsPlayer::Update(float elapsedTime, float updateRate)
{
	GameObject::Update(elapsedTime, updateRate);
	
	for (int i = 0; i < 4; ++i)
	{
		if (mVehicle)
		{
			btTransform wheelTransform = mVehicle->getWheelTransformWS(i);
			mWheel[i]->UpdatePosition(elapsedTime, wheelTransform);
		}
	}

	//btVector3 linearVel = mBtRigidBody->getLinearVelocity();
	//mBtRigidBody->applyCentralImpulse(btVector3(0, -linearVel.length() / 10, 0));

	if (mBoosterLeft > 0.0f)
	{
		if (mFovCoefficient < 1.1f)
			mFovCoefficient += elapsedTime * 5.0f * (1.1f - mFovCoefficient);
		else
			mFovCoefficient = 1.1f;
	}
	else
	{
		if (mFovCoefficient > 1.0f)
			mFovCoefficient -= elapsedTime * 5.0f * (mFovCoefficient - 1.0f);
		else
			mFovCoefficient = 1.0f;
	}
}
Update runs after OnPreciseKeyInput runs.

The vehicle chassis was created using a Hull Shape created by the V-HACD.

And I don't know if this is going to be an impact, but because the vehicle modeling is pretty big, all the objects have been scaled six times accordingly.

That is, 1 meter is 6 in the code internal value.

I'm not sure what part of the code is causing this sudden bounce. Is there any guideline for tuning the Raycast Vehicle?
bennicus
Posts: 4
Joined: Wed Mar 30, 2022 9:29 am

Re: Raycast Vehicle bounces while driving for unknown reasons

Post by bennicus »

I haven't used the bullet raycast vehicle before, but try logging or visualizing the contact normal of each wheel. It's possible that the wheel raycast could be hitting on a boundary between triangles and giving you horizontal or upside-down normal, I've had this problem before with raycast wheels on tri meshes in PhysX. If that's the issue, you might want to try manually smoothing or filtering out sudden changes in the normal direction like that.
Post Reply