I have a mixture of polygonal chains, quite dense. These chains represent mixture of polymers (~5000 chains). I want to render it photorealistic (without using VMD or similar special software) so they look like smooth curves. Chains are stored, for now, just as sequence of coordinates of the vertices. Is there a format which supports such data so I can import chains into blender? Or shall I convert every chain into concatenated cylinders? Do you know some tools which do it with smoothing the chain with splines?
-
2$\begingroup$ What format are those chains in? If it's something custom you will have to write your own importer. $\endgroup$– Jaroslav Jerryno NovotnyJan 27, 2016 at 12:10
-
$\begingroup$ I can write a converter to any standard open format, yet I don't know one which supports just lines (without polygons) $\endgroup$– Kirill LykovJan 27, 2016 at 16:39
2 Answers
You might just want to use python to convert the coordinates into a mesh. There are many examples on the internet. I'll include an excerpt from http://web.purplefrog.com/~thoth/blender/python-cookbook/triangle-donut.html because it has an accompanying narrative linked at the top:
import bpy
import math
def triangleDonut(name, nChunks, r1, r2, z1, z2):
verts=[]
faces = []
for i in range(2*nChunks):
# the first ring of vertices; we create them later in the loop
v1=i*3
v2 = v1+1
v3 = v1+2
# the second ring of vertices; these refer to vertices created next time
v4 = v1+3
v5 = v1+4
v6 = v1+5
if (i+1 >= 2*nChunks): # connect the end to the start
v4=0
v5=1
v6=2
# each ring is at a different angle from the center, eventually sweeping a full circle by the end of the loop
theta = i*math.pi/nChunks
if 0 == i%2:
z=z1
else:
z=z2
# basic triangle geometry here
c = math.cos(theta)
s = math.sin(theta)
# append the coordinates for v1..v3 to the verts list
verts.append( [r1*c, r1*s, 0] )
verts.append( [r2*c, r2*s, z] )
verts.append( [r2*c, r2*s, -z] )
# build faces that go from the freshly added vertices to the vertices we will add in the next loop
faces.append( [v1, v4, v5, v2] )
faces.append( [v2, v5, v6, v3] )
faces.append( [v3, v6, v4, v1] )
mesh = bpy.data.meshes.new(name);
mesh.from_pydata(verts, [], faces)
mesh.validate(True)
mesh.show_normal_face = True
obj = bpy.data.objects.new(name, mesh)
scn = bpy.context.scene
scn.objects.link(obj)
triangleDonut("donut", 20, 3, 2, 1,1.5)
There are many other examples at that site and around the internet. the from_pydata
method is probably a good search term, although it comes up with startlingly few results on stackexchange
If these vertices are just points on a curve, you could use python to fabricate a Bezier curve. I'll include an excerpt from http://web.purplefrog.com/~thoth/blender/python-cookbook/create-bezier.html
import bpy
name = "wiggle"
curve = bpy.data.curves.new(name, 'CURVE')
curve.dimensions = '3D'
# only if you need some non-zero Z coordinates
spline = curve.splines.new('BEZIER')
# options are 'POLY', 'BEZIER', 'BSPLINE', 'CARDINAL', 'NURBS'
# the spline starts off with a single point, we want one more.
spline.bezier_points.add(1)
b0 = spline.bezier_points[0]
b1 = spline.bezier_points[1]
b0.handle_left = (-2.5, -0.5, 0)
b0.co = (-2, 0, 0)
b0.handle_right = (-1, 1, 0)
b1.handle_left = (1, -1, 0)
b1.co = (2, 0, 0)
b1.handle_right = (2.5, 0.5, 0)
# curves data can have multiple unconnected curves
s2 = curve.splines.new('BEZIER')
# we want 3 = 1+2
s2.bezier_points.add(2)
b0 = s2.bezier_points[0]
b1 = s2.bezier_points[1]
b2 = s2.bezier_points[2]
b0.handle_left = (-0.5, 2.5, 1)
b0.co = (0, 2, 1)
b0.handle_right = (1, 1, 1)
b1.handle_left = (1, 1, 1)
b1.co = (0, 0, 1)
b1.handle_right = (-1, -1, 1)
b2.handle_left = (-1, -1, 1)
b2.co = (0, -2, 1)
b2.handle_right = (0.5, -2.5, 1)
#
s3 = curve.splines.new('BEZIER')
s3.bezier_points.add(1)
b0 = s3.bezier_points[0]
b1 = s3.bezier_points[1]
b0.handle_left = (-1, 1, -1)
b0.co = (0, 1, -1)
b0.handle_right = (1, 1, -1)
b1.handle_left = (1, -1, -1)
b1.co = (0, -1, -1)
b1.handle_right = (-1, -1, -1)
s3.use_cyclic_u = True
# forms a closed loop
#
#
ob = bpy.data.objects.new(name, curve)
scn = bpy.context.scene
scn.objects.link(ob)
ob.select = True
for i in range(len(curve.splines)):
spline = curve.splines[i]
print("spline[%d]" % i)
for j in range(len(spline.bezier_points)):
bp = spline.bezier_points[j]
print("bp[%d] = %s(%s , %s , %s)%s" % (j, bp.handle_left_type, bp.handle_left, bp.co, bp.handle_right, bp.handle_right_type))
Of course, that just gives you the central curve. You'll probably want to add a "Bevel Object", probably using a second bezier circle object as the bevel.
If you want them to be straight cylinders, go with a POLY instead of a BEZIER. If you do go with BEZIER, you'll have to figure out exactly what you want to do with the control points/handles (I'm partial to bp[i].co +- 0.3*(bp[i-1].co-bp[i+1].co)
)