# vim:ts=4:et # # Copyright (C) 2012 Bill Currie # Date: 2012/2/20 # # ##### BEGIN GPL LICENSE BLOCK ##### # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # ##### END GPL LICENSE BLOCK ##### # bl_info = { "name": "Strut Generator", "author": "Bill Currie", "blender": (2, 6, 2), "api": 35622, "location": "View3D > Add > Mesh > Struts", "description": "Add struts meshes based on selected truss meshes", "warning": "can get very high-poly", "wiki_url": "", "tracker_url": "", "category": "Add Mesh"} import bpy from bpy.props import FloatProperty,IntProperty,BoolProperty from mathutils import Vector,Matrix from math import pi, cos, sin cossin = [] def build_cossin(n): global cossin cossin = [] for i in range(n): a = 2 * pi * i / n cossin.append((cos(a), sin(a))) def make_strut(v1, v2, id, od, n, solid, loops): v1 = Vector(v1) v2 = Vector(v2) axis = v2 - v1 pos = [(0, od / 2)] if loops: pos += [((od - id) / 2, od / 2), (axis.length - (od - id) / 2, od / 2)] pos += [(axis.length, od / 2)] if solid: pos += [(axis.length, id / 2)] if loops: pos += [(axis.length - (od - id) / 2, id / 2), ((od - id) / 2, id / 2)] pos += [(0, id / 2)] vps = len(pos) fps = vps if not solid: fps -= 1 fw = axis.copy() fw.normalize() if (abs(axis[0] / axis.length) < 1e-5 and abs(axis[1] / axis.length) < 1e-5): up = Vector((-1, 0, 0)) else: up = Vector((0, 0, 1)) lf = up.cross(fw) lf.normalize() up = fw.cross(lf) mat = Matrix((fw, lf, up)) mat.transpose() verts = [None] * n * vps faces = [None] * n * fps for i in range(n): base = (i - 1) * vps x = cossin[i][0] y = cossin[i][1] for j in range(vps): p = Vector((pos[j][0], pos[j][1] * x, pos[j][1] * y)) p = mat * p verts[i * vps + j] = p + v1 if i: for j in range(fps): f = (i - 1) * fps + j faces[f] = [base + j, base + vps + j, base + vps + (j + 1) % vps, base + (j + 1) % vps] base = len(verts) - vps i = n for j in range(fps): f = (i - 1) * fps + j faces[f] = [base + j, j, (j + 1) % vps, base + (j + 1) % vps] #print(verts,faces) return verts, faces def create_struts(self, context, id, od, segments, solid, loops): build_cossin(segments) vps = 2 if solid: vps *= 2 if loops: vps *= 2 fps = vps if not solid: fps -= 1 bpy.context.user_preferences.edit.use_global_undo = False for truss_obj in bpy.context.scene.objects: if not truss_obj.select: continue truss_obj.select = False truss_mesh = truss_obj.to_mesh(context.scene, True, 'PREVIEW') if not truss_mesh.edges: continue mesh = bpy.data.meshes.new("Struts") verts = [None] * len(truss_mesh.edges) * segments * vps faces = [None] * len(truss_mesh.edges) * segments * fps vbase = 0 fbase = 0 for e in truss_mesh.edges: v1 = truss_mesh.vertices[e.vertices[0]] v2 = truss_mesh.vertices[e.vertices[1]] v, f = make_strut(v1.co, v2.co, id, od, segments, solid, loops) for fv in f: for i in range(len(fv)): fv[i] += vbase for i in range(len(v)): verts[vbase + i] = v[i] for i in range(len(f)): faces[fbase + i] = f[i] #if not base % 12800: # print (base * 100 / len(verts)) vbase += vps * segments fbase += fps * segments #print(verts,faces) mesh.from_pydata(verts, [], faces) obj = bpy.data.objects.new("Struts", mesh) bpy.context.scene.objects.link(obj) obj.select = True obj.location = truss_obj.location bpy.context.scene.objects.active = obj mesh.update() bpy.context.user_preferences.edit.use_global_undo = True return {'FINISHED'} class Struts(bpy.types.Operator): """Add one or more struts meshes based on selected truss meshes""" bl_idname = "mesh.generate_struts" bl_label = "Struts" bl_description = """Add one or more struts meshes based on selected truss meshes""" bl_options = {'REGISTER', 'UNDO'} id = FloatProperty(name = "Inside Diameter", description = "diameter of inner surface", min = 0.0, soft_min = 0.0, max = 100, soft_max = 100, default = 0.04) od = FloatProperty(name = "Outside Diameter", description = "diameter of outer surface", min = 0.01, soft_min = 0.01, max = 100, soft_max = 100, default = 0.05) solid = BoolProperty(name="Solid", description="Create inner surface.", default=True) loops = BoolProperty(name="Loops", description="Create sub-surf friendly loops.", default=False) segments = IntProperty(name="Segments", description="Number of segments around strut", min=3, soft_min=3, max=64, soft_max=64, default=32) def execute(self, context): keywords = self.as_keywords () return create_struts(self, context, **keywords) def menu_func(self, context): self.layout.operator(Struts.bl_idname, text = "Struts", icon='PLUGIN') def register(): bpy.utils.register_module(__name__) bpy.types.INFO_MT_mesh_add.append(menu_func) def unregister(): bpy.utils.unregister_module(__name__) if __name__ == "__main__": register()