Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Physics] Bepu integration #2131

Open
wants to merge 502 commits into
base: master
Choose a base branch
from
Open

Conversation

Eideren
Copy link
Collaborator

@Eideren Eideren commented Jan 28, 2024

PR Details

Adds support for Bepu Physics as an alternative physics engine, we'll keep the current one but will move our focus towards this new one instead.

Motivation

Unified ecosystem, improved performance, flexibility and debugging experience compared to Bullet's physics engine.

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

WIP

  • Navigation - @Doprez is taking care of that part
  • Replace car asset
  • Add license above all files
  • Check that physics does not occur between input sampling and update ... ensures that update receives the most up to date inputs
  • Deal with the last few outstanding warnings
  • Split softbodies into a future PR
  • Ask if Norbo is available to check some areas that could be improved
  • Scaling / sharing issue with hulls
  • Check if gizmos for hull are working properly
  • Gizmos for box collider seem to ignore local pos ?
  • Constraints detach from colliders after changing mass
  • Access to physics tick
  • Basic gizmos for constrained bodies and axis of constraints
  • show/hide gizmos at runtime through a simple component
  • Body teleportation
  • Improve collision masks
  • Index of collider hit in intersection structure
  • Fix doprez's issue
  • Improve multi simulation
  • Cleanup and document FilterByDistance
  • Wait for Freeze and explosive memory growth when newing a ConvexHull with specific input bepu/bepuphysics2#325

Post release

  • Query mesh material index from physics tests
  • Ragdoll utilities
  • Ignore contact between specific objects, contact response utilities
  • Wider support of the different mesh formats (ExtractBepuMesh)

A huge thanks goes to @Nicogo1705 and @Doprez for working on this. As well as @RossNordby for Bepu and dealing with our nonsense.

N.B.: PR #2127 and #2120 were cherry-picked to support this PR.

COMMIT HISTORY HAS BEEN PRESERVED, DO NOT SQUASH OR REBASE - JUST MERGE

@delustra
Copy link

delustra commented Jul 4, 2024

feature request: I have a bodycomponent, which consists of many collider boxes. When I do raytracing to that bodycomponent, I want to get information which exact small collider box was hit within bodycomponent.

@delustra
Copy link

delustra commented Sep 3, 2024

I think I've found an issue. In CollisionMask.cs it says:
Collision occurs when 'a' contains all the layers set in 'b' or 'b' contains all the layers of 'a'.

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool Collide(this CollisionMask a, CollisionMask b)
    {
        CollisionMask and = a & b;
        return and != 0 && (and == a || and == b);
    }

in that logic, layers of a will always be a subset of layers of b (or vice versa). Meaning, that adding a layer of interaction to either a or b will make them noninteractive.

I'd propose doing something similar to godot. Layer and mask are two different sets of values. Layer is where the object is present and mask is what the object can interact with. They've encountered something similar before godotengine/godot-proposals#2775.

In Unity they also have something similar to masks and layers.

@Eideren
Copy link
Collaborator Author

Eideren commented Sep 3, 2024

@delustra This is one area I've been meaning to address, but I put it on the back burner as there's one edge case that I have not found a good lightweight solution for yet; both the current solution and unity/godot's implementation still require another system to ignore collisions between specific objects, rag-dolls for example typically do not collide between parts that are directly connected, but do collide with parts of other rag-dolls. Layers and masks would not handle this appropriately. Using some sort of hash table would work of course, but would introduce a significant performance hit I would rather avoid if at all possible.

@mihai-ene-public
Copy link

Hi, guys. Will this feature be in the next release? Or is there a planned release for this feature?
Thanks

@Eideren
Copy link
Collaborator Author

Eideren commented Sep 21, 2024

@mihai-ene-public Yes, it's almost ready for release, just a couple of things to iron out. Likely to be released in a minor 4.2 for testing purposes and then 4.3 once we think it is stable enough and we have samples to go along with it.

@Doprez
Copy link
Contributor

Doprez commented Oct 3, 2024

Is there a proper way to remove bepu entities from the scene? I was trying to do it the same way I usually do with just setting the scene to null but with this branch it hits the Debug.Assert for bodies and statics.

The way I am removing now is casting a ray to find the collidable:

	public bool ScreenRayCastPenetrating(out List<HitInfo> hits)
	{
		hits = [];

		Entity.Transform.GetWorldTransformation(out var _, out var rotation, out var _);
		var worldDir = -Vector3.UnitZ;
		rotation.Rotate(ref worldDir);

		Span<HitInfoStack> buffer = stackalloc HitInfoStack[16];
		int j = 0;
		foreach (var hitInfo in _bepuConfig.BepuSimulations[BepuSimulation].RaycastPenetrating(Camera.Entity.WorldPosition(), worldDir, RayLength, buffer, CollisionMask))
		{
			hits.Add(hitInfo);
		}
		if (j == 0)
		{
			return false;
		}
		return true;
	}

and then I just set the scene to null:

	public void Interact()
	{
		RaycastHandler.ScreenRayCastPenetrating(out var hits);
		if (hits.Count == 0)
			return;

		var hit = hits[0];

		// AFAIK the hits are sorted by distance, so the first hit is probably the selected object.
		// If that's the case, we'll use the second hit which should be consistant.
		if (hit.Collidable.Entity == _character.Entity)
		{
			if (hits.Count < 2)
				return;
			hit = hits[1];
		}

		// Do something with the hit
		hit.Collidable.Entity.Scene = null;
	}

EDIT: Added note, it is not crashing due to this so maybe this is just going to be normal. It does just constantly break here to tell me that the body is null.

@Eideren
Copy link
Collaborator Author

Eideren commented Oct 3, 2024

Your logic is correct*, you should not have hit those assertions, I'll look into those asap.

*The comment making the assumption that hits are sorted by distance is incorrect though, and the summary does mention this. The only guarantee you have is that the hits collected are the closest n ones; the first one could very well be further away from the origin than the last one. Sorting does require additional processing and may not be required depending on the context, so we're skipping that step, as does unity for example.

@Doprez
Copy link
Contributor

Doprez commented Oct 3, 2024

So I may have been too hasty in reporting this. I was a couple weeks behind from your branch and after pulling and rebuilding I cant seem to recreate the error. I'll be messing with this a good amount in the coming month due to an inventory system requirement for the player so Ill keep a close eye on this if it comes up again.

*The comment making the assumption that hits are sorted by distance is incorrect though, and the summary does mention this. The only guarantee you have is that the hits collected are the closest n ones; the first one could very well be further away from the origin than the last one. Sorting does require additional processing and may not be required depending on the context, so we're skipping that step, as does unity for example.

Ah ok, that is good to know. I have a dedicated abstraction class for raycasts so I can filter points before returning in that case. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants