mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 06:10:56 +00:00
207 lines
6.7 KiB
Python
207 lines
6.7 KiB
Python
|
# vim:ts=4:et
|
||
|
#
|
||
|
# Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||
|
# 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 #####
|
||
|
|
||
|
# <pep8 compliant>
|
||
|
|
||
|
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()
|