openscad / openscad

OpenSCAD - The Programmers Solid 3D CAD Modeller
https://www.openscad.org
Other
7.15k stars 1.22k forks source link

internal breaking change 2021.01 vs 2019.05 #3713

Open mjk-at-sag opened 3 years ago

mjk-at-sag commented 3 years ago
module print (emboss=$preview)
    if (emboss) { children(); }
    else { difference() { children(0); children([1:$children-1]); } }

module background ()
    if (false) cube([75, 20, 10], true);

print($preview) {
    background();
    color("black")
        translate([0, 0, 4.5]) linear_extrude(1)
        text(str(version()), valign="center", halign="center");
  }
  1. open with 2021.05

  2. F6 - render

  3. read "WARNING: No top level geometry to render"

  4. F7 - export

  5. read "ERROR: Nothing to export! ..."

  6. open with 2019.05

  7. F6

  8. F7

  9. success

--- Want to back this issue? **[Post a bounty on it!](https://app.bountysource.com/issues/97022585-internal-breaking-change-2021-01-vs-2019-05?utm_campaign=plugin&utm_content=tracker%2F52063&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://app.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F52063&utm_medium=issues&utm_source=github).
thehans commented 3 years ago

@mjk-at-sag This is a consequence of changes from #3342 and how empty geometries are now handled. The bug was in 2019 version, and is now fixed. You are subtracting your text from an empty child background(); so the result is empty geometry.

mjk-at-sag commented 3 years ago

@thehans Very well, I accept that. Now I don't understand why the following two designs produce the same results when previewed (F5) and different results when rendered (F6).

This produces the now correct result:

module print (emboss=$preview)
    if (emboss) { children(); }
    else { difference() { children(0); children([1:$children-1]); } }

module background ()
    if (false) cube([75, 20, 10], true);

print($preview) {
    //////// background();       //////////////// <========
    color("black")
        translate([0, 0, 4.5]) linear_extrude(1)
        text(str(version()), valign="center", halign="center");
    color("red")
        translate([0, 0, -0.5]) linear_extrude(1)
        text(str(version()), valign="center", halign="center");
}

This produces the old incorrect result:

module print (emboss=$preview)
    if (emboss) { children(); }
    else { difference() { children(0); children([1:$children-1]); } }

module background ()
    if (false) cube([75, 20, 10], true);

print($preview) {
    if (false) background();     ////////////////// <=======
    color("black")
        translate([0, 0, 4.5]) linear_extrude(1)
        text(str(version()), valign="center", halign="center");
    color("red")
        translate([0, 0, -0.5]) linear_extrude(1)
        text(str(version()), valign="center", halign="center");
}
thehans commented 3 years ago

OK, I see. The second example does appear to be a bug when rendered with F6.

kintel commented 8 months ago

Looking at this, it looks correct: The designs happen to produce the same results when previewed (F5) and different results when rendered (F6) because the design is written to handle previews differently from render.

jordanbrown0 commented 8 months ago

The preview/render difference is presumably related to the $preview.

But the 2019-vs-later difference is, as @thehans described above, based on a change in the behavior of empty geometries.

Here's a test case:

module dummy() {
}

difference() {
    dummy();
    cube(10);
    cube(10, center=true);
}

2019.05 ignores the dummy child, for at least some purposes, and yields a cube with the corner cut out. 2021.01 and later subtract two cubes from nothing, and yield nothing.

Note: in all three, an "if" is counted as a child, but if it fails it yields no geometry. Or something like that. If you change the dummy(); to if (false) dummy();, all three yield the cube with corner cut off; the failing "if" does not count as the first child of the difference.

module dummy() {
}

difference() {
    if (false) dummy();
    cube(10);
    cube(10, center=true);
}

Similarly, if the first child of the difference() is an echo(), it is ignored for geometry purposes and yields the cube-with-cut-corner. However, if the first child of the difference is a module that calls echo() and does nothing else, in 2019.05 it's ignored and in 2021.01 and later that does count for geometry purposes, and you end up with nothing.


My humble opinion is that they are all wrong, though 2021.01 and later are better. Every module invocation, including echo, failing if, and for-that-executes-zero-times, should yield geometry, perhaps empty. Nothing should peek at the resulting geometry, in any way, to handle it specially if it is empty.

jordanbrown0 commented 8 months ago

Further clarification: they should all yield exactly one child, which might be empty geometry.