Loading

Rendering time slow, alternatives suggestions?

Please Login to Comment

I'm generating a maze. My code is at :

https://pastebin.com/rkdXVnGG

It's a 10x10x10 maze carved in a cube.
I hit F6 to render this morning, and when I'm back in the evening. It's only about half-way done.

OpenSCAD's rendering is incredible slow, if there's no way to speed it up, I'd like to find some alternative programs.
Any suggestions?

Another thing to try is to abandon your ball-cylinder-ball approach. Instead, lay out the paths with nothing but pencil thin cylinders that come together at the intersection points. Once everything is laid out, hit the whole thing with a minkowski with a sphere.

So I improved my code a bit, but nothing really different, and I published the source so you can toy with it.
I've reduced the $fn to 10 so I can render it in 30 minutes or so.

I'm satisfied with my result, and probably won't further explore the optimizations. I'd think it's the polygon count being too many for OpenSCAD.

Originally I thought that it's just some simple mathematical operation and that models with far many more polygons could be rendered, so why not for OpenSCAD? But now I think I might have been too optimistic.

Stop trying to help the guy. A few hours after his question he published a totally different, much more sophisticated and less hopeless code.
Seilgu, thanks for sharing that....

Sorry I read that wrong. I thought you were blaming me lol.

Comment has been deleted

Although Openscaddad and JustinSDK are totally right, it is doable with a lot of struggle. I used the attached scad-file with the zipped STL as result. It took somewhere between 30 and 90 minutes and as said, openscad was really struggling to end the rendering.

hull is helpful here because it reduces total (unnecessary) facets, compared to the original model. There is a trade-off between facets and rendering time, especially for programmable modeling tools.

I think that hull() increases the Preview(F5) time due to the cost of computing hulls?

It probably does, especially with large numbers like here. But you get the time back during rendering due to the smaller number of facets. A more specialized function which combine the ease of cylinder and spheres with less facets (union and translate) should probably pay off in this case.

How does that improve polygon count tho? If you check the polygon on the cylinder surface ( not from hull() ), it's made of very thin triangles stretched between the top and bottom. I don't see how any other way can reduce the polygon count. If the top and bottom circles has N edges, the cylinder would consists of 2N triangles. Any other vertices added would only increase the facets count, and I don't think hull() would violate this constraint.

Your model actually has many unnecessary facets, too.

I noticed that too when I posted that picture. It turns out there's a simple fix. Use $fn that are even numbers not divisible by 4. So in this case 18 or 22 instead of 20. It still takes way too long to render on my PC though.

EDIT: I just noticed op said he tried 10. That works too.

But surely doubles of odd numbers (like 10) will work in one direction but not the other, assuming you don't rotate() (and then you have 90s which would break it too). I would think what you would do is do multiples of 4 and then rotate() by 45.

Interesting. So it might actually be better to use fractional spheres and eliminate them where they aren't needed (straight-through paths) in any case.

My line3d module does it.

include <line3d.scad>;

line3d(
    p1 = [0, 0, 0], 
    p2 = [10, 2, 10], 
    thickness = 1, 
    p1Style = "CAP_SPHERE", 
    p2Style = "CAP_SPHERE",
    $fn = 24
);

The code uses some math, however, it's faster than hull.

It does not. I assumed that the, on first sight, simpler processing of union of a cylinder and two spheres was faster then the hull function with two spheres. And that the total rendering-time was lower that way. It isn't. It is the other way around, rendering with hull() is 25% faster. I did a little test with 10 "rounded rods". Union() took 15 seconds. Hull() took 11 seconds. Well never to old to learn.

@seilgu actually doesn't play to the strength of OpenSCAD. Generating a maze automatically will be the stage of OpenSCAD, such as Random maze and here's my some creations about mazes.

Using square or cube is faster. The attached source takes 5 mins on my computer.

The render time is mainly taken by rod and ball. Even you don't difference, it still takes long time. Here's a STL without difference. It takes almost 5 mins, too.

If this is going to be a blind maze where the ball goes in and you try to get it out the other side and you can't see the internals, why make them round? You could do square passages just fine.

10X10X10 seems a bit big too. I think that once you had one of these it would be far more complicated than you think. I would suggest you start smaller, make a few and then check the playability of the result.
.

Round seems easier to print, and nicer aesthetic.

It's not easier to print since it's more changes of direction in the horizontal plane and shallow overhangs in the vertical ones. Plus you have to deal with circle shrinkage. Using a triangle, square or diamond would mean less filament too. Aesthetic isn't going to make much difference for interior shapes.

Well, a triangle tube would be hard for a marble to roll, and the tubes has to be carefully connected. A square is not that good because of overhangs. However a round cylinder can support itself during printing.

It depends on how big the cylinder is and what overhang your printer can support. Any sag at all and you've lost some of your radius. This is why holes are sometimes printed with a pointed top.

Something else I'd recommend is to drop all those explicit module calls and stick your maze info into an array. Your code would be much more compact and manageable.

Also, you can probably drop the balls. Just have the ends of your rods fully overlap. It won't look as tidy but this is going to be inside an object anyway, right? If you're using a ball-bearing or something, you don't even need round rods. Just use cube(). You can make the entrance and exit round for appearance if you want. Or maybe even a triangle (or diamond). Then it's printable with no bridging or shallow overhangs.

That's a lot of rods and balls. Other people have probably offered better suggestions but I'm wondering if doing a union() on the rods & balls first would help.

Some suggestions:
-Don't blame a program if you don't know what you are doing.
-Don't use overcomplicated examples from the internet to draw a cylinder from A to B.
-Read and try the manual -> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual
-Use the parameters you are defining

Ok, less cranky:
It is simpler to use two spheres and a hull to draw a "rod" for example:

rad = 0.4;
$fn=20;

module rod(a, b)
{
hull()
{
translate(a)
sphere(r=rad);
translate(b)
sphere(r=rad);
}
};

rod([1,2,3],[4,5,6]);

Then first try to build the maze and then use difference with the cube.
Rendering will still take ages, but at least you have a code which is understandable.

"It is simpler to use two spheres and a hull to draw a "rod" for example:"

It's simpler but is it faster? I know I've used minkowsky before but it can bog things down over a less-elegant solution. My renders would take 5 minutes or more so I changed my workflow and generate the shapes I need before importing them now and have very short render times. (I should dig out some of that old stuff and benchmark it against offset() now that we have that).

Maybe not. The undoubtedly complicated hull-function is of course, as most predefined functions, not streamlined for a particular case. But according to Scruss the rendering-time of the "internals" seems acceptable. I think difference() with the cube is the bigger problem here and reducing the number of facets before difference creates the most time saving. But maybe I am wrong, I didn't try it.

Edit: Well I tried and it works more or less (see somewhere above). The biggest hurdle is indeed differnce().

Also, if you use @Coat's hull-based code for rod(), you can drop those 1000 or so calls to ball(). Setting $fn=8, I can render the maze internals in 2½ minutes (i7-4790K @ 4.00GHz). It looks like the Pompidou Centre and your lower intestine got together and had a baby ☺

If you are going to print this and expect anything to pass along those channels, follow the wisdom of nop head and make the channels slightly larger to allow for corner shrinkage: Polyholes

Try benchmarking simpler components. For instance, 1000 balls.

  1. You can build your "inverted" maze as single polyhedron - this will significantly improve rendering speeds because there will be just 2 objects - cube and "inverted" maze. However this won't be an easy job...

  2. Render "inverted" (without cube difference) maze - export it as STL and import back with cube difference.

The difference operation seems to be what is slowing things down. Maybe refactor the code so the rod and ball functions punch holes in a small cube. Basically generate all possible combinations of trivial 1x1x1 mazes (tiny cubes with an entry hole in one face and a exit in another), then assemble those into a larger maze. The paths that don't go straight through would need a ball in the middle. The reason that might work is that I think OpenSCAD is pretty good about caching intermediate results (i.e. the 1x1x1 mazes) and can efficiently assemble the final 10x10x10 while the original approach it has to deal with all the geometry in the 10x10x10 at once.

Even removing the difference() it took quite a while to do the render. This is an O(n^3) problem so even thought the final product only has 1000 cells, what you are asking the computer to do grows quite fast as the model gets larger. Consider a smaller maze when profiling different approaches, maybe 5x5x5?

Maybe try a smaller $fn. I'm not sure that's the entire problem though. If you look as the screen shot showing a zoom in of the "positive" path, you can see there are lots of extra facets from where the rods and balls intersect. It also looks like there might be some ball in the middle of straight tubes. I'd try eliminating those first. Also, the balls themselves don't line up with the rods near the "polls". Maybe rotate the balls so balls "pole" is normal to the direction the rods are turning.

That's all I got for now. It looks like an interesting problem. Good Luck!
Bob M

I tried playing with different $fn values and didn't see much improvement to those little facets I mentioned above. One trick that might help is to replace the sphere() functions with a rotate extrude on a half circle. That way you get more control on how the facets line up. Here's an example showing what I mean:

$fn=20;

translate ([4,0,0]) elbow2();
elbow1();

module elbow1() {
    rotate_extrude() difference() {
        circle(1);
        translate([0,-1,0]) square(2);
    }

    cylinder(2,1,1);
    rotate([90,0,0]) cylinder(2,1,1);
}

module elbow2() {
    sphere(1);

    cylinder(2,1,1);
    rotate([90,0,0]) cylinder(2,1,1);
}