RaycastVehicle vibrating & GhostObject not giving collisions

User avatar
Pyritie
Posts: 25
Joined: Thu Aug 11, 2011 6:42 pm

RaycastVehicle vibrating & GhostObject not giving collisions

Post by Pyritie »

Hi, I'm new to bullet and I'm using a c# wrapper and have two small problems that are probably just me doing something stupid. :D

I'm doing a mariokart-like racing game.

First problem is that when I use a RaycastVehicle for the karts and drive them around (or even just let them sit there, not moving), they "vibrate" a lot.

here's the values I'm using for the wheels:

Code: Select all

Radius = 0.5
Width = 0.2
SuspensionRestLength = 0.2

SpringStiffness = 500
SpringCompression = 4.2
SpringDamping = 100
FrictionSlip = 100
RollInfluence = 1
Creating the vehicle:

Code: Select all

			Raycaster = new DefaultVehicleRaycaster(LKernel.Get<PhysicsMain>().World);
			Tuning = new RaycastVehicle.VehicleTuning();
			Tuning.MaxSuspensionTravelCm = 40f;
			Vehicle = new RaycastVehicle(Tuning, Body, Raycaster);
			Vehicle.SetCoordinateSystem(0, 1, 2); // I have no idea what this does... I'm assuming something to do with a matrix?

			LKernel.Get<PhysicsMain>().World.AddAction(Vehicle);
// then add wheels...
Wheel adding:

Code: Select all

		public void CreateWheel(Vector3 connectionPoint, bool isFrontWheel) {
			Kart.Vehicle.AddWheel(connectionPoint, WheelDirection, WheelAxle, SuspensionRestLength, Radius, Kart.Tuning, isFrontWheel);

			WheelInfo info = Kart.Vehicle.GetWheelInfo((int) WheelID);
			info.SuspensionStiffness = SpringStiffness;
			info.WheelDampingRelaxation = SpringDamping;
			info.WheelDampingCompression = SpringCompression;
			info.FrictionSlip = FrictionSlip;
			info.RollInfluence = RollInfluence;
		}
And the transform in the custom motion state thing:

Code: Select all

		public override Matrix4 WorldTransform {
			get {
				return transform;
			}
			set {
				if (node == null)
					base.Dispose();

				node.Orientation = value.ExtractQuaternion();
				node.Position = value.GetTrans();
			}
		}
Kart is a box (1.5 x 0.5 x 1.4) offset by 0.7 along +Y (using a compound collision thing).
Wheels are at 1.7f, 0.4f, 1.33f (making X and Z negative as needed)
Sooooo... I don't know what I'm doing wrong there. But it's probably something dumb!

-------------------------------------------------------------------------------------------------------

Second question: I want to have some sort of "trigger region" things (like what physx has if you've ever used that). They're basically objects that send off events when something collides with them, but you can drive through them as if they weren't there. So you could use them to find when a car passes through a checkpoint, for example.

From what I understand I have to use ghostobjects for this, but I'm not sure I'm using them right either.

here's my code that sets up the ghostobject:

Code: Select all

			// physics
			Matrix4 transform = new Matrix4(rotation.DegreeVectorToGlobalQuaternion());
			transform.SetTrans(position);

			// make our ghost object
			Ghost = new GhostObject();
			Ghost.CollisionFlags = CollisionFlags.NoContactResponse | CollisionFlags.StaticObject;
			Ghost.CollisionShape = shape; // usually something like "new BoxShape(1, 1, 1)" or similar
			Ghost.WorldTransform = transform;
			LKernel.Get<PhysicsMain>().World.AddCollisionObject(Ghost);
and then this runs each frame, after simulating. What it basically does is go through each ghost object, finds out what it's colliding with and then figures out if it's a "new" collision or not, since I only want to send out events whenever something enters or leaves a region, and not when it's just sitting inside it. (This code is pretty untested though, so I'll poke around with it some more)

Code: Select all

		void PostSimulate(DiscreteDynamicsWorld world, FrameEvent evt) {
			foreach (TriggerRegion region in Regions.Values) {
				// get our set of bodies that were inside the region from the previous frame
				Collection<RigidBody> previousBodies = region.CurrentlyCollidingWith;
				Collection<RigidBody> newBodies = new Collection<RigidBody>();

				// get all of the objects that are inside the region and add them to the new collection
				for (int a = 0; a < region.Ghost.NumOverlappingObjects; a++) {
					RigidBody body = region.Ghost.GetOverlappingObject(a) as RigidBody;
					// check to make sure this is actually a RigidBody - if it isn't, ignore it
					if (body != null) {
						newBodies.Add(body);
					}
				}

				// get the bodies that have been removed and added (yay linq)
				IEnumerable<RigidBody> added = newBodies.Except(previousBodies);
				IEnumerable<RigidBody> removed = previousBodies.Except(newBodies);

				// update the region's list of bodies that are inside it
				region.CurrentlyCollidingWith = newBodies;

				// then run our triggers
				foreach (RigidBody addedBody in added)
					region.InvokeTrigger(addedBody, TriggerReportFlags.Enter);
				foreach (RigidBody removedBody in removed)
					region.InvokeTrigger(removedBody, TriggerReportFlags.Leave);
			}
		}
At the moment when I drive through a region, nothing happens. The debug drawer's line colors on the region don't change (they're always white), and I get no events sent out. Am I doing this correctly?

I can upload a little demo if it's needed.
User avatar
Pyritie
Posts: 25
Joined: Thu Aug 11, 2011 6:42 pm

Re: RaycastVehicle vibrating & GhostObject not giving collis

Post by Pyritie »

If I flip my kart upside down, the vibration stops. So it's likely something to do with how I set up the wheels.
User avatar
Pyritie
Posts: 25
Joined: Thu Aug 11, 2011 6:42 pm

Re: RaycastVehicle vibrating & GhostObject not giving collis

Post by Pyritie »

well even if I stick a kart or a regular box inside the region, ghostObject.NumOverlappingObjects always returns 0. So my method that only fires events when things just enter or leave the region isn't causing the problem... I've also tried playing around with some more flags. Still nothing.

EDIT: weird, my collision reporter (loops through every manifold in the dispatcher every frame) picks up that the kart is inside the region, even when the region has the NoContactResponse flag, but the ghostObject.NumOverlappingObjects still has nothing.

I guess I can work around this by just using my collision reporter thing, though the ghostObject stuff is still pretty strange.

I still have no idea what's causing the vibrating though.

EDIT 2: Kulik on #ogre3d suggested upping the target framestep, which I had at 1/60. I upped it to 1/120 and max substeps to 15, and now it's a lot less vibrate-y.
User avatar
Pyritie
Posts: 25
Joined: Thu Aug 11, 2011 6:42 pm

Re: RaycastVehicle vibrating & GhostObject not giving collis

Post by Pyritie »

My trigger regions are now just static rigid bodies with the NoContactResponse flag raised.
Fixed the problem with the vibratey kart too - I had the damping set to 100. I changed it to 10 and now it doesn't vibrate at all!

...solved I guess?
irrmich
Posts: 6
Joined: Thu Sep 04, 2014 1:23 pm

Re: RaycastVehicle vibrating & GhostObject not giving collis

Post by irrmich »

Thank you, after some days of research about the cause of wheels vibration, i found your post. It's true, increasing the maxSubSteps and using your framerate 1/120 removed wheels vibrations. Thank you! :D