discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

is render() a function or a module or an operator please

JB
Jordan Brown
Fri, Aug 1, 2025 7:15 AM

[ again, sorry for duplicates]

On Jul 31, 2025, at 4:27 PM, vulcan_--- via Discuss discuss@lists.openscad.org wrote:
the operation of render() is coming clear .. it is syntactically an operator module

It is syntactically a module, and it is useful only if given children. (As I said separately, modules that are useful only with children could generate errors if childless, but the builtins do not.)

it can appear last in a statement but then it does nothing, and if it is the only module in a statement it does nothing

Both true, though I would say that they are the same case.

i have not been able to find a way that it can be used in an expression

It is a module, not a function.

[ Note: all of the stuff below is the same for render() and top-level F6. ]

And i still feel that there is a conceptual bug here:

render() sphere();

leaves the sphere as quads with n-sided polygons at north and south ends

OpenSCAD makes no particular promises about the details of its rendering. It does not promise that everything will be reduced to triangles, and it does not promise that it won’t, and whether or not a particular case is reduced to triangles can depend on subtle factors.  It would be entirely with the specification (such as it is) for it to randomly do one or the other. (We don’t like that answer for testability reasons, but it would be legal.)

So .. it should also do nothing for:

render() { sphere(); sphere(); sphere(); }

It cannot do nothing there, because it must produce a single resulting mesh that is geometrically legal (mostly, no self intersections).

Whether in that process it reduces everything to triangles is an implementation detail subject to change without notice or explanation.

because if quads are good on the solo sphere why are quads no longer acceptable when i try to draw 3 spheres ?

Quads would be completely acceptable there. But there are no promises, and for its own reasons OpenSCAD (in Manifold mode) chooses to reduce them to triangles. (Internally, this is because Manifold wants only triangles,)

and please rem from my images that i was using translate to keep them from intersecting so there are no intersections nor joints to fix up

There is no such thing.  If there’s more than one input object it must do all of the processing to figure out that there’s no overlap.  And whether or not there is overlap, it is required to produce a single geometrically legal mesh as the output.  (Note that a single mesh can have discontiguous volumes.)

Why are quads converted to triangles at all?

For specification purposes… because the program feels like it.  There is no promise one way or the other.

The actual reason is that the geometry engine (Manifold) only processes triangles.  Maybe the next version of Manifold will process non-triangles and it will no longer be necessary; we might then not do that conversion.

The key thing to understand here is that you must not care, because the behavior is unspecified and subject to change or variation without notice or explanation.

Related example: how many polygons does one invocation of cube() generate?  Six quads or twelve triangles are obvious answers, but seven, or seven hundred, would be equally legal. You must not care; the only promise is that when you assemble all of the polygons you end up with a rectangular prism of the specified dimensions. It would even be legal for the answer to be that it doesn’t generate polygons at all, that it stays as a “cube” throughout the entire pipeline, until it needs to be exported to a form that requires polygons.

[ again, sorry for duplicates] > On Jul 31, 2025, at 4:27 PM, vulcan_--- via Discuss <discuss@lists.openscad.org> wrote: > the operation of render() is coming clear .. it is syntactically an operator module > It is syntactically a module, and it is useful only if given children. (As I said separately, modules that are useful only with children could generate errors if childless, but the builtins do not.) > it can appear last in a statement but then it does nothing, and if it is the only module in a statement it does nothing > Both true, though I would say that they are the same case. > i have not been able to find a way that it can be used in an expression > It is a module, not a function. [ Note: all of the stuff below is the same for render() and top-level F6. ] > And i still feel that there is a conceptual bug here: > > render() sphere(); > > leaves the sphere as quads with n-sided polygons at north and south ends > OpenSCAD makes no particular promises about the details of its rendering. It does not promise that everything will be reduced to triangles, and it does not promise that it won’t, and whether or not a particular case is reduced to triangles can depend on subtle factors. It would be entirely with the specification (such as it is) for it to randomly do one or the other. (We don’t like that answer for testability reasons, but it would be legal.) > So .. it should also do nothing for: > > render() { sphere(); sphere(); sphere(); } > It *cannot* do nothing there, because it *must* produce a single resulting mesh that is geometrically legal (mostly, no self intersections). Whether in that process it reduces everything to triangles is an implementation detail subject to change without notice or explanation. > because if quads are good on the solo sphere why are quads no longer acceptable when i try to draw 3 spheres ? > Quads would be completely acceptable there. But there are no promises, and for its own reasons OpenSCAD (in Manifold mode) chooses to reduce them to triangles. (Internally, this is because Manifold wants only triangles,) > and please rem from my images that i was using translate to keep them from intersecting so there are no intersections nor joints to fix up > There is no such thing. If there’s more than one input object it must do all of the processing to figure out that there’s no overlap. And whether or not there is overlap, it is required to produce a single geometrically legal mesh as the output. (Note that a single mesh can have discontiguous volumes.) > Why are quads converted to triangles at all? > For specification purposes… because the program feels like it. There is no promise one way or the other. The actual reason is that the geometry engine (Manifold) only processes triangles. Maybe the next version of Manifold will process non-triangles and it will no longer be necessary; we might then not do that conversion. The key thing to understand here is that you must not care, because the behavior is unspecified and subject to change or variation without notice or explanation. Related example: how many polygons does one invocation of cube() generate? Six quads or twelve triangles are obvious answers, but seven, or seven hundred, would be equally legal. You must not care; the only promise is that when you assemble all of the polygons you end up with a rectangular prism of the specified dimensions. It would even be legal for the answer to be that it doesn’t generate polygons at all, that it stays as a “cube” throughout the entire pipeline, until it needs to be exported to a form that requires polygons.
NH
nop head
Fri, Aug 1, 2025 8:02 AM

Also, unless you use show edges, the image drawn is identical on the
screen. The graphics pipeline may simply draw two triangles for each quad
anyway.

When you export it as an STL it will be converted to triangles and when you
slice it to make a 3D print the print will be identical.

On Fri, 1 Aug 2025 at 08:16, Jordan Brown via Discuss <
discuss@lists.openscad.org> wrote:

[ again, sorry for duplicates]

On Jul 31, 2025, at 4:27 PM, vulcan_--- via Discuss <
discuss@lists.openscad.org> wrote:

the operation of render() is coming clear .. it is syntactically an
operator module

It is syntactically a module, and it is useful only if given children. (As
I said separately, modules that are useful only with children could
generate errors if childless, but the builtins do not.)

it can appear last in a statement but then it does nothing, and if it is
the only module in a statement it does nothing

Both true, though I would say that they are the same case.

i have not been able to find a way that it can be used in an expression

It is a module, not a function.

[ Note: all of the stuff below is the same for render() and top-level F6. ]

And i still feel that there is a conceptual bug here:

render() sphere();

leaves the sphere as quads with n-sided polygons at north and south ends

OpenSCAD makes no particular promises about the details of its rendering.
It does not promise that everything will be reduced to triangles, and it
does not promise that it won’t, and whether or not a particular case is
reduced to triangles can depend on subtle factors.  It would be entirely
with the specification (such as it is) for it to randomly do one or the
other. (We don’t like that answer for testability reasons, but it would be
legal.)

So .. it should also do nothing for:

render() { sphere(); sphere(); sphere(); }

It cannot do nothing there, because it must produce a single resulting
mesh that is geometrically legal (mostly, no self intersections).

Whether in that process it reduces everything to triangles is an
implementation detail subject to change without notice or explanation.

because if quads are good on the solo sphere why are quads no longer
acceptable when i try to draw 3 spheres ?

Quads would be completely acceptable there. But there are no promises, and
for its own reasons OpenSCAD (in Manifold mode) chooses to reduce them to
triangles. (Internally, this is because Manifold wants only triangles,)

and please rem from my images that i was using translate to keep them from
intersecting so there are no intersections nor joints to fix up

There is no such thing.  If there’s more than one input object it must do
all of the processing to figure out that there’s no overlap.  And whether
or not there is overlap, it is required to produce a single geometrically
legal mesh as the output.  (Note that a single mesh can have discontiguous
volumes.)

Why are quads converted to triangles at all?

For specification purposes… because the program feels like it.  There is
no promise one way or the other.

The actual reason is that the geometry engine (Manifold) only processes
triangles.  Maybe the next version of Manifold will process non-triangles
and it will no longer be necessary; we might then not do that conversion.

The key thing to understand here is that you must not care, because the
behavior is unspecified and subject to change or variation without notice
or explanation.

Related example: how many polygons does one invocation of cube()
generate?  Six quads or twelve triangles are obvious answers, but seven, or
seven hundred, would be equally legal. You must not care; the only promise
is that when you assemble all of the polygons you end up with a rectangular
prism of the specified dimensions. It would even be legal for the answer to
be that it doesn’t generate polygons at all, that it stays as a “cube”
throughout the entire pipeline, until it needs to be exported to a form
that requires polygons.


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Also, unless you use show edges, the image drawn is identical on the screen. The graphics pipeline may simply draw two triangles for each quad anyway. When you export it as an STL it will be converted to triangles and when you slice it to make a 3D print the print will be identical. On Fri, 1 Aug 2025 at 08:16, Jordan Brown via Discuss < discuss@lists.openscad.org> wrote: > [ again, sorry for duplicates] > > On Jul 31, 2025, at 4:27 PM, vulcan_--- via Discuss < > discuss@lists.openscad.org> wrote: > > the operation of render() is coming clear .. it is syntactically an > operator module > > > It is syntactically a module, and it is useful only if given children. (As > I said separately, modules that are useful only with children could > generate errors if childless, but the builtins do not.) > > it can appear last in a statement but then it does nothing, and if it is > the only module in a statement it does nothing > > > Both true, though I would say that they are the same case. > > i have not been able to find a way that it can be used in an expression > > > It is a module, not a function. > > [ Note: all of the stuff below is the same for render() and top-level F6. ] > > And i still feel that there is a conceptual bug here: > > render() sphere(); > > leaves the sphere as quads with n-sided polygons at north and south ends > > > OpenSCAD makes no particular promises about the details of its rendering. > It does not promise that everything will be reduced to triangles, and it > does not promise that it won’t, and whether or not a particular case is > reduced to triangles can depend on subtle factors. It would be entirely > with the specification (such as it is) for it to randomly do one or the > other. (We don’t like that answer for testability reasons, but it would be > legal.) > > So .. it should also do nothing for: > > render() { sphere(); sphere(); sphere(); } > > > It *cannot* do nothing there, because it *must* produce a single resulting > mesh that is geometrically legal (mostly, no self intersections). > > Whether in that process it reduces everything to triangles is an > implementation detail subject to change without notice or explanation. > > because if quads are good on the solo sphere why are quads no longer > acceptable when i try to draw 3 spheres ? > > > Quads would be completely acceptable there. But there are no promises, and > for its own reasons OpenSCAD (in Manifold mode) chooses to reduce them to > triangles. (Internally, this is because Manifold wants only triangles,) > > and please rem from my images that i was using translate to keep them from > intersecting so there are no intersections nor joints to fix up > > > There is no such thing. If there’s more than one input object it must do > all of the processing to figure out that there’s no overlap. And whether > or not there is overlap, it is required to produce a single geometrically > legal mesh as the output. (Note that a single mesh can have discontiguous > volumes.) > > Why are quads converted to triangles at all? > > > For specification purposes… because the program feels like it. There is > no promise one way or the other. > > The actual reason is that the geometry engine (Manifold) only processes > triangles. Maybe the next version of Manifold will process non-triangles > and it will no longer be necessary; we might then not do that conversion. > > The key thing to understand here is that you must not care, because the > behavior is unspecified and subject to change or variation without notice > or explanation. > > Related example: how many polygons does one invocation of cube() > generate? Six quads or twelve triangles are obvious answers, but seven, or > seven hundred, would be equally legal. You must not care; the only promise > is that when you assemble all of the polygons you end up with a rectangular > prism of the specified dimensions. It would even be legal for the answer to > be that it doesn’t generate polygons at all, that it stays as a “cube” > throughout the entire pipeline, until it needs to be exported to a form > that requires polygons. > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
V
vulcan_@mac.com
Fri, Aug 1, 2025 9:30 AM

well then, thank you all, esp Nop Head and JB .. i feel content and secure in my understanding of what render() is doing for us (wearing my User hat)

Nop Head and Jordan, my deepest thanks for patiently re-explaining your answers .. your filling in of blanks and coloring in the edges of the topic have allowed me to finally “get it”.

I can now revise the docs section on render() to accurately convey its use the the public at large

well then, thank you all, esp Nop Head and JB .. i feel content and secure in my understanding of what render() is doing for us (wearing my User hat) Nop Head and Jordan, my deepest thanks for patiently re-explaining your answers .. your filling in of blanks and coloring in the edges of the topic have allowed me to finally “get it”. I can now revise the docs section on render() to accurately convey its use the the public at large