Comments (7)
I'm also getting this issue, randomly as I move my planes around
from ezy-slice.
This appears to happen when 1 or more points in a triangle fall ON the plane.
If the other point(s) are UP, the whole triangle should be considered UP.
If the other point(s) are DOWN, the whole triangle should be considered DOWN.
If 1 point falls on the plane, 1 is UP and 1 is DOWN, then the triangle should be split between the two hulls.
from ezy-slice.
Found a few reasons for this issue.
1: Plane.SideOf uses float.Epsilon to determine whether or not a point is ON the plane. This is something like 1e-45 which in this case may as well be zero. I changed this to use an epsilon of 0.0001f which makes the behavior much more stable.
2: In Slicer.Slice, if a triangle is not successfully split, only the first vert is considered when determining the side of the whole triangle. This causes big problems if that vert is ON, because then it's just added to the upperHull via this code:
SideOfPlane side = pl.SideOf(verts[i0]);
if (side == SideOfPlane.UP || side == SideOfPlane.ON) {
mesh.upperHull.Add(newTri);
} else {
mesh.lowerHull.Add(newTri);
}
Consider the following instead:
SideOfPlane sa = pl.SideOf(verts[i0]);
SideOfPlane sb = pl.SideOf(verts[i1]);
SideOfPlane sc = pl.SideOf(verts[i2]);
SideOfPlane side = SideOfPlane.ON;
if (sa != SideOfPlane.ON)
{
side = sa;
}
if (sb != SideOfPlane.ON)
{
Debug.Assert(side == SideOfPlane.ON || side == sb);
side = sb;
}
if (sc != SideOfPlane.ON)
{
Debug.Assert(side == SideOfPlane.ON || side == sc);
side = sc;
}
if (side == SideOfPlane.UP || side == SideOfPlane.ON) {
mesh.upperHull.Add(newTri);
} else {
mesh.lowerHull.Add(newTri);
}
Additionally, we can and should short out Intersector.Intersect in these cases. Currently we're only shorting out if all 3 sides are equal or 2 or more verts are ON. This is my check:
// detect cases where one point is on the plane and the other two are on the same side
else if ((sa == SideOfPlane.ON && sb != SideOfPlane.ON && sb == sc) ||
(sb == SideOfPlane.ON && sa != SideOfPlane.ON && sa == sc) ||
(sc == SideOfPlane.ON && sa != SideOfPlane.ON && sa == sb)) {
return;
}
For what it's worth I'm still getting those asserts triggered sometimes. Currently looking into how that is possible.
from ezy-slice.
This is such a frustrating bug!
@SlimeQ if your solution above provides better and more consistent results, would you be able to do a pull request and i'll merge it with the current code.
I'm going to dig out some of my old collision detection books to see if there is anything about performing reliable comparison tests on 32bit or 64bit floating point numbers. would be keen to patch it up once and for all.
from ezy-slice.
@DavidArayan I was hoping to avoid making a pull request since I made some other changes as well and didn't want to sort it out myself... anybody should be able to implement the fix from the info I provided above but I'll see if I can find the time to make the pull request myself tomorrow.
Obviously if epsilon is too big you're going to run into issues with very small meshes, but I'm not really sure what the limits here are. 0.0001f works fine for my particular case but it's literally just a box that I'm slicing with a few planes. The box is a few units high (most of the time) and at least one plane intersects the corners of the box at all times. Before the epsilon fix I was getting crazy flashing as I resized the box, because of the rounding errors.
I mean think about it, if you're just checking x == 0 you have 0 bits of wiggle room. float.Epsilon by definition gives you 1 bit of wiggle room so if you're checking that -epsilon < x < epsilon you're only giving yourself a window of 3 bits which is still ridiculously strict. I've observed this type of rounding errors elsewhere in my projects and it seems like the margin of error is somewhere around 1e-5 which is surprisingly large.
The other part is just a logic change, I determined what was happening by drawing the triangles during the split operation like so:
public static void Intersect(Plane pl, Triangle tri, IntersectionResult result) {
...
{
Color aColor = Color.white;
switch (sa)
{
case SideOfPlane.ON:
aColor = Color.yellow;
break;
case SideOfPlane.UP:
aColor = Color.green;
break;
case SideOfPlane.DOWN:
aColor = Color.red;
break;
}
Debug.DrawLine(a, (a+b)/2, aColor);
Debug.DrawLine(a, (a+c)/2, aColor);
Color bColor = Color.white;
switch (sb)
{
case SideOfPlane.ON:
bColor = Color.yellow;
break;
case SideOfPlane.UP:
bColor = Color.green;
break;
case SideOfPlane.DOWN:
bColor = Color.red;
break;
}
Debug.DrawLine(b, (a+b)/2, bColor);
Debug.DrawLine(b, (b+c)/2, bColor);
Color cColor = Color.white;
switch (sc)
{
case SideOfPlane.ON:
cColor = Color.yellow;
break;
case SideOfPlane.UP:
cColor = Color.green;
break;
case SideOfPlane.DOWN:
cColor = Color.red;
break;
}
Debug.DrawLine(c, (c+b)/2, cColor);
Debug.DrawLine(c, (c+a)/2, cColor);
}
...
}
With the super tiny epsilon, I could see the coplanar points flipping between yellow (ON) and red (DOWN) as I moved them around in world space. After the epsilon change those ON corners stay yellow but always get added to the UP hull.
from ezy-slice.
Hi @DavidArayan, Just submitted a pull request for this fix.
I have not seen the asserts get triggered using this code, there was some issue with my short-out logic before.
You may want to experiment with smaller epsilon values, but this one worked for my purposes.
from ezy-slice.
Hello @SlimeQ
Thank you for your contribution! I've tested on my end and successfully merged the pull request, cheers!
from ezy-slice.
Related Issues (20)
- Apply to Animated Model? HOT 5
- Bug: wrong slice direction when object we want to cut has different localscale on axis HOT 1
- If a mesh does not intersect the cutting plane it would be nice if I was told if it was on the upper or lower side. HOT 3
- How to test an example project?
- The name 'Normal' does not exist in the current context HOT 1
- Script Doesn't Link To Editor HOT 2
- Oculus Quest crashing HOT 7
- Slicing Unity's sphere results in meshes with uncovered holes HOT 5
- When cutting a complex mesh, the face does not respect the geometry HOT 1
- Get the intersection points HOT 2
- Lost HOT 4
- Doesn't work for more complex objects HOT 6
- After slicing the game object the original prefab holes are closed , the region is filled? i wanted to know if we can retain the original holes in the obj after slicing the game object ? HOT 3
- Ezy Slice - imported objects don't get sliced HOT 4
- Randomly doesn't slice (this could well be user error) HOT 2
- Can't download the project through unity git system. HOT 1
- [bug]Cut a hollow object in the middle. The object after cutting is incorrect HOT 1
- I'm curious. This object is not complex, but it can't be cut HOT 1
- Unexpected hole patching after slice HOT 1
- how can i add internal material to sliced object
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ezy-slice.