nortikin / sverchok

Sverchok
http://nortikin.github.io/sverchok/
GNU General Public License v3.0
2.26k stars 234 forks source link

Nodes for 3d Printing features #542

Closed zeffii closed 9 years ago

zeffii commented 9 years ago

This is probably the right place for these things.

Seeing those Zoetrope sculptures on vimeo made me curious about how to manufacture them. In a back and forth between @enjalot and myself we hit one of the obvious effects of reality, gravity and heat. The printer's algorithm will happily deposit at elevation without proper support structures / scaffolding to hold the resin there.

https://www.youtube.com/watch?v=zUb3OIp0WkE (time laps of print and brief description by @enjalot)

original file: zoetrope b blend

A solution could be pillars the blend

But it might be neat to have a node to grow a support structure like a Tree with a

Time to look for a 3d printing handbook

portnov commented 9 years ago

Do you have a 3d printer? :)

zeffii commented 9 years ago

@portnov nope, but am interesting in 3d printing sculptures in general :D

enjalot commented 9 years ago

i have a 3d printer and will happily test/play with this. was excited to do the first print from @zeffii's blend file. it was super straightforward: select all, export as STL and boom! printing.

yanivg101 commented 9 years ago

I have 3D Printer too. If you export your model to STL you can see what will happen on the 3D Printer with Cura for example. https://software.ultimaker.com in this link you can also download netfabb to see if the file is printable etc.

BTW, you can make exelent support with Meshmixer, you can see how in this link: https://www.youtube.com/watch?v=aFTyTV3wwsE and also here: http://umforum.ultimaker.com/index.php?/topic/3880-meshmixer-20-a-better-way-to-generate-support

zeffii commented 9 years ago

Yeah, @yanivg101 I was going to write a node for that even before seeing that video earlier today, but it may be duplicated effort, but have meaning to find an excuse to write a Tree generator ..so.. maybe :)

yanivg101 commented 9 years ago

@zeffii , the real problem is to make the tree as closed mesh (boolean of the branches) so it can be 3D printable. If you can make just this solver as a node, it will be a big time saver for me on my cloth project that I trying to make "one button" node to make mesh into real wireframe that is: 1) without holes/inner faces. 2) low polygon count. (don't using remesh etc) 3) nice and clean mesh

Right now I'm using the "Pipe tube node", after getting the object (one object) on edit mode I select only the holes (with MeshLint -> Check Nonmanifold, The "close" option on the node dosn't work as I need) after that I separate the objects to get each pipe as one object. and join them again with boolean of the "BoolTool" addon. adding to the new object the balls on the joints (with BoolTool) and thats it.

In this method I get the 1 and 2 above but it isn't "nice and clean"...

zeffii commented 9 years ago

@yanivg101 I think we can solve the Tree mesh generation with a dedicated Skin Node, essentially a limited version of the BMeshViewer. It will have substantially less code because of its limited intended scope. The Tree geometry (verts+edges) creation would be done in a separate Node because there may be extra complexity in the construction of the Tree shape (obstacles, branching, supports for branched overhangs... a substantial list I think)

The final graph would be

TreeGen (Verts+Edges+Radii) => SkinNode (Bmesh+ (modifier: Skin + set radii from Radii))

I love to see pictures @yanivg101 I find them quite motivational and informative.

yanivg101 commented 9 years ago

OK, I already upload this setup but this is the results from my method above: image It's make good mesh that the 3D Slicer can slice good witout errors. image

zeffii commented 9 years ago

I sort of have a skin node working, but the performance is not exactly real-time. So i'm thinking it might be useful to include a button (operator) to reset the Skin Modifier on that Node. It might not even be very meaningful to have the modifier update its generated mesh on every micro mesh change.

zeffii commented 9 years ago

live_update

kind of works as expected, probably won't make sense until accompanied by a Tree structure node..which i'll work on today at some point

zeffii commented 9 years ago

As a side node, some of the uglier code in this node exists only because there seems to be a problem with data.skin_vertices when using bm.to_mesh(obj.data) or obj.data.from_pydata(). For the life of me I can't find a way to ensure that data.skin_vertices is generated by any other means than the convoluted code needed in this node. If it was up to me i'd still use our bmesh_from_pydata and then

bm.to_mesh(obj.data)
obj.data.ensure_skin_vertices()  # or something
zeffii commented 9 years ago

possibly auto add subsurf..

portnov commented 9 years ago

Yes, in some cases it can produce nice results with subsurf on top of Skin. And one more point: currently, if I apply Subsurf manually to created mesh, and then change radius in SkinViewer node, then sv_skin modifier moves to be last on stack. I think when node is re-applying skin modifier, it should remain on the same place in the stack.

zeffii commented 9 years ago

Yes, @portnov this node does its own crude modifier stack handling at the moment. Please don't expect it to behave nicely with user added modifiers yet (it's added complexity which i'm not interested in solving yet, tho can't imagine it would be difficult.. just my attention is elsewhere) .

zeffii commented 9 years ago

@portnov incidentally, the whole reason for removing the modifier at all is because of a possible bug (or unimplemented feature). Explained above. https://github.com/nortikin/sverchok/issues/542#issuecomment-71190533 I hope to make a demo script to file a report soon. with any luck the result will mean the modifier stack can be used more liberally without my intervention. :)

zeffii commented 7 years ago

so.. @nortikin : @yanivg101 helped danit Peleg do the 3d dresses in 2015 ?

nortikin commented 7 years ago

yes, but only this thing in image. i hope we can work, i writed this month to Dani Peleg and her new proger. You watched them in blendconf2016. Sent them some pieces, but not exact propositions.

yanivg101 commented 7 years ago

Hi, What I really want to do is this: http://n-e-r-v-o-u-s.com/projects/sets/kinematics

later I found a better way to to the example above without a need to use boolean nor Sverchok. simply use Skin modifier: base with skin modifier

zeffii commented 7 years ago

yeah, the kinematics stuff is superb :)

nortikin commented 7 years ago

no need for serchok sometimes. i think we can propose vertex stripes node for experimenting for some cases

zeffii commented 7 years ago

i think the Kinematics dress is a limited case of an adaptive faces node, limit to Triangles only, and donor shape has features (hinges) which don't scale in relation to the polygon size of the recipient. The donor shape would be parametric :)

yanivg101 commented 7 years ago

I can get the middle of the edge between two faces but can't get the right normals that is the average between the two, if there is a way to spread mesh on this point and get the exact rotation of the point according the normal I can use particles to make the hinges.

zeffii commented 7 years ago

yeah, I don't think we provide any edge normal socket. it's a simple but slow process. bmesh does provide a quick lookup per edge to find which faces are attached to it.

zeffii commented 7 years ago

@yanivg101 edge normals for snlite node.

"""
in verts v d=[[]] n=1
in faces s d=[[]] n=1
in resize s d=1.0 n=2
out normals v
out midpoints v
"""

import bpy

from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata

def normalize(v):
    l = math.sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]))
    return [v[0]/l, v[1]/l, v[2]/l]

normals = [[]]
midpoints = [[]]
add_normal = normals[0].append
add_midpoint = midpoints[0].append

if verts and faces:

    bm = bmesh_from_pydata(verts, [], faces)
    bm.verts.index_update()

    for e in bm.edges:
        faces = e.link_faces
        if faces:
            x = 0
            y = 0
            z = 0
            for i in faces:
                i.normal_update()
                x += i.normal.x
                y += i.normal.y
                z += i.normal.z

            avg_normal = [x*resize,y*resize,z*resize]
            add_normal(avg_normal)

        v1, v2 = e.verts
        avg_vert = (v1.co + v2.co) / 2
        add_midpoint(avg_vert[:])

image

https://gist.github.com/c6927b4df73f0dcf68c4dc71d2abb383

zeffii commented 7 years ago

warning btw, I don't think the indices of the edges that come directly from Sphere, will match with the order in which the normals/edge midpoints are outputted from the snlite-bmesh code . Means you probably want to output bm.verts and bm.faces from that node too

nortikin commented 7 years ago

not matching, but hacky way - sort if midedge equal midedge maybe with dictionary invlved, again snlight

nortikin commented 7 years ago

interesting case of cube generator with subdivs - making nice lines ))

yanivg101 commented 7 years ago

can you try with Suzzane with or without triangulation?, I need an example of more complex mesh.

zeffii commented 7 years ago

@nortikin yeah, the 'unstable' bm.edge/face indexing is ok for most things that don't care about order, but .. often we do care :)

ok @yanivg101 , just import suzanne on object_in

zeffii commented 7 years ago

suzanne btw, has many quads that are distorted, the result of the edge normals will be partially broken..

zeffii commented 7 years ago

i'll have time lateron to dig deeper

yanivg101 commented 7 years ago

OK, I will try. I have another idea that I wish to accomplish: there is an addon that can import gcode into bunch of curves. what I want is the reverse... an addon or Sverchok node the can take a curve and put gcode for it. take each point of the curve and make one gcode command for it. for the extrude I wish to convert the radius of each point of the curve to the material amount.

all 3d printers can only print flat layer by flat layer, with this tool you can do visually layers that are not flat, you can add noise right into the gcode and do something like this: gcode with noise

zeffii commented 7 years ago

it's been a while since i wrote G-code :D

zeffii commented 7 years ago

i fixed the previous gist (check again)

zeffii commented 7 years ago

with normalize and resize : )

"""
in verts v d=[[]] n=1
in faces s d=[[]] n=1
in resize s d=1.0 n=2
out normals v
out midpoints v
"""

import bpy
import math

from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata

normals = [[]]
midpoints = [[]]
add_normal = normals[0].append
add_midpoint = midpoints[0].append

if verts and faces:

    bm = bmesh_from_pydata(verts, [], faces)
    bm.verts.index_update()

    for e in bm.edges:
        faces = e.link_faces
        if faces:
            x = 0
            y = 0
            z = 0
            for i in faces:
                i.normal_update()
                x += i.normal.x
                y += i.normal.y
                z += i.normal.z

            # normalize, and resize from there..
            v = [x, y, z]
            l = math.sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]))
            avg_normal = [v[0]/l*resize, v[1]/l*resize, v[2]/l*resize]

            add_normal(avg_normal)

        v1, v2 = e.verts
        avg_vert = (v1.co + v2.co) / 2
        add_midpoint(avg_vert[:])
nortikin commented 7 years ago

i think, the real problem is we put not edges, but polygons. and it makes order as it want. so we need edges to output too from bmesh

nortikin commented 7 years ago
"""
in verts v d=[[]] n=1
in faces s d=[[]] n=1
in resize s d=1.0 n=2
out normals v
out midpoints v
out vers v
out edges s
"""

import bpy
import math

from sverchok.utils.sv_bmesh_utils import bmesh_from_pydata

normals = [[]]
midpoints = [[]]
edges = [[]]
vers = [[]]
add_normal = normals[0].append
add_midpoint = midpoints[0].append
add_vers = vers[0].append
add_edges = edges[0].append

if verts and faces:

    bm = bmesh_from_pydata(verts, [], faces)
    bm.verts.index_update()
    bm.verts.ensure_lookup_table()

    add_vers([v.co[:] for v in bm.verts])
    for e in bm.edges:
        faces = e.link_faces
        add_edges([i.index for i in e.verts])
        if faces:
            x = 0
            y = 0
            z = 0
            for i in faces:
                i.normal_update()
                x += i.normal.x
                y += i.normal.y
                z += i.normal.z

            # normalize, and resize from there..
            v = [x, y, z]
            l = math.sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]))
            avg_normal = [v[0]/l*resize, v[1]/l*resize, v[2]/l*resize]
            add_normal(avg_normal)

        v1, v2 = e.verts
        avg_vert = (v1.co + v2.co) / 2
        add_midpoint(avg_vert[:])
nortikin commented 7 years ago

https://gist.github.com/baebed9417908a3027f4b7da117f1c6f the problem now is why edges x2 count?

zeffii commented 7 years ago

hmm, i think snlite has an unrelated bug... it freezes for reasons not yet known to me.. smells like infinite loop

zeffii commented 7 years ago

@nortikin regarding extra edges,, see https://gist.github.com/3f2068bd472784c56d43fbfd5a8e58c4

I don't think there's double edges from the bm.edges, so it must be correct to *2