Physx vehicle whith sweep contact in 3.4 build

Hello,

I have tried the sweep queries on our engine but i found an problem , we have minus z axis as forward for the vehicle PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(0, 0, -1)) this case is a problem at the suspensions they bounce on the y axis . I tested on the snippets project too and this bug apears only when the ground is an heightfield and the forward axis is on -Z. Is this an bug or we could solve this issue somehow ?

Hello,

I don’t fully understand the problem. I must have misunderstood but I don’t see any problem at all!

From your description I expect the suspension to move up and down along the y-axis. The problem you describe is that the suspensions bounce on the y axis. That is the expected behaviour.

The suspension moves along the up vector. The up vector is set in the first function argument passed to PxVehicleSetBasisVectors. Your code sets (0,1,0) to be the up vector. I’d expect the suspension to move along the y-axis.

Videos, screengrabs and pvd recordings might help show the problem more clearly.

Cheers,

Gordon

The origin of the sweep query is translated on +Y randomly on the pvd tool some frames the sweeps results run corectly and some frames don’t (the result query shows them as in air) and the wheels bounce even when the car has velocity 0(very unstable).I will post tomorow an link with video :) .

We are preparing an updated version of pvd. Our efforts to get that ready has meant a few bugs have appeared in the released pvd tool with 3.4. One of those bugs is the visualisation of batched sweeps and raycasts.

The unstable car is a greater concern. Could you post a pvd recording as well as a video?

Cheers,

Gordon

I know is not the final release but in game the suspension is the same , I think it’s engine problem not tool problem .

tool video link: http://sendvid.com/oacj89dv
snippet video: http://sendvid.com/ja2hords

That doesn’t look good.

It is unlikely that pvd would add jitter when it visualises the car’s motion. This is a data or coding problem somewhere.

It is very hard to diagnose this from a video. Did you make the second video by modifying a vehicle snippet? Could you send me all the changes you made to the snippet code so I can reproduce exactly what you did?

Yes , I’ve added an flat heightfield(i’ve change the plane creation function ) and changed this PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(0, 0, 1)) to this PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(0, 0, -1)). with car forward on +Z iti works fine , but when I set it on -Z it’s not working.

This is the initPhysics function with the modifications :).

void initPhysics()
{
	gFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, gAllocator, gErrorCallback);
	gPvd = PxCreatePvd(*gFoundation);
	PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate(PVD_HOST, 5425, 10);
	gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL);

	gPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gFoundation, PxTolerancesScale(),true, gPvd);

	PxSceneDesc sceneDesc(gPhysics->getTolerancesScale());
	sceneDesc.gravity = PxVec3(0.0f, -9.81f, 0.0f);
	
	PxU32 numWorkers = 1;
	gDispatcher = PxDefaultCpuDispatcherCreate(numWorkers);
	sceneDesc.cpuDispatcher	= gDispatcher;
	sceneDesc.filterShader	= VehicleFilterShader;							//Set the filter shader
	sceneDesc.contactModifyCallback = &gWheelContactModifyCallback;			//Enable contact modification
	sceneDesc.ccdContactModifyCallback = &gWheelCCDContactModifyCallback;	//Enable ccd contact modification
	sceneDesc.flags |= PxSceneFlag::eENABLE_CCD;							//Enable ccd

	gScene = gPhysics->createScene(sceneDesc);
	PxPvdSceneClient* pvdClient = gScene->getScenePvdClient();
	if(pvdClient)
	{
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true);
	}
	gMaterial = gPhysics->createMaterial(0.1f, 0.1f, 0.01f);

	gCooking = 	PxCreateCooking(PX_PHYSICS_VERSION, *gFoundation, PxCookingParams(PxTolerancesScale()));	

	/////////////////////////////////////////////

	PxInitVehicleSDK(*gPhysics);
	PxVehicleSetBasisVectors(PxVec3(0,1,0), PxVec3(0,0,-1));
	PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
	PxVehicleSetSweepHitRejectionAngles(POINT_REJECT_ANGLE, NORMAL_REJECT_ANGLE);
	PxVehicleSetMaxHitActorAcceleration(MAX_ACCELERATION);

	//Create the batched scene queries for the suspension sweeps.
	//Use the post-filter shader to reject hit shapes that overlap the swept wheel at the start pose of the sweep.
	PxQueryHitType::Enum(*sceneQueryPreFilter)(PxFilterData, PxFilterData, const void*, PxU32, PxHitFlags&);
	PxQueryHitType::Enum(*sceneQueryPostFilter)(PxFilterData, PxFilterData, const void*, PxU32, const PxQueryHit&);
#if BLOCKING_SWEEPS
	sceneQueryPreFilter = &WheelSceneQueryPreFilterBlocking;
	sceneQueryPostFilter = &WheelSceneQueryPostFilterBlocking;
#else
	sceneQueryPreFilter = &WheelSceneQueryPreFilterNonBlocking;
	sceneQueryPostFilter = &WheelSceneQueryPostFilterNonBlocking;
#endif 
	gVehicleSceneQueryData = VehicleSceneQueryData::allocate(NUM_VEHICLES, PX_MAX_NB_WHEELS, gNbQueryHitsPerWheel, NUM_VEHICLES, sceneQueryPreFilter, sceneQueryPostFilter, gAllocator);
	gBatchQuery = VehicleSceneQueryData::setUpBatchedSceneQuery(0, *gVehicleSceneQueryData, gScene);

	//Create the friction table for each combination of tire and surface type.
	gFrictionPairs = createFrictionPairs(gMaterial);
	
	//Create a plane to drive on.
	PxFilterData groundPlaneSimFilterData(COLLISION_FLAG_GROUND, COLLISION_FLAG_GROUND_AGAINST, 0, 0);
	PxShape* shape = NULL;
	PxU16 nbColumns = PxU16(1024);
	PxU16 nbRows = PxU16(1024);
	PxHeightFieldDesc heightfieldDesc;
	heightfieldDesc.nbColumns = nbColumns;
	heightfieldDesc.nbRows = nbRows;
	PxHeightFieldSample* samplesData = (PxHeightFieldSample*)malloc(sizeof(PxHeightFieldSample) * (nbColumns * nbRows));
	heightfieldDesc.samples.data = samplesData;
	heightfieldDesc.samples.stride = sizeof(PxHeightFieldSample);
	heightfieldDesc.convexEdgeThreshold = 0;
	PxHeightFieldSample* currentByte = (PxHeightFieldSample*)heightfieldDesc.samples.data;

	for (PxU32 column = 0; column < nbRows * nbColumns; column++)
	{
		//for(PxU32 row = 0; row < nbRows; row++)
		{
			PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
			currentSample->height = 0;
			currentSample->materialIndex0 = 0;
			currentSample->materialIndex1 = 0;
			currentSample->clearTessFlag();
			currentByte++;
		}
	}
	heightfieldDesc.isValid();
	PxHeightField* heightfield = gCooking->createHeightField(heightfieldDesc, gPhysics->getPhysicsInsertionCallback());
	delete samplesData;
	shape = gPhysics->createShape(PxHeightFieldGeometry(heightfield, PxMeshGeometryFlags(), 1.f, 1, 1), *gMaterial);

	PxFilterData simFilterData;
	simFilterData.word0 = COLLISION_FLAG_GROUND;
	simFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST;
	shape->setSimulationFilterData(simFilterData);

	physx::PxFilterData qryFilterData;
	qryFilterData.word3 = DRIVABLE_SURFACE;
	shape->setQueryFilterData(qryFilterData);

	shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, true);
	shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);

	PxTransform trs = PxTransform(PxIdentity);
	trs.p.x -= 100;
	trs.p.z -= 100;
	PxRigidStatic* groundPlane = gPhysics->createRigidStatic(trs);
	groundPlane->attachShape(*shape);
	gScene->addActor(*groundPlane);

	//Create several static obstacles for the first vehicle to drive on.
	//  (i) collide only with wheel shapes
	// (ii) have continuous collision detection (CCD) enabled
	//(iii) have contact modification enabled
	// (iv) are configured to be drivable surfaces
	const PxF32 capsuleRadii[4] = {0.05f, 	0.1f, 0.125f, 0.135f};
	const PxF32 capsuleZ[4] = {5.0f, 10.0f, 15.0f, 20.0f};
	for(PxU32 i = 0; i < 4; i++)
	{
		PxTransform t(PxVec3(xCoordVehicleStarts[0], capsuleRadii[i], capsuleZ[i]), PxQuat(PxIdentity));
		PxRigidStatic* rd = gPhysics->createRigidStatic(t);
		PxCapsuleGeometry capsuleGeom(capsuleRadii[i], 3.0f);
		PxShape* shape = PxRigidActorExt::createExclusiveShape(*rd, capsuleGeom, *gMaterial);
		PxFilterData simFilterData(COLLISION_FLAG_OBSTACLE, COLLISION_FLAG_WHEEL, PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eDETECT_CCD_CONTACT, 0);
		shape->setSimulationFilterData(simFilterData);
		PxFilterData qryFilterData;
		setupDrivableSurface(qryFilterData);
		shape->setQueryFilterData(qryFilterData);
		gScene->addActor(*rd);
	}
	const PxF32 boxHalfHeights[1] = {1.0f};
	const PxF32 boxZ[1] = {30.0f};
	for(PxU32 i = 0; i < 1; i++)
	{
		PxTransform t(PxVec3(xCoordVehicleStarts[0], boxHalfHeights[i], boxZ[i]), PxQuat(PxIdentity));
		PxRigidStatic* rd = gPhysics->createRigidStatic(t);

		PxBoxGeometry boxGeom(PxVec3(3.0f, boxHalfHeights[i], 3.0f));
		PxShape* shape = PxRigidActorExt::createExclusiveShape(*rd, boxGeom, *gMaterial);
		
		PxFilterData simFilterData(COLLISION_FLAG_OBSTACLE, COLLISION_FLAG_WHEEL, PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eDETECT_CCD_CONTACT, 0);
		shape->setSimulationFilterData(simFilterData);
		PxFilterData qryFilterData;
		setupDrivableSurface(qryFilterData);
		shape->setQueryFilterData(qryFilterData);
		
		gScene->addActor(*rd);
	}

	//Create a pile of dynamic objects for the second vehicle to drive on.
	//  (i) collide only with wheel shapes
	// (ii) have continuous collision detection (CCD) enabled
	//(iii) have contact modification enabled
	// (iv) are configured to be drivable surfaces
	{
		for (PxU32 i = 0; i < 64; i++)
		{
			PxTransform t(PxVec3(xCoordVehicleStarts[1] + i*0.01f, 2.0f + i*0.25f, 20.0f + i*0.025f), PxQuat(PxPi*0.5f, PxVec3(0, 1, 0)));
			PxRigidDynamic* rd = gPhysics->createRigidDynamic(t);
	
			PxBoxGeometry boxGeom(PxVec3(0.08f, 0.25f, 1.0f));
			PxShape* shape = PxRigidActorExt::createExclusiveShape(*rd, boxGeom, *gMaterial);

			PxFilterData simFilterData(COLLISION_FLAG_OBSTACLE, COLLISION_FLAG_OBSTACLE_AGAINST, PxPairFlag::eMODIFY_CONTACTS | PxPairFlag::eDETECT_CCD_CONTACT, 0);
			shape->setSimulationFilterData(simFilterData);
			PxFilterData qryFilterData;
			setupDrivableSurface(qryFilterData);
			shape->setQueryFilterData(qryFilterData);

			PxRigidBodyExt::updateMassAndInertia(*rd, 30.0f);

			gScene->addActor(*rd);
		}
	}

	//Create two vehicles that will drive on the obstacles.
	//The vehicles are configured with wheels that 
	//  (i) collide with obstacles
	// (ii) have continuous collision detection (CCD) enabled
	//(iii) have contact modification enabled
	//The vehicle chassis only collides with the ground to highlight the collision between the wheels and the obstacles.
	for (PxU32 i = 0; i < NUM_VEHICLES; i++)
	{
		PxFilterData chassisSimFilterData(COLLISION_FLAG_CHASSIS, COLLISION_FLAG_GROUND, 0, 0);
		PxFilterData wheelSimFilterData(COLLISION_FLAG_WHEEL, COLLISION_FLAG_WHEEL, PxPairFlag::eDETECT_CCD_CONTACT | PxPairFlag::eMODIFY_CONTACTS, 0);
		VehicleDesc vehicleDesc = initVehicleDesc(chassisSimFilterData, wheelSimFilterData, i);
		gVehicle4W[i] = createVehicle4W(vehicleDesc, gPhysics, gCooking);
		PxTransform startTransform(PxVec3(xCoordVehicleStarts[i], (vehicleDesc.chassisDims.y*0.5f + vehicleDesc.wheelRadius + 1.0f), 0), PxQuat(PxIdentity));
		gVehicle4W[i]->getRigidDynamicActor()->setGlobalPose(startTransform);
		gVehicle4W[i]->getRigidDynamicActor()->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, true);
		gScene->addActor(*gVehicle4W[i]->getRigidDynamicActor());

		//Set the vehicle to rest in first gear.
		//Set the vehicle to use auto-gears.
		gVehicle4W[i]->setToRestState();
		gVehicle4W[i]->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
		gVehicle4W[i]->mDriveDynData.setUseAutoGears(true);
	}
}

Thanks. I have a repro for this now. The sweeps frequently fail to find a hit against the heightfield. This does seem to be a problem with the sweeps. I’ll update soon with more details.

I found the bug and have a fix you can try straight away.

The problem was that negative scale values were being set on the convex mesh that was being swept.

A quick fix is in PxVehicleUpdate.cpp in the function PxVehicleWheels4SuspensionSweeps. Replace this

			PxVec3(
			gRight.x*sweepWidthScale + (gUp.x + gForward.x)*sweepRadiusScale,
			gRight.y*sweepWidthScale + (gUp.y + gForward.y)*sweepRadiusScale,
			gRight.z*sweepWidthScale + (gUp.z + gForward.z)*sweepRadiusScale);

with this

			PxVec3(
			PxAbs(gRight.x*sweepWidthScale + (gUp.x + gForward.x)*sweepRadiusScale),
			PxAbs(gRight.y*sweepWidthScale + (gUp.y + gForward.y)*sweepRadiusScale),
			PxAbs(gRight.z*sweepWidthScale + (gUp.z + gForward.z)*sweepRadiusScale));

Cheers,

Gordon

I tried the fix and it works fine now . Thank you Gordon.

Thanks Ionut.

Hello ,

I’m asking here another question about car sweeps . I saw in 3.4 build that we can now activate collision between wheel and terrain , it works fine in the examples . When I try to activate collision between wheel and terrain the results of the sweep show that the wheels are in air but the wheels are on the ground . What can be wrong in my build ? with the visual debugger everything looks ok . Can you help me with this Gordon ?

Thanks Ionut.