-
Notifications
You must be signed in to change notification settings - Fork 511
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
No zero length normals. #734
Conversation
@jwesthues This fixes the problem of cutting a hemisphere out of a face, but it introduces some slightly weird shading on cones. Apparently for shading a zero normal is better than this, but for NURBS this is better than zero-length. It is actually correct at the poles of a sphere, which is where the remaining problem was happening in issue #652. Just wondering if you have a better idea how to deal with zero-length normals. |
Without having thought too deeply about this; what's the advantage of what you're doing now with |
What I did here gives a correct normal at the pole of a sphere. I was investigating a problem with a sphere. For a cone the best displacement might be at (0.5 0.001) or (0.001 0.5) but that will be similar to this normal and will need to decide between 0.001 or 0.999? There really is no correct normal for the tip of a cone - ideally I think finding the axis of revolution would give the best normal for some definition of best. |
There's no correct normal at the tip of the cone, but there is a correct normal over 100% of the surface area. So it still seems naively like just displacing the test point inwards (like with respect to the trim curves in the (u, v) plane) a bit should always get the desired answer, with either a fixed offset or some kind of heuristic (step until both derivatives have magnitude over some threshold?) to determine that? I see why your 1 - u approach gets the right answer on the sphere sections, which have a kind of symmetry. It's not obvious to me why that would be correct for arbitrary surfaces, though. |
@phkahler I agree with Jonathan. As you have already explained here sometimes NURBS patches have a "degenerate" (zero length/to a point) edge/side. In this case the tangents along that edge become undefined(?). Here is a picture: In my opinion in this case the correct logic is to fix
I could not quickly figure out how check if
It is wrong in so many ways (e.g. Instead of the above logic it bay be possible to somehow change the algorithm itself to do "the right thing (TM)" in such cases but I am light years away from understanding it :-) And last: |
@ruevs The triangle case from 652 is already fixed on master, it's only when you use the sketch line as the rotation axis that there is a problem and it seem to be due to the zero normal vector at the "pole". My fix works by using 2 different tangent vector at the pole. Only one of them will go to zero which causes the cross product (normal) to be zero. I think what I did has the normal pointing inward or outward at opposite "ends" of the degenerate curve. I'm going to try what @jwesthues suggests and just take tangents nearby along the "good" U or V axis. Another thought I had... For argument lets assume the V direction is the zero-length edge at a given U value. I think a better way to find tangent tv (only as a substitute when the real tv is zero) would be to calculate the derivative to tv with respect to U. that should work and would produce different tv vectors depending on the V coordinate even though it's always at the same point in space. Similar to offsetting along U but without actually doing so. I don't have the ambition to write that at the moment so I'm going to try the nearby u,v point ;-) |
I tried this. Both still fail often for the case of a triangle lathed around it's own edge:
But this version doesn't have strange shading issues, probably the other version points the normal inward sometimes and this doesn't. |
Lathed surfaces with a point on the lathe axis, there is a degenerate edge where one of the tangents is zero and the computed normal will be zero. That messes up booleans when the seams are in-plane with another surface. To prevent that we avoid taking tangents at the vertex and instead use on nearby.
I've updated to the @ruevs method which works better even for the spherecut. There are probably places that don't like the tangents to be zero, so fixing it there is probably better. |
Cool. If you want something nicer numerically than a check for exact equality, you could try checking if the magnitude of the vector is less than a threshold, and then incrementing (if u or v < 0.5) or decrementing (otherwise) u and v until that magnitude is greater or until you give up with an error. |
@ruevs it's fine if you think we can do better. The check for weather a tangent is going to be zero would be that the adjacent control point is equal to the one we're evaluating at. So if i,j = (0,0) we should check if ctrl[0][0].EQUALS(ctrl[1][0]) then the tu tangent is going to be zero so we should offset our v coordinate to some small value. But if ctrl[0][0].EQUALS(ctrl[0][1]) then tv is going to be zero and we should offset u. At the other extreme we're at u,v = (1,1) we'd check if ctrl[degm][degn].EQUALS(ctrl[debm-1][degn]) to see if tu is zero and set v = 0.999999. And so on. There are a lot of conditions that can probably be somewhat simplified with a bit of cleverness. Don't take my word for which control points need to match here, after that other PR for the other NURBS issue I'm not sure I can logic today ;-) |
Being lazy, I'd probably just nudge both. The unnecessary nudge won't hurt much. Another direction is to not generate coincident control points in the first place. I'm not perfectly confident that's always possible, but I suspect that it is (as long as you don't need the trim curve to be a square from (0, 0) to (1, 1), like it is now for all new extruded or lathed surfaces; whenever there's a singularity like the tip of a cone, you'd need to make that correspond to a single point of the trim curve). |
For example cones. Also a bunch of debug code. solvespace#652 solvespace#734
This avoids zero length normals. Sometimes NURBS patches have a "degenerate" (zero length/to a point) edge/side. In this case the tangent(s) on points "along" that "edge" become zero length. A normal `n` at a point (u.v) on a NURBS surface is calculated by calculating the tangents `tu` and `tv` at that point and taking the cross product. However when an edge is "degenerate" (for example a cone created by lathing a triangle) then `tv` (and possibly `tu`) becomes zero and `n` becomes zero. This causes a problems with NURBS booleans. To solve this problem the tangent calculation is changed to shift `u` or `v` inwards if they are on a degenerate/pinched point on the surface. Fixes: solvespace#652 Alternative to: solvespace#734
Here is what I came up with. Seems to work :-) |
This avoids zero length normals. Sometimes NURBS patches have a "degenerate" (zero length/to a point) edge/side. For example lathed surfaces with a point on the lathe axis. In this case the tangent(s) on points "along" that "edge" become zero length. A normal `n` at a point (u.v) on a NURBS surface is calculated by calculating the tangents `tu` and `tv` at that point and taking the cross product. However when an edge is "degenerate" then `tv` (or possibly `tu`) becomes zero and `n` becomes zero. This causes a problems with NURBS booleans when the seams are in-plane with another surface. To solve this problem the tangent calculation is changed to shift `u` or `v` inwards if they are on a degenerate/pinched point on the surface. Fixes: solvespace#652 Alternative to: solvespace#734
Closing as inferior to #736. |
This avoids zero length normals. Sometimes NURBS patches have a "degenerate" (zero length/to a point) edge/side. For example lathed surfaces with a point on the lathe axis. In this case the tangent(s) on points "along" that "edge" become zero length. A normal `n` at a point (u.v) on a NURBS surface is calculated by calculating the tangents `tu` and `tv` at that point and taking the cross product. However when an edge is "degenerate" then `tv` (or possibly `tu`) becomes zero and `n` becomes zero. This causes a problems with NURBS booleans when the seams are in-plane with another surface. To solve this problem the tangent calculation is changed to shift `u` or `v` inwards if `tu` or `tv` is shorter than a threshold value. Fixes: solvespace#652 Alternative to: solvespace#736 solvespace#734
If a surface normal is zero length, try harder by using tangents at different points along the degenerate U or V curve - like at the poles of a sphere.