In-experience Constructive Solid Geometry (CSG) APIs now available in published experiences [Beta]

Hey! The new system is great except for one issue regarding GeometryService:SubtractAsync().

If you resize a PartOperation and subtract it from another part, the PartOperation’s Size and PartColor are reverted. This is not the case for unions, which has its Size and PartColor applied in the subtraction function for Part:SubtractAsync(). Is this intended or would it be fixed in the future?

Attached is an image and place which explains this better. Thanks :+1:

place.rbxl (56.4 KB)

2 Likes

Hi @HungryMangoes. Thanks for the bug report looking at it right now. This is very much a bug.

I have to say, I LOVE the repro file :slight_smile:

Thanks
~BelgianBikeGuy

2 Likes

Pretty Cool!

Finally a update to better physics in a roblox game!

Things that can be improved:

Would like to see a Substitute function for mesh parts.
Would love to see the documentation being easier.
Keeping a basepart as the main part when subtracting.

Bugs:

On creation of new part after subtraction the new part does not keep color on removed bits

GeometryService

2 Likes

Hi @Loiciboy123

Two bugs were found with scaling and color and are being worked on. In particular with the usePartColor property on PartOperation. You seem to have a slightly different error happening? I’m having some issues seeing the issue from the Gif, If you have an example repro place (or want me to join a group to show me something, feel free to shoot me a DM)

  1. Substitute on MeshParts: it’s definitely something we’re looking at (along with CSG on mesh and so forth). No set ETA but active development
  2. Documentation: If you could explain what your issue is/ was, we could try to make it better for future developers :).
  3. BaseParts unfortunately cannot support Meshes or PartOperation data. I’m not saying this will never be possible but this is a bit more of a fundamental problems. BaseParts are extremely optimized and light but it comes at a cost of a lack of flexibility

Hey @HungryMangoes ,

A quick follow up on your bug report:

  1. Color issue is a trivial fix and we should have that in extremely fast (look for release of bug fix sometime next week)
  2. the issue with scaling is a little more complex but should have a fix the week after that (hopefully in two weeks)
3 Likes

Oh alright sounds good. Thanks again! :smiley:

i commented out the code because it didn’t feel natural inside the game but if you want you can test some stuff inside the game, ill revert the code if youd like!

It would be appreciated to try to identify the problem. (and hopefully discovered I’ve fixed it with code change from yesterday :slight_smile: )

Could :GetClosestPointOnSurface() potentially also return the surface normal, or could we get a way to retrieve the surface normal at that location? This would be useful for a variety of behaviours.

It would also be very useful to have e.g. :IsPointInsidePart() and potentially :GetClosestPointInVolume().

With the surface normal you could determine this for fully convex parts like so:

local function isPointInside(part: BasePart, position: Vector3)
	local closestPoint = part:GetClosestPointOnSurface(position)
	local surfaceNormalAtPoint = ???

	return surfaceNormalAtPoint:Dot(position - closestPoint) < 0
end

Having the surface normal would essentially let you compute SDFs for arbitrary part geometry which is useful for a variety of things outside of raymarching but could be used to implement raymarching in luau. Another more practical usecase for deciding if a point is inside of a part is finding the closest point not just on the surface of the part but in the entire part’s volume.

I currently would like to be able to determine the closest point in a part’s volume to another part’s center so I can determine the two corresponding depths between two contacting or overlapping parts for computing this more accurately as it depends on the distance to the measured temperatures (which would be measured from the part’s centers)

c.c. @FGmm_r2

2 Likes

I was wondering if they could make CollisionFidelity changeable during runtime :eyes:

You can choose the collisionFidelity as a result of an operation. Changing the collisionfidelity directly is something we have (and still are) discussing. There are a couple of annoyances with it, especially related to processing time and supporting APIs in perpetuity.

In other words, we’re looking into it :slight_smile:

1 Like

This is a massive point that needs to be addressed, how will the functionality of these systems work when we apply factors such as force, billboardGUI’s is it just totally incompatible?

1 Like

I was really hoping the decal support would be more accurate than… whatever this is :confused:

Though it seems like on smaller chunks removed it’s working better. Getting some flicker on the decal with fast substitutions, but nothing too crazy.

Also, why does it say I can’t call this method from a plugin yet when I try to use it in Studio’s command prompt? Surely it should support in studio/plugin usage if it’s out in games already… lol

1 Like

I’ve been using this API for procedural generation as a polygon efficient solution for flat surfaces when previously I was using terrain.

First, I create the platforms and holes for the stairs, then merge the overlapping ones in real time in one efficient step. to create a solution for merging unions that I can use simply.

1 Like

Also, I agree the decal placement is not accurate. I use exact 20x2x20 increments in my real time usage of the api and I get inconsistent results from the decal placement. As you can see in my picture each texture is offset by 10, but sometimes it looks correct and sometimes it doesn’t even though I’m using math and increments of 20. It appears to be a bug.

Two parts, same position, before union.

Unioned Parts has different texture offset with the same geometry. It’s inconsistent, maybe too late to fix it. idk.

I’m going to try to add an exception for when the texture is parented to a part and when it is parent to a union to try to fix it.

1 Like

Do you think these problems are worth filing as bugs at this point?

The problem is that its inconsistent. Sometimes the textures align perfectly with the default offset that works with parts, and other times its offset on the x or z. I’m using exact increments of 20 so it should appear consistently. Meanwhile what it is doing is alternating between offset by 10 and not offset by 10. So it definitely appears to be a bug, because how can I anticipate the behavior of the textures algorithmically?
Issue:

  1. Textures have inconsistent offset behavior when using unions

Seems so. Interestingly this might be somewhat unrelated to the problem I was having - In my gif, the texture is lined up how it should be on the union itself, but when I ‘chop’ part of the union off, the change to the union’s bounding box or size decides to scrunch the decal down as though it was placed on a smaller part, rather than actually cut the image appropriately. I’m not sure mine constitutes as a bug because of that, funnily, as I think that’s just how decals work, but it’s definitely not useful behavior on cut unions…

The UVs are created via box mapping in the local coordinate system of the newly created Part. If the mainPart is always the same, I would expect the behavior to be consistent. If you can provide a simple, reproducing example I can take a look and we can figure out what exactly the problem is.

1 Like

I managed to actually solve the issue by offseting the texture by half of the size of the x and z size of the union respectively.


I also managed to rewrite my union solver with this much simpler solution that does exactly what I wanted to do.

local function areObjectsOverlapping(object1)
	-- Get the CFrame and size of the first object
	local cframe1 = object1.CFrame
	local size1 = object1.Size

	-- Get the CFrame and size of the second object


	-- Create OverlapParams
	local overlapParams = OverlapParams.new()
	overlapParams.FilterType = Enum.RaycastFilterType.Include
	overlapParams.FilterDescendantsInstances = getinterest(true)

	-- Check if object1's bounding box overlaps with object2
	local overlappingParts = workspace:GetPartBoundsInBox(cframe1, size1, overlapParams)

	-- If overlappingParts contains object2, they are overlapping
	print("Iteration")

	return overlappingParts
end

This explains the inconsistent behavior because instead of like a part that that calculates its texture bounds from the edge, this one calculates from the center. thus adding this complication when texturing unions but it performs as intended. But the choice of changing the behavior between parts and unions is probably not a good thing.