Determining contact area of touching parts

6d142d2093ef6d9e9614348bfcc4c5b2

Given 2 touching parts, what would be a reliable and at least somewhat performant way of determining the approximate position of where the parts are touching? In the image above, I am looking for the approximate location of the red circle.

This would be very simple if Roblox included touch position in any of its collision functions, but that is not the case. Unfortunately, raycasts aren’t a good option since that would require 1,000s or more rays just to find the approximate location, and even then they’re liable to miss if the parts are especially big and their contact area is especially small.

This wouldn’t be so bad if I didn’t have to do this process with about 10,000 touching parts (imagine a map of large buildings).

Let me know if there is some trick with some obscure functions or services that I’m not aware of, or perhaps an algorithm I could follow for the raycasts that would keep them from missing.

2 Likes

from what I know, the distance of 2 parts can only be measured by the part CFrame or Position.

I’m not looking for the distance between parts, I’m looking for their collision/intersection area or approximate position.

2 Likes

There isn’t a built in way to tell where a collision is happening.

As for custom solutions, it depends on what types of collisions you’re looking for and how efficient/precise you need it to be. What’s your use case?

Edit:
Oh I didn’t see this:

If all the buildings are boxes it wouldn’t be super hard. You could just use some math to find a point that represents where the intersection is. You could also use raycasts along the edges to find where edges intersect.

If you don’t need the answers real time you could also program an inefficient solution then store the data.

1 Like

It would be good to know why you need this. Perhaps there’s a better way to do what you want rather than finding contact area.

1 Like

It is for a building stability system where parts that lack proper support will break apart when under stress. The stability is determined by taking note of the surface area of the contact points to other parts, their stability values, gravity, weight, etc. It doesn’t need to be incredibly accurate.
I’m likely going to need to figure out OBB vs. OBB intersection algorithms, though I’m yet to actually find any online; everyone only wants SAT checks.

1 Like

If the increment isn’t very low, you could just use raycasting in squares on the bottom of the cuboid and calculate contact area from that

local Cuboid = workspace.Cuboid

local Increment = 0.1

local MaxContacts = (Cuboid.Size.X / Increment) * (Cuboid.Size.Z / Increment)

local RayParams = RaycastParams.new()
RayParams.FilterType = Enum.RaycastFilterType.Blacklist
RayParams.FilterDescendantsInstances = {Cuboid}

local Contacts = 0

for X = -Cuboid.Size.X / 2, Cuboid.Size.X / 2, Increment do
	for Z = -Cuboid.Size.Z / 2, Cuboid.Size.Z / 2, Increment do
		local Position = Cuboid.Position + Vector3.new(X, 0, Z)
		
		local Hit = workspace:Raycast(
			Position,
			Vector3.new(0, -1, 0),
			RayParams
		)

		if Hit then
			Contacts += 1
		end
	end
end

local ContactAreaUnit = Contacts / MaxContacts

print(ContactAreaUnit, Contacts, MaxContacts)

if ContactAreaUnit < 0.5 then
    --More than half of the structure is floating
end


The red block is half floating, and the code reports this with ContactAreaUnit being 0.5
image

The reason why I’m not raycasting to find the collision point is that I would need to fire off a large number of rays to reliably find all contact areas, and the smaller the contact areas can be, the more rays I need.

For example, say I need to find the contact points on a 20x20x20 stud part and the smallest contact area allowed is 0.25x0.25 studs. Assuming I fire the rays in a cuboid pattern around the part in question, the increment would have to be 0.25 studs or less. That would be 6400 rays per side and 38400 rays in total. While not the end of the world, it would be pretty slow (even when not done live) and would still limit the smallest contact area to 0.25 studs.

The idea I had in mind is, once I had the approximate location of the contact point, to fire a circle of rays at the location and expand them until they reach the edges of the contact area in a binary search fashion (fast at first, slows down by half every time it changes direction). Once the rays are done, I take their data and calculate the approximate surface area of where the parts are touching and plug that into the stability system that does what it wants with it.

You could also take a voxel approach: breaking down the buildings into voxels, then very roughly checking the voxels with GetPartBoundsInBox. Maybe instead of using cubes use tall rectangles to optimize things too.

You could also wait for RigidConstraints, though that will probably be a while.

I will probably do something like that for the stability calculations so they can be done live for cheap (e.g. if a floor has lost its support pillars and too many players are on it, the floor may collapse), but not for the contact areas between parts. That needs to be figured out beforehand and used later.

After some research on OBB (oriented bounding box) vs. OBB collision checking, I found that the best way of finding the approximate contact area of 2 parts is to fire 2 rays along every edge of both parts; 1 forwards, 1 backwards, and have them whitelist the other part.

Doing so will return the points where the parts’ bounding boxes intersect with minimal cost. These contact points will accurately show you the exact contact area of the parts if they are both blocks, requiring no additional work.

Since this would only detect intersecting areas and not touching areas, adding a small value like 0.001 to the distance of each ray will cause touching areas to be included, as seen in the latter bit of the video.

While this wouldn’t be enough for complex shapes like wedges, spheres, cylinders, or mesh parts, it would still give the approximate contact area for all of them! No matter the type of part, if the parts are touching, their bounding boxes will intersect around the area being touched. With this info, I can fire a circle of rays at the area and use them to scan for where the parts are intersecting or touching and find the edges, giving a reliable result. I’ll update when I do that.

9 Likes

After doing a bounding box intersection check, if one of the parts isn’t a block (e.g. a sphere) I fire some rays within the intersection to find the approximate contact area. With that, I fire the circle of rays around this position and scan for the exact contact area, giving me the contact area for complex shapes.

This includes mesh parts as well! This does slow things down quite a bit.
For blocks, of course, none of this is necessary and the bounding box intersections are enough.

5 Likes

Hey! Sorry this is a bit late, but you would mind sharing your code/ make is open sourced? This looks like exactly what In need and I would greatly appreciate it!

8 Likes

Prior to seeing this thread I’ve also just decided to use blockcasting, but it’s still very inefficient and susceptible to alot of bugs, so I would avoid using raycasting entirely tbh

But neither did I find any better solution at the moment, to solve the same problem

1 Like