こんにちは,
I’m n- also known as A-na5.
I’ve been using Blender for several years. recent works are making 3D models based on mathematical expressions. However, I’ve just started studying Blender – Python API (https://docs.blender.org/api/) since last month. Please let me know if there are any mistakes.
Inspiration and References
A new 3-d four-wing smooth autonomous chaotic systems
Modeling
How To Make “A 3-D Four-Wing Attractor” with Blender in Python
import bpy
import platform
print("Blender " + bpy.app.version_string)
print("Python " + platform.python_version())
# Blender 2.77 (sub 3)
# Python 3.5.1
Setting
Choose Screen Layout > Scripting
Window > Toggle System Console
Create a new text data block
Creating curve with chaotic attractors
import bpy def wang_sun(a, b, c, d, e, f): return lambda x, y, z: ( a*x + c*y*z, b*x + d*y - x*z, e*z + f*x*y ) def make_components(func, max_iteration, x=0, y=0, z=0, dt=0.1): verts = [] edges = [] faces = [] i = 0 while i < max_iteration: xn, yn, zn = func(x, y, z) x = x + xn*dt y = y + yn*dt z = z + zn*dt verts.append((x, y, z)) i = i + 1 return verts, edges, faces def generate_curve(func, max_iteration, curve_name, *start_xyz): verts, edges, faces = make_components(func, max_iteration, *start_xyz) w = 1 curvedata = bpy.data.curves.new(name=curve_name, type='CURVE') curvedata.dimensions = '3D' obj = bpy.data.objects.new(curve_name, curvedata) obj.location = (0, 0, 0) bpy.context.scene.objects.link(obj) polyline = curvedata.splines.new('POLY') polyline.points.add(len(verts)-1) for num in range(len(verts)): polyline.points[num].co = (verts[num])+(w,) obj.select = True obj.show_bounds = True wang_sun_params = (("a", 0.2), ("b", -0.01), ("c", 1.0), ("d", -0.4), ("e", -1.0), ("f", -1.0)) wang_sun_start = (0.15, 0.1 , 0.2, 0.05) n = 20000 name = "wang-sun" param = (v for k,v in wang_sun_params) attract = wang_sun(*param) generate_curve(attract, n, name, *wang_sun_start)
Run
Resizing Objects
import bpy def resize_objects(objects_name, *, axis="z", size=10): obj = bpy.data.objects[objects_name] bpy.context.scene.update() obj.select = True bpy.context.scene.objects.active = obj bo = bpy.context.object dimX = bo.dimensions[0] dimY = bo.dimensions[1] dimZ = bo.dimensions[2] if axis == "x": s = size/dimX elif axis == "y": s = size/dimY else: s = size/dimZ bo.scale[0] = 1*s bo.scale[1] = 1*s bo.scale[2] = 1*s bpy.ops.object.transform_apply( location=False, rotation=False, scale=True ) name = "wang-sun" s = 10 resize_objects(name, axis="z", size=s)
Run
Curve to mesh
import bpy def mesh_from_curve(curve_name, *, fill_mode='BACK', bevel_depth=0.05): obj = bpy.data.objects[curve_name] bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.context.scene.objects.active = obj bo = bpy.context.object bo.data.fill_mode = fill_mode bo.data.bevel_depth = bevel_depth bpy.ops.object.shade_flat() bpy.ops.object.convert(target='MESH') obj.data.name = curve_name name = "wang-sun" mesh_from_curve(name, fill_mode='BACK', bevel_depth=0.05)
Run
Duplicate
import bpy import bmesh def duplicate_checker_select(mesh_name, *, nth=3): for offset in range(nth): bpy.ops.object.select_all(action='DESELECT') obj = bpy.data.objects[mesh_name] scn = bpy.context.scene obj.select = True scn.objects.active = obj bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_mode(type="FACE") bpy.ops.mesh.select_all(action='DESELECT') me = obj.data bm = bmesh.from_edit_mesh(me) bm.faces.ensure_lookup_table() index_offset = 0 for faces in bm.faces: index_offset = faces.index + offset if faces.index % nth == 0: index_select = index_offset if index_offset < len(me.polygons) else index_offset - len(me.polygons) bm.faces[index_select].select = True bmesh.update_edit_mesh(me, True) bpy.ops.mesh.duplicate() bpy.ops.mesh.separate(type='SELECTED') bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.context.scene.objects.active = obj bpy.ops.object.delete(use_global=False) name = "wang-sun" duplicate_checker_select(name, nth=10)
Run
Export to sketchfab.timeframe
import bpy import os def export_txt_sketchfab_timeframe(path, sec): if os.path.isdir(path) is False: # os.makedirs(path) print("'path' is missing") return 0 bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_by_type(type='MESH') objList = [obj.name for obj in bpy.context.selected_objects] objList = sorted(objList) timeframe = open(path + 'sketchfab.timeframe', 'w') with timeframe as text: for objects in objList: text.write(sec + " " + objects + ".ply" + "\n") bpy.ops.object.select_all(action='DESELECT') print("writing " + path + "sketchfab.timeframe done") # "~/Desktop/attractor/Wang-Sun/" # "/Users/your-name/Desktop/attractor/Wang-Sun/" # "C:/Users/your-name/Desktop/attractor/Wang-Sun/" sec = "0.1" path = "/path/to/" export_txt_sketchfab_timeframe(path, sec) # print(os.makedirs.__doc__) """ Recursive directory creation function. Like mkdir(), but makes all intermediate-level directories needed to contain the leaf directory.
Run
Creating Wire-Frame Models
# bevel = 0.05 bevel = 0.01 n = 20000 name = "wang-sun" param = (v for k,v in wang_sun_params) # 2) Run attract = wang_sun(*param) generate_curve(attract, n, name, *wang_sun_start) # 3) Run resize_objects(name) # 4) Run mesh_from_curve(name, bevel_depth=bevel)
Run
Adding objects to sketchfab.timeframe
import bpy import os def append_objects_to_sketchfab_timeframe(path, objects_name): if os.path.isdir(path) is False: # os.makedirs(path) print("'path' is missing") return 0 obj = bpy.data.objects[objects_name] bpy.ops.object.select_all(action='DESELECT') obj.select = True timeframe = open(path + 'sketchfab.timeframe', 'r') lines = timeframe.readlines() timeframe.close() timeframe = open(path + 'sketchfab.timeframe', 'w') with timeframe as text: for line in lines: text.write(line.strip() + "+" + obj.name + ".ply" + "\n") print("writing " + line.strip() + "+" + obj.name + ".ply") # "~/Desktop/attractor/Wang-Sun/" # "/Users/your-name/Desktop/attractor/Wang-Sun/" # "C:/Users/your-name/Desktop/attractor/Wang-Sun/" path = "/path/to/" name = "wang-sun" append_objects_to_sketchfab_timeframe(path, name)
Run
Export to .ply
import bpy import os def export_ply_all(path): if os.path.isdir(path) is False: # os.makedirs(path) print("'path' is missing") return 0 bpy.ops.object.select_all(action='DESELECT') bpy.ops.object.select_by_type(type='MESH') objList = [obj.name for obj in bpy.context.selected_objects] objList = sorted(objList) for objects in objList: obj = bpy.data.objects[objects] _objects = objects.replace('.', '_') bpy.ops.object.select_all(action='DESELECT') obj.select=True bpy.context.scene.objects.active = obj obj.data.name = _objects bpy.context.active_object.name = _objects bpy.ops.export_mesh.ply( filepath=path+_objects+".ply", check_existing=True, axis_forward='Y', axis_up='Z', filter_glob="*.ply", use_mesh_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True, global_scale=1.0 ) # "~/Desktop/attractor/test/" # "/Users/your-name/Desktop/attractor/test/" # "C:/Users/your-name/Desktop/attractor/test/" path = "/path/to/" export_ply_all(path)
Run
Rendering of the Sketchfab is beautiful than my own rendering image…, that is easy to use for beginner 3D artist. It is the most attractive thing to me. Thank you for give me a place to publish my work.
I’d like to thank the Sketchfab Team & Community!
Find me on: