add_extra_mesh_objects: new version
Tracker: https://developer.blender.org/T44561 New UI, New Addons, Better organization & removal of 'Lesser Object Types' Merged & removed "lesser" & 'larger" add mesh scripts. Menu updates & re-organization & modernize. New: Add Vert, Round Cube, Menger Cube, Brilliant Diamond, Parent to Empty Removed: Add Mesh: Sqorus, Trapezohedron, Wedge, Polysphere. Merged add_mesh_symmetrical_empty from contrib Documentation: http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Add_Mesh/Add_Mesh_Extra_Objects
This commit is contained in:
parent
3b6028fd8b
commit
40c00d312f
Notes:
blender-bot
2023-02-14 19:56:31 +01:00
Referenced by issue #44561, add_mesh_extra_objects new version
|
@ -16,13 +16,13 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
# Contributed to by
|
||||
# Pontiac, Fourmadmen, varkenvarken, tuga3d, meta-androcto, metalliandy, dreampainter & cotejrp1#
|
||||
# Pontiac, Fourmadmen, varkenvarken, tuga3d, meta-androcto, metalliandy, dreampainter, cotejrp1#
|
||||
|
||||
bl_info = {
|
||||
"name": "Extra Objects",
|
||||
"author": "Multiple Authors",
|
||||
"version": (0, 3, 0),
|
||||
"blender": (2, 72, 0),
|
||||
"blender": (2, 74, 0),
|
||||
"location": "View3D > Add > Mesh",
|
||||
"description": "Add extra mesh object types",
|
||||
"warning": "",
|
||||
|
@ -33,12 +33,12 @@ bl_info = {
|
|||
|
||||
if "bpy" in locals():
|
||||
import importlib
|
||||
importlib.reload(add_mesh_extra_objects)
|
||||
importlib.reload(add_mesh_star)
|
||||
importlib.reload(add_mesh_twisted_torus)
|
||||
importlib.reload(add_mesh_gemstones)
|
||||
importlib.reload(add_mesh_gears)
|
||||
importlib.reload(add_mesh_3d_function_surface)
|
||||
importlib.reload(add_mesh_polysphere)
|
||||
importlib.reload(add_mesh_round_cube)
|
||||
importlib.reload(add_mesh_supertoroid)
|
||||
importlib.reload(add_mesh_pyramid)
|
||||
importlib.reload(add_mesh_torusknot)
|
||||
|
@ -46,14 +46,17 @@ if "bpy" in locals():
|
|||
importlib.reload(add_mesh_teapot)
|
||||
importlib.reload(add_mesh_pipe_joint)
|
||||
importlib.reload(add_mesh_solid)
|
||||
|
||||
importlib.reload(add_mesh_round_brilliant)
|
||||
importlib.reload(add_mesh_menger_sponge)
|
||||
importlib.reload(add_mesh_vertex)
|
||||
importlib.reload(add_empty_as_parent)
|
||||
else:
|
||||
from . import add_mesh_extra_objects
|
||||
from . import add_mesh_star
|
||||
from . import add_mesh_twisted_torus
|
||||
from . import add_mesh_gemstones
|
||||
from . import add_mesh_gears
|
||||
from . import add_mesh_3d_function_surface
|
||||
from . import add_mesh_polysphere
|
||||
from . import add_mesh_round_cube
|
||||
from . import add_mesh_supertoroid
|
||||
from . import add_mesh_pyramid
|
||||
from . import add_mesh_torusknot
|
||||
|
@ -61,9 +64,33 @@ else:
|
|||
from . import add_mesh_teapot
|
||||
from . import add_mesh_pipe_joint
|
||||
from . import add_mesh_solid
|
||||
from . import add_mesh_round_brilliant
|
||||
from . import add_mesh_menger_sponge
|
||||
from . import add_mesh_vertex
|
||||
from . import add_empty_as_parent
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class INFO_MT_mesh_vert_add(bpy.types.Menu):
|
||||
# Define the "Pipe Joints" menu
|
||||
bl_idname = "INFO_MT_mesh_vert_add"
|
||||
bl_label = "Single Vert"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("mesh.primitive_vert_add",
|
||||
text="Add Single Vert ")
|
||||
layout.operator("mesh.primitive_emptyvert_add",
|
||||
text="Object Origin Only")
|
||||
layout.operator("mesh.primitive_symmetrical_vert_add",
|
||||
text="Origin & Vert Mirrored")
|
||||
layout.operator("mesh.primitive_symmetrical_empty_add",
|
||||
text="Object Origin Mirrored")
|
||||
|
||||
|
||||
class INFO_MT_mesh_gears_add(bpy.types.Menu):
|
||||
# Define the "Gears" menu
|
||||
bl_idname = "INFO_MT_mesh_gears_add"
|
||||
|
@ -77,6 +104,23 @@ class INFO_MT_mesh_gears_add(bpy.types.Menu):
|
|||
layout.operator("mesh.primitive_worm_gear",
|
||||
text="Worm")
|
||||
|
||||
|
||||
class INFO_MT_mesh_diamonds_add(bpy.types.Menu):
|
||||
# Define the "Gears" menu
|
||||
bl_idname = "INFO_MT_mesh_diamonds_add"
|
||||
bl_label = "Diamonds"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("mesh.primitive_brilliant_add",
|
||||
text="Brilliant Diamond")
|
||||
layout.operator("mesh.primitive_diamond_add",
|
||||
text="Diamond")
|
||||
layout.operator("mesh.primitive_gem_add",
|
||||
text="Gem")
|
||||
|
||||
|
||||
class INFO_MT_mesh_math_add(bpy.types.Menu):
|
||||
# Define the "Math Function" menu
|
||||
bl_idname = "INFO_MT_mesh_math_add"
|
||||
|
@ -89,27 +133,29 @@ class INFO_MT_mesh_math_add(bpy.types.Menu):
|
|||
text="Z Math Surface")
|
||||
layout.operator("mesh.primitive_xyz_function_surface",
|
||||
text="XYZ Math Surface")
|
||||
self.layout.operator("mesh.primitive_solid_add", text="Solid")
|
||||
self.layout.operator("mesh.primitive_solid_add", text="Regular Solid")
|
||||
|
||||
class INFO_MT_mesh_basic_add(bpy.types.Menu):
|
||||
|
||||
class INFO_MT_mesh_extras_add(bpy.types.Menu):
|
||||
# Define the "Simple Objects" menu
|
||||
bl_idname = "INFO_MT_mesh_basic_add"
|
||||
bl_label = "Simple Objects"
|
||||
bl_idname = "INFO_MT_mesh_extras_add"
|
||||
bl_label = "Extras"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("mesh.primitive_diamond_add",
|
||||
text="Diamond")
|
||||
layout.operator("mesh.primitive_gem_add",
|
||||
text="Gem")
|
||||
layout.operator("mesh.primitive_sqorus_add",
|
||||
text="Sqorus")
|
||||
layout.operator("mesh.primitive_wedge_add")
|
||||
layout.menu("INFO_MT_mesh_diamonds_add", text="Diamonds", icon="PMARKER_SEL")
|
||||
layout.operator("mesh.primitive_star_add",
|
||||
text="Star")
|
||||
layout.operator("mesh.primitive_trapezohedron_add",
|
||||
text="Trapezohedron")
|
||||
text="Simple Star")
|
||||
layout.operator("mesh.primitive_steppyramid_add",
|
||||
text="Step Pyramid")
|
||||
layout.operator("mesh.honeycomb_add",
|
||||
text="Honeycomb")
|
||||
layout.operator("mesh.primitive_teapot_add",
|
||||
text="Teapot+")
|
||||
layout.operator("mesh.menger_sponge_add",
|
||||
text="Menger Sponge")
|
||||
|
||||
|
||||
class INFO_MT_mesh_torus_add(bpy.types.Menu):
|
||||
# Define the "Simple Objects" menu
|
||||
|
@ -126,20 +172,6 @@ class INFO_MT_mesh_torus_add(bpy.types.Menu):
|
|||
layout.operator("mesh.primitive_torusknot_add",
|
||||
text="Torus Knot")
|
||||
|
||||
class INFO_MT_mesh_misc_add(bpy.types.Menu):
|
||||
# Define the "Simple Objects" menu
|
||||
bl_idname = "INFO_MT_mesh_misc_add"
|
||||
bl_label = "Misc Objects"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator("mesh.primitive_steppyramid_add",
|
||||
text="Step Pyramid")
|
||||
layout.operator("mesh.honeycomb_add",
|
||||
text="Honeycomb")
|
||||
layout.operator("mesh.primitive_teapot_add",
|
||||
text="Teapot+")
|
||||
|
||||
class INFO_MT_mesh_pipe_joints_add(bpy.types.Menu):
|
||||
# Define the "Pipe Joints" menu
|
||||
|
@ -160,17 +192,22 @@ class INFO_MT_mesh_pipe_joints_add(bpy.types.Menu):
|
|||
layout.operator("mesh.primitive_n_joint_add",
|
||||
text="Pipe N-Joint")
|
||||
|
||||
|
||||
# Register all operators and panels
|
||||
|
||||
# Define "Extras" menu
|
||||
def menu_func(self, context):
|
||||
self.layout.operator("mesh.primitive_polysphere_add", text="Polysphere")
|
||||
self.layout.menu("INFO_MT_mesh_pipe_joints_add", text="Pipe Joints")
|
||||
self.layout.menu("INFO_MT_mesh_gears_add", text="Gears")
|
||||
self.layout.menu("INFO_MT_mesh_math_add", text="Math Function")
|
||||
self.layout.menu("INFO_MT_mesh_torus_add", text="Torus Objects")
|
||||
self.layout.menu("INFO_MT_mesh_basic_add", text="Basic Objects")
|
||||
self.layout.menu("INFO_MT_mesh_misc_add", text="Misc Objects")
|
||||
self.layout.separator()
|
||||
self.layout.menu("INFO_MT_mesh_vert_add", text="Single Vert", icon="LAYER_ACTIVE")
|
||||
self.layout.menu("INFO_MT_mesh_round_cube_add", text="Round Cube", icon="WIRE")
|
||||
self.layout.menu("INFO_MT_mesh_math_add", text="Math Function", icon="PACKAGE")
|
||||
self.layout.menu("INFO_MT_mesh_pipe_joints_add", text="Pipe Joints", icon="SNAP_PEEL_OBJECT")
|
||||
self.layout.menu("INFO_MT_mesh_gears_add", text="Gears", icon="SCRIPTWIN")
|
||||
self.layout.menu("INFO_MT_mesh_torus_add", text="Torus Objects", icon="MESH_TORUS")
|
||||
self.layout.menu("INFO_MT_mesh_extras_add", text="Extras", icon="MESH_DATA")
|
||||
self.layout.separator()
|
||||
self.layout.operator("object.parent_to_empty", text="Parent To Empty", icon="LINK_AREA")
|
||||
self.layout.separator()
|
||||
|
||||
|
||||
def register():
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
# GPL # Original Author Liero #
|
||||
|
||||
import bpy
|
||||
from bpy.props import StringProperty, FloatProperty, BoolProperty, FloatVectorProperty
|
||||
|
||||
def centro(objetos):
|
||||
x = sum([obj.location[0] for obj in objetos])/len(objetos)
|
||||
y = sum([obj.location[1] for obj in objetos])/len(objetos)
|
||||
z = sum([obj.location[2] for obj in objetos])/len(objetos)
|
||||
return (x,y,z)
|
||||
|
||||
class P2E(bpy.types.Operator):
|
||||
bl_idname = 'object.parent_to_empty'
|
||||
bl_label = 'Parent Selected to Empty'
|
||||
bl_description = 'Parent selected objects to a new Empty'
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
nombre = StringProperty(name='', default='OBJECTS', description='Give the empty / group a name')
|
||||
grupo = bpy.props.BoolProperty(name='Create Group', default=False, description='Also link objects to a new group')
|
||||
cursor = bpy.props.BoolProperty(name='Cursor Location', default=False, description='Add the empty at cursor / selection center')
|
||||
renombrar = bpy.props.BoolProperty(name='Rename Objects', default=False, description='Rename child objects')
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.object and context.object.select)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.prop(self,'nombre')
|
||||
column = layout.column(align=True)
|
||||
column.prop(self,'grupo')
|
||||
column.prop(self,'cursor')
|
||||
column.prop(self,'renombrar')
|
||||
|
||||
def execute(self, context):
|
||||
objs = bpy.context.selected_objects
|
||||
bpy.ops.object.mode_set()
|
||||
if self.cursor:
|
||||
loc = context.scene.cursor_location
|
||||
else:
|
||||
loc = centro(objs)
|
||||
bpy.ops.object.add(type='EMPTY',location=loc)
|
||||
bpy.context.object.name = self.nombre
|
||||
if self.grupo:
|
||||
bpy.ops.group.create(name=self.nombre)
|
||||
bpy.ops.group.objects_add_active()
|
||||
for o in objs:
|
||||
o.select = True
|
||||
if not o.parent:
|
||||
bpy.ops.object.parent_set(type='OBJECT')
|
||||
if self.grupo:
|
||||
bpy.ops.group.objects_add_active()
|
||||
o.select = False
|
||||
for o in objs:
|
||||
if self.renombrar:
|
||||
o.name = self.nombre+'_'+o.name
|
||||
return {'FINISHED'}
|
|
@ -1,25 +1,4 @@
|
|||
# ##### 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 #####
|
||||
'''
|
||||
"name": "3D Function Surfaces",
|
||||
"author": "Buerbaum Martin (Pontiac), Elod Csirmaz",
|
||||
"version": (0, 3, 8),
|
||||
'''
|
||||
# GPL # original by Buerbaum Martin (Pontiac), Elod Csirmaz
|
||||
|
||||
import bpy
|
||||
from mathutils import *
|
||||
|
@ -66,18 +45,7 @@ def create_mesh_object(context, verts, edges, faces, name):
|
|||
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
# Connects two equally long vertex rows with faces.
|
||||
# Returns a list of the new faces (list of lists)
|
||||
#
|
||||
# vertIdx1 ... First vertex list (list of vertex indices).
|
||||
# vertIdx2 ... Second vertex list (list of vertex indices).
|
||||
# closed ... Creates a loop (first & last are closed).
|
||||
# flipped ... Invert the normal of the face(s).
|
||||
#
|
||||
# Note: You can set vertIdx1 to a single vertex index to create
|
||||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
|
|
|
@ -1,486 +0,0 @@
|
|||
# ##### 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 #####
|
||||
|
||||
import bpy
|
||||
from mathutils import *
|
||||
from math import *
|
||||
from bpy.props import *
|
||||
|
||||
# Create a new mesh (object) from verts/edges/faces.
|
||||
# verts/edges/faces ... List of vertices/edges/faces for the
|
||||
# new mesh (as used in from_pydata).
|
||||
# name ... Name of the new mesh (& object).
|
||||
def create_mesh_object(context, verts, edges, faces, name):
|
||||
|
||||
# Create new mesh
|
||||
mesh = bpy.data.meshes.new(name)
|
||||
|
||||
# Make a mesh from a list of verts/edges/faces.
|
||||
mesh.from_pydata(verts, edges, faces)
|
||||
|
||||
# Update mesh geometry after adding stuff.
|
||||
mesh.update()
|
||||
|
||||
from bpy_extras import object_utils
|
||||
return object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
# Connects two equally long vertex rows with faces.
|
||||
# Returns a list of the new faces (list of lists)
|
||||
#
|
||||
# vertIdx1 ... First vertex list (list of vertex indices).
|
||||
# vertIdx2 ... Second vertex list (list of vertex indices).
|
||||
# closed ... Creates a loop (first & last are closed).
|
||||
# flipped ... Invert the normal of the face(s).
|
||||
#
|
||||
# Note: You can set vertIdx1 to a single vertex index to create
|
||||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
if not vertIdx1 or not vertIdx2:
|
||||
return None
|
||||
|
||||
if len(vertIdx1) < 2 and len(vertIdx2) < 2:
|
||||
return None
|
||||
|
||||
fan = False
|
||||
if (len(vertIdx1) != len(vertIdx2)):
|
||||
if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
|
||||
fan = True
|
||||
else:
|
||||
return None
|
||||
|
||||
total = len(vertIdx2)
|
||||
|
||||
if closed:
|
||||
# Bridge the start with the end.
|
||||
if flipped:
|
||||
face = [
|
||||
vertIdx1[0],
|
||||
vertIdx2[0],
|
||||
vertIdx2[total - 1]]
|
||||
if not fan:
|
||||
face.append(vertIdx1[total - 1])
|
||||
faces.append(face)
|
||||
|
||||
else:
|
||||
face = [vertIdx2[0], vertIdx1[0]]
|
||||
if not fan:
|
||||
face.append(vertIdx1[total - 1])
|
||||
face.append(vertIdx2[total - 1])
|
||||
faces.append(face)
|
||||
|
||||
# Bridge the rest of the faces.
|
||||
for num in range(total - 1):
|
||||
if flipped:
|
||||
if fan:
|
||||
face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
|
||||
else:
|
||||
face = [vertIdx2[num], vertIdx1[num],
|
||||
vertIdx1[num + 1], vertIdx2[num + 1]]
|
||||
faces.append(face)
|
||||
else:
|
||||
if fan:
|
||||
face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
|
||||
else:
|
||||
face = [vertIdx1[num], vertIdx2[num],
|
||||
vertIdx2[num + 1], vertIdx1[num + 1]]
|
||||
faces.append(face)
|
||||
|
||||
return faces
|
||||
|
||||
|
||||
# @todo Clean up vertex&face creation process a bit.
|
||||
def add_sqorus(hole_size, subdivide):
|
||||
verts = []
|
||||
faces = []
|
||||
|
||||
size = 2.0
|
||||
|
||||
thickness = (size - hole_size) / 2.0
|
||||
distances = [
|
||||
-size / 2.0,
|
||||
-size / 2.0 + thickness,
|
||||
size / 2.0 - thickness,
|
||||
size / 2.0]
|
||||
|
||||
if subdivide:
|
||||
for i in range(4):
|
||||
y = distances[i]
|
||||
|
||||
for j in range(4):
|
||||
x = distances[j]
|
||||
|
||||
verts.append(Vector((x, y, size / 2.0)))
|
||||
verts.append(Vector((x, y, -size / 2.0)))
|
||||
|
||||
# Top outer loop (vertex indices)
|
||||
vIdx_out_up = [0, 2, 4, 6, 14, 22, 30, 28, 26, 24, 16, 8]
|
||||
# Lower outer loop (vertex indices)
|
||||
vIdx_out_low = [i + 1 for i in vIdx_out_up]
|
||||
|
||||
faces_outside = createFaces(vIdx_out_up, vIdx_out_low, closed=True)
|
||||
faces.extend(faces_outside)
|
||||
|
||||
# Top inner loop (vertex indices)
|
||||
vIdx_inner_up = [10, 12, 20, 18]
|
||||
|
||||
# Lower inner loop (vertex indices)
|
||||
vIdx_inner_low = [i + 1 for i in vIdx_inner_up]
|
||||
|
||||
faces_inside = createFaces(vIdx_inner_up, vIdx_inner_low,
|
||||
closed=True, flipped=True)
|
||||
faces.extend(faces_inside)
|
||||
|
||||
row1_top = [0, 8, 16, 24]
|
||||
row2_top = [i + 2 for i in row1_top]
|
||||
row3_top = [i + 2 for i in row2_top]
|
||||
row4_top = [i + 2 for i in row3_top]
|
||||
|
||||
faces_top1 = createFaces(row1_top, row2_top)
|
||||
faces.extend(faces_top1)
|
||||
faces_top2_side1 = createFaces(row2_top[:2], row3_top[:2])
|
||||
faces.extend(faces_top2_side1)
|
||||
faces_top2_side2 = createFaces(row2_top[2:], row3_top[2:])
|
||||
faces.extend(faces_top2_side2)
|
||||
faces_top3 = createFaces(row3_top, row4_top)
|
||||
faces.extend(faces_top3)
|
||||
|
||||
row1_bot = [1, 9, 17, 25]
|
||||
row2_bot = [i + 2 for i in row1_bot]
|
||||
row3_bot = [i + 2 for i in row2_bot]
|
||||
row4_bot = [i + 2 for i in row3_bot]
|
||||
|
||||
faces_bot1 = createFaces(row1_bot, row2_bot, flipped=True)
|
||||
faces.extend(faces_bot1)
|
||||
faces_bot2_side1 = createFaces(row2_bot[:2], row3_bot[:2],
|
||||
flipped=True)
|
||||
faces.extend(faces_bot2_side1)
|
||||
faces_bot2_side2 = createFaces(row2_bot[2:], row3_bot[2:],
|
||||
flipped=True)
|
||||
faces.extend(faces_bot2_side2)
|
||||
faces_bot3 = createFaces(row3_bot, row4_bot, flipped=True)
|
||||
faces.extend(faces_bot3)
|
||||
|
||||
else:
|
||||
# Do not subdivde outer faces
|
||||
|
||||
vIdx_out_up = []
|
||||
vIdx_out_low = []
|
||||
vIdx_in_up = []
|
||||
vIdx_in_low = []
|
||||
|
||||
for i in range(4):
|
||||
y = distances[i]
|
||||
|
||||
for j in range(4):
|
||||
x = distances[j]
|
||||
|
||||
append = False
|
||||
inner = False
|
||||
# Outer
|
||||
if (i in [0, 3] and j in [0, 3]):
|
||||
append = True
|
||||
|
||||
# Inner
|
||||
if (i in [1, 2] and j in [1, 2]):
|
||||
append = True
|
||||
inner = True
|
||||
|
||||
if append:
|
||||
vert_up = len(verts)
|
||||
verts.append(Vector((x, y, size / 2.0)))
|
||||
vert_low = len(verts)
|
||||
verts.append(Vector((x, y, -size / 2.0)))
|
||||
|
||||
if inner:
|
||||
vIdx_in_up.append(vert_up)
|
||||
vIdx_in_low.append(vert_low)
|
||||
|
||||
else:
|
||||
vIdx_out_up.append(vert_up)
|
||||
vIdx_out_low.append(vert_low)
|
||||
|
||||
# Flip last two vertices
|
||||
vIdx_out_up = vIdx_out_up[:2] + list(reversed(vIdx_out_up[2:]))
|
||||
vIdx_out_low = vIdx_out_low[:2] + list(reversed(vIdx_out_low[2:]))
|
||||
vIdx_in_up = vIdx_in_up[:2] + list(reversed(vIdx_in_up[2:]))
|
||||
vIdx_in_low = vIdx_in_low[:2] + list(reversed(vIdx_in_low[2:]))
|
||||
|
||||
# Create faces
|
||||
faces_top = createFaces(vIdx_in_up, vIdx_out_up, closed=True)
|
||||
faces.extend(faces_top)
|
||||
faces_bottom = createFaces(vIdx_out_low, vIdx_in_low, closed=True)
|
||||
faces.extend(faces_bottom)
|
||||
faces_inside = createFaces(vIdx_in_low, vIdx_in_up, closed=True)
|
||||
faces.extend(faces_inside)
|
||||
faces_outside = createFaces(vIdx_out_up, vIdx_out_low, closed=True)
|
||||
faces.extend(faces_outside)
|
||||
|
||||
return verts, faces
|
||||
|
||||
|
||||
def add_wedge(size_x, size_y, size_z):
|
||||
verts = []
|
||||
faces = []
|
||||
|
||||
size_x /= 2.0
|
||||
size_y /= 2.0
|
||||
size_z /= 2.0
|
||||
|
||||
vIdx_top = []
|
||||
vIdx_bot = []
|
||||
|
||||
vIdx_top.append(len(verts))
|
||||
verts.append(Vector((-size_x, -size_y, size_z)))
|
||||
vIdx_bot.append(len(verts))
|
||||
verts.append(Vector((-size_x, -size_y, -size_z)))
|
||||
|
||||
vIdx_top.append(len(verts))
|
||||
verts.append(Vector((size_x, -size_y, size_z)))
|
||||
vIdx_bot.append(len(verts))
|
||||
verts.append(Vector((size_x, -size_y, -size_z)))
|
||||
|
||||
vIdx_top.append(len(verts))
|
||||
verts.append(Vector((-size_x, size_y, size_z)))
|
||||
vIdx_bot.append(len(verts))
|
||||
verts.append(Vector((-size_x, size_y, -size_z)))
|
||||
|
||||
faces.append(vIdx_top)
|
||||
faces.append(vIdx_bot)
|
||||
faces_outside = createFaces(vIdx_top, vIdx_bot, closed=True)
|
||||
faces.extend(faces_outside)
|
||||
|
||||
return verts, faces
|
||||
|
||||
def add_star(points, outer_radius, inner_radius, height):
|
||||
PI_2 = pi * 2
|
||||
z_axis = (0, 0, 1)
|
||||
|
||||
verts = []
|
||||
faces = []
|
||||
|
||||
segments = points * 2
|
||||
|
||||
half_height = height / 2.0
|
||||
|
||||
vert_idx_top = len(verts)
|
||||
verts.append(Vector((0.0, 0.0, half_height)))
|
||||
|
||||
vert_idx_bottom = len(verts)
|
||||
verts.append(Vector((0.0, 0.0, -half_height)))
|
||||
|
||||
edgeloop_top = []
|
||||
edgeloop_bottom = []
|
||||
|
||||
for index in range(segments):
|
||||
quat = Quaternion(z_axis, (index / segments) * PI_2)
|
||||
|
||||
if index % 2:
|
||||
# Uneven
|
||||
radius = outer_radius
|
||||
else:
|
||||
# Even
|
||||
radius = inner_radius
|
||||
|
||||
edgeloop_top.append(len(verts))
|
||||
vec = quat * Vector((radius, 0, half_height))
|
||||
verts.append(vec)
|
||||
|
||||
edgeloop_bottom.append(len(verts))
|
||||
vec = quat * Vector((radius, 0, -half_height))
|
||||
verts.append(vec)
|
||||
|
||||
|
||||
|
||||
faces_top = createFaces([vert_idx_top], edgeloop_top, closed=True)
|
||||
faces_outside = createFaces(edgeloop_top, edgeloop_bottom, closed=True)
|
||||
faces_bottom = createFaces([vert_idx_bottom], edgeloop_bottom,
|
||||
flipped=True, closed=True)
|
||||
|
||||
faces.extend(faces_top)
|
||||
faces.extend(faces_outside)
|
||||
faces.extend(faces_bottom)
|
||||
|
||||
return verts, faces
|
||||
|
||||
def trapezohedron(s,r,h):
|
||||
"""
|
||||
s = segments
|
||||
r = base radius
|
||||
h = tip height
|
||||
"""
|
||||
|
||||
# calculate constants
|
||||
a = 2*pi/(2*s) # angle between points along the equator
|
||||
l = r*cos(a) # helper for e
|
||||
e = h*(r-l)/(l+r) # the z offset for each vector along the equator so faces are planar
|
||||
|
||||
# rotation for the points
|
||||
quat = Quaternion((0,0,1),a)
|
||||
|
||||
# first 3 vectors, every next one is calculated from the last, and the z-value is negated
|
||||
verts = [Vector(i) for i in [(0,0,h),(0,0,-h),(r,0,e)]]
|
||||
for i in range(2*s-1):
|
||||
verts.append(quat*verts[-1]) # rotate further "a" radians around the z-axis
|
||||
verts[-1].z *= -1 # negate last z-value to account for the zigzag
|
||||
|
||||
faces = []
|
||||
for i in range(2,2+2*s,2):
|
||||
n = [i+1,i+2,i+3] # vertices in current section
|
||||
for j in range(3): # check whether the numbers dont go over len(verts)
|
||||
if n[j]>=2*s+2: n[j]-=2*s # if so, subtract len(verts)-2
|
||||
|
||||
# add faces of current section
|
||||
faces.append([0,i]+n[:2])
|
||||
faces.append([1,n[2],n[1],n[0]])
|
||||
|
||||
return verts,faces
|
||||
|
||||
class AddSqorus(bpy.types.Operator):
|
||||
"""Add a sqorus mesh"""
|
||||
bl_idname = "mesh.primitive_sqorus_add"
|
||||
bl_label = "Add Sqorus"
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
hole_size = FloatProperty(name="Hole Size",
|
||||
description="Size of the Hole",
|
||||
min=0.01,
|
||||
max=1.99,
|
||||
default=2.0 / 3.0)
|
||||
subdivide = BoolProperty(name="Subdivide Outside",
|
||||
description="Enable to subdivide the faces on the outside " \
|
||||
"(this results in equally spaced vertices)",
|
||||
default=True)
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
# Create mesh geometry
|
||||
verts, faces = add_sqorus(
|
||||
self.hole_size,
|
||||
self.subdivide)
|
||||
|
||||
# Create mesh object (and meshdata)
|
||||
obj = create_mesh_object(context, verts, [], faces, "Sqorus")
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class AddWedge(bpy.types.Operator):
|
||||
"""Add a wedge mesh"""
|
||||
bl_idname = "mesh.primitive_wedge_add"
|
||||
bl_label = "Add Wedge"
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
size_x = FloatProperty(name="Size X",
|
||||
description="Size along the X axis",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=2.0)
|
||||
size_y = FloatProperty(name="Size Y",
|
||||
description="Size along the Y axis",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=2.0)
|
||||
size_z = FloatProperty(name="Size Z",
|
||||
description="Size along the Z axis",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=2.00)
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
verts, faces = add_wedge(
|
||||
self.size_x,
|
||||
self.size_y,
|
||||
self.size_z)
|
||||
|
||||
obj = create_mesh_object(context, verts, [], faces, "Wedge")
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class AddStar(bpy.types.Operator):
|
||||
"""Add a star mesh"""
|
||||
bl_idname = "mesh.primitive_star_add"
|
||||
bl_label = "Add Star"
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
points = IntProperty(name="Points",
|
||||
description="Number of points for the star",
|
||||
min=2,
|
||||
max=256,
|
||||
default=5)
|
||||
outer_radius = FloatProperty(name="Outer Radius",
|
||||
description="Outer radius of the star",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=1.0)
|
||||
innter_radius = FloatProperty(name="Inner Radius",
|
||||
description="Inner radius of the star",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=0.5)
|
||||
height = FloatProperty(name="Height",
|
||||
description="Height of the star",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=0.5)
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
verts, faces = add_star(
|
||||
self.points,
|
||||
self.outer_radius,
|
||||
self.innter_radius,
|
||||
self.height)
|
||||
|
||||
obj = create_mesh_object(context, verts, [], faces, "Star")
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class AddTrapezohedron(bpy.types.Operator):
|
||||
"""Add a trapezohedron"""
|
||||
bl_idname = "mesh.primitive_trapezohedron_add"
|
||||
bl_label = "Add trapezohedron"
|
||||
bl_description = "Create one of the regular solids"
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
segments = IntProperty(name = "Segments",
|
||||
description = "Number of repeated segments",
|
||||
default = 4, min = 2, max = 256)
|
||||
radius = FloatProperty(name = "Base radius",
|
||||
description = "Radius of the middle",
|
||||
default = 1.0, min = 0.01, max = 100.0)
|
||||
height = FloatProperty(name = "Tip height",
|
||||
description = "Height of the tip",
|
||||
default = 1, min = 0.01, max = 100.0)
|
||||
|
||||
def execute(self,context):
|
||||
# generate mesh
|
||||
verts,faces = trapezohedron(self.segments,
|
||||
self.radius,
|
||||
self.height)
|
||||
|
||||
obj = create_mesh_object(context, verts, [], faces, "Trapazohedron")
|
||||
|
||||
return {'FINISHED'}
|
|
@ -1,28 +1,4 @@
|
|||
# add_mesh_gear.py (c) 2009, 2010 Michel J. Anders (varkenvarken)
|
||||
#
|
||||
# ***** 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 LICENCE BLOCK *****
|
||||
'''
|
||||
"name": "Gears",
|
||||
"author": "Michel J. Anders (varkenvarken)",
|
||||
"version": (2, 4, 2),
|
||||
'''
|
||||
# GPL # (c) 2009, 2010 Michel J. Anders (varkenvarken)
|
||||
|
||||
import bpy
|
||||
from math import *
|
||||
|
@ -58,6 +34,7 @@ def create_mesh_object(context, verts, edges, faces, name):
|
|||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
|
|
|
@ -1,25 +1,5 @@
|
|||
# ##### 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 #####
|
||||
'''
|
||||
"name": "Gemstones",
|
||||
"author": "Pontiac, Fourmadmen, Dreampainter",
|
||||
"version": (0, 4),
|
||||
'''
|
||||
# GPL # "author": "Pontiac, Fourmadmen, Dreampainter"
|
||||
|
||||
import bpy
|
||||
from mathutils import *
|
||||
from math import *
|
||||
|
@ -44,18 +24,7 @@ def create_mesh_object(context, verts, edges, faces, name):
|
|||
return object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
# Connects two equally long vertex rows with faces.
|
||||
# Returns a list of the new faces (list of lists)
|
||||
#
|
||||
# vertIdx1 ... First vertex list (list of vertex indices).
|
||||
# vertIdx2 ... Second vertex list (list of vertex indices).
|
||||
# closed ... Creates a loop (first & last are closed).
|
||||
# flipped ... Invert the normal of the face(s).
|
||||
#
|
||||
# Note: You can set vertIdx1 to a single vertex index to create
|
||||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
|
|
|
@ -1,25 +1,5 @@
|
|||
# ##### 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 #####
|
||||
'''
|
||||
"name": "HoneyComb",
|
||||
"author": "Kayo Phoenix <kayo@illumium.org>",
|
||||
"version": (0, 1),
|
||||
'''
|
||||
# GPL # "author": "Kayo Phoenix"
|
||||
|
||||
from math import pi, sin, cos
|
||||
|
||||
class honeycomb_geometry():
|
||||
|
@ -256,20 +236,3 @@ class add_mesh_honeycomb(bpy.types.Operator):
|
|||
object_utils.object_data_add(context, mesh, operator=self)
|
||||
|
||||
return {'FINISHED'}
|
||||
'''
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(add_mesh_honeycomb.bl_idname, text = bl_info['name'], 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__)
|
||||
|
||||
bpy.types.INFO_MT_mesh_add.remove(menu_func)
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
'''
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2015 sugiany
|
||||
# This file is distributed under the MIT License. See the LICENSE.md for more details.
|
||||
|
||||
import bpy
|
||||
|
||||
from bpy.props import IntProperty, BoolProperty, FloatVectorProperty, FloatProperty
|
||||
|
||||
import bpy
|
||||
import mathutils
|
||||
import copy
|
||||
|
||||
class MengerSponge(object):
|
||||
FACE_INDICES = [
|
||||
[3, 7, 4, 0],
|
||||
[5, 6, 2, 1],
|
||||
[1, 2, 3, 0],
|
||||
[7, 6, 5, 4],
|
||||
[4, 5, 1, 0],
|
||||
[2, 6, 7, 3],
|
||||
]
|
||||
|
||||
def __init__(self, level):
|
||||
self.__level = level
|
||||
self.__max_point_number = 3 ** level
|
||||
self.__vertices_map = {}
|
||||
self.__indices = []
|
||||
self.__face_visibility = {}
|
||||
self.__faces = []
|
||||
|
||||
for x in range(3):
|
||||
for y in range(3):
|
||||
for z in range(3):
|
||||
self.__face_visibility[(x, y, z)] = [
|
||||
x == 0 or x == 2 and (y == 1 or z == 1),
|
||||
x == 2 or x == 0 and (y == 1 or z == 1),
|
||||
y == 0 or y == 2 and (x == 1 or z == 1),
|
||||
y == 2 or y == 0 and (x == 1 or z == 1),
|
||||
z == 0 or z == 2 and (y == 1 or x == 1),
|
||||
z == 2 or z == 0 and (y == 1 or x == 1),
|
||||
]
|
||||
|
||||
def create(self, width, height):
|
||||
m = self.__max_point_number
|
||||
points = [
|
||||
(0, 0, 0),
|
||||
(m, 0, 0),
|
||||
(m, 0, m),
|
||||
(0, 0, m),
|
||||
(0, m, 0),
|
||||
(m, m, 0),
|
||||
(m, m, m),
|
||||
(0, m, m),
|
||||
]
|
||||
self.__make_sub_sponge(points, None, self.__level)
|
||||
vertices = self.__make_vertices(width, height)
|
||||
return vertices, self.__faces
|
||||
|
||||
def __get_vindex(self, p):
|
||||
if p in self.__vertices_map:
|
||||
return self.__vertices_map[p]
|
||||
index = len(self.__vertices_map)
|
||||
self.__vertices_map[p] = index
|
||||
return index
|
||||
|
||||
def __make_vertices(self, width, height):
|
||||
vertices = [None] * len(self.__vertices_map)
|
||||
w2 = width / 2
|
||||
h2 = height / 2
|
||||
w_step = width / self.__max_point_number
|
||||
h_step = height / self.__max_point_number
|
||||
for p, i in sorted(self.__vertices_map.items(), key=lambda x: x[1]):
|
||||
vertices[i] = mathutils.Vector([
|
||||
p[0] * w_step - w2,
|
||||
p[1] * w_step - w2,
|
||||
p[2] * h_step - h2,
|
||||
])
|
||||
return vertices
|
||||
|
||||
def __make_sub_sponge(self, cur_points, face_vis, depth):
|
||||
if depth <= 0:
|
||||
if not face_vis:
|
||||
face_vis = True * 6
|
||||
cur_point_indices = []
|
||||
for p in cur_points:
|
||||
cur_point_indices.append(self.__get_vindex(p))
|
||||
for i, vis in enumerate(face_vis):
|
||||
if vis:
|
||||
f = []
|
||||
for vi in self.FACE_INDICES[i]:
|
||||
f.append(cur_point_indices[vi])
|
||||
self.__faces.append(f)
|
||||
return
|
||||
|
||||
base = cur_points[0]
|
||||
width = (cur_points[1][0] - base[0]) / 3
|
||||
local_vert_map = {}
|
||||
for z in range(4):
|
||||
for y in range(4):
|
||||
for x in range(4):
|
||||
local_vert_map[(x, y, z)] = (
|
||||
width * x + base[0],
|
||||
width * y + base[1],
|
||||
width * z + base[2],
|
||||
)
|
||||
|
||||
for x in range(3):
|
||||
for y in range(3):
|
||||
for z in range(3):
|
||||
if [x, y, z].count(1) > 1:
|
||||
continue
|
||||
next_points = [
|
||||
local_vert_map[(x, y, z)],
|
||||
local_vert_map[(x+1, y, z)],
|
||||
local_vert_map[(x+1, y, z+1)],
|
||||
local_vert_map[(x, y, z+1)],
|
||||
local_vert_map[(x, y+1, z)],
|
||||
local_vert_map[(x+1, y+1, z)],
|
||||
local_vert_map[(x+1, y+1, z+1)],
|
||||
local_vert_map[(x, y+1, z+1)],
|
||||
]
|
||||
visibility = copy.copy(self.__face_visibility[(x, y, z)])
|
||||
if face_vis:
|
||||
visibility[0] = visibility[0] and (face_vis[0] or x != 0)
|
||||
visibility[1] = visibility[1] and (face_vis[1] or x != 2)
|
||||
visibility[2] = visibility[2] and (face_vis[2] or y != 0)
|
||||
visibility[3] = visibility[3] and (face_vis[3] or y != 2)
|
||||
visibility[4] = visibility[4] and (face_vis[4] or z != 0)
|
||||
visibility[5] = visibility[5] and (face_vis[5] or z != 2)
|
||||
self.__make_sub_sponge(
|
||||
next_points,
|
||||
visibility,
|
||||
depth - 1)
|
||||
|
||||
|
||||
class AddMengerSponge(bpy.types.Operator):
|
||||
"""Add a menger sponge"""
|
||||
bl_idname = "mesh.menger_sponge_add"
|
||||
bl_label = "Menger Sponge"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
level = IntProperty(
|
||||
name="Level",
|
||||
description="Sponge Level",
|
||||
min=0, max=4,
|
||||
default=1,
|
||||
)
|
||||
|
||||
radius = FloatProperty(
|
||||
name="Width",
|
||||
description="Sponge Radius",
|
||||
min=0.01, max=100.0,
|
||||
default=1.0,
|
||||
)
|
||||
|
||||
# generic transform props
|
||||
view_align = BoolProperty(
|
||||
name="Align to View",
|
||||
default=False,
|
||||
)
|
||||
location = FloatVectorProperty(
|
||||
name="Location",
|
||||
subtype='TRANSLATION',
|
||||
)
|
||||
rotation = FloatVectorProperty(
|
||||
name="Rotation",
|
||||
subtype='EULER',
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
sponger = MengerSponge(self.level)
|
||||
vertices, faces = sponger.create(self.radius * 2, self.radius * 2)
|
||||
del sponger
|
||||
|
||||
mesh = bpy.data.meshes.new(name='Sponge')
|
||||
mesh.from_pydata(vertices, [], faces)
|
||||
uvs = [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]
|
||||
mesh.uv_textures.new()
|
||||
for i, uvloop in enumerate(mesh.uv_layers.active.data):
|
||||
uvloop.uv = uvs[i%4]
|
||||
|
||||
from bpy_extras import object_utils
|
||||
object_utils.object_data_add(context, mesh, operator=self)
|
||||
|
||||
return {'FINISHED'}
|
|
@ -1,25 +1,5 @@
|
|||
# ##### 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 #####
|
||||
'''
|
||||
"name": "Pipe Joints",
|
||||
"author": "Buerbaum Martin (Pontiac)",
|
||||
"version": (0, 10, 7),
|
||||
'''
|
||||
# GPL # "author": "Buerbaum Martin (Pontiac)"
|
||||
|
||||
import bpy
|
||||
from math import *
|
||||
from bpy.props import *
|
||||
|
@ -42,18 +22,7 @@ def create_mesh_object(context, verts, edges, faces, name):
|
|||
return object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
# Connects two equally long vertex rows with faces.
|
||||
# Returns a list of the new faces (list of lists)
|
||||
#
|
||||
# vertIdx1 ... First vertex list (list of vertex indices).
|
||||
# vertIdx2 ... Second vertex list (list of vertex indices).
|
||||
# closed ... Creates a loop (first & last are closed).
|
||||
# flipped ... Invert the normal of the face(s).
|
||||
#
|
||||
# Note: You can set vertIdx1 to a single vertex index to create
|
||||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
|
@ -988,5 +957,3 @@ class AddNJoint(bpy.types.Operator):
|
|||
base = create_mesh_object(context, verts, [], faces, "N Joint")
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
################################
|
|
@ -1,79 +0,0 @@
|
|||
# ##### 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 #####
|
||||
'''
|
||||
"name": "Add PolySphere",
|
||||
"author": "Andy Davies (metalliandy)",
|
||||
"version": (0,1,6),
|
||||
'''
|
||||
|
||||
import bpy
|
||||
|
||||
def Add_PolySphere():
|
||||
#Add Cube to scene
|
||||
bpy.ops.mesh.primitive_cube_add()
|
||||
|
||||
#Changes name of Cube to PolySphere adds the variable cube
|
||||
cube = bpy.context.object
|
||||
cube.name = "PolySphere"
|
||||
|
||||
#Positions Cube primitive to scene centre
|
||||
bpy.context.active_object.location = [0, 0, 0]
|
||||
|
||||
#Adds Subsurf Modifier
|
||||
bpy.ops.object.modifier_add(type='SUBSURF')
|
||||
|
||||
#Selects Subsurf Modifier for editing
|
||||
subsurf = cube.modifiers['Subsurf']
|
||||
|
||||
#Changes Subsurf levels
|
||||
subsurf.levels = 3
|
||||
|
||||
#Applys Subsurf Modifier
|
||||
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Subsurf")
|
||||
|
||||
#Adds smooth shading
|
||||
bpy.ops.object.shade_smooth()
|
||||
|
||||
#Change to Editmode
|
||||
bpy.ops.object.editmode_toggle()
|
||||
|
||||
#Selects cube in Editmode
|
||||
#bpy.ops.mesh.select_all(action='TOGGLE')
|
||||
|
||||
#Adds transform "To Sphere"
|
||||
bpy.ops.transform.tosphere(value=1)
|
||||
|
||||
#Change to Objectmode
|
||||
bpy.ops.object.editmode_toggle()
|
||||
|
||||
#Scales Object to 2.0 Units
|
||||
bpy.ops.transform.resize(value=(1.15525, 1.15525, 1.15525), constraint_axis=(False, False, False), constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1, snap=False, snap_target='CLOSEST', snap_point=(0, 0, 0), snap_align=False, snap_normal=(0, 0, 0), release_confirm=False)
|
||||
|
||||
#Applys location, rotation and scale data
|
||||
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
|
||||
|
||||
#makes PolySphere an operator
|
||||
class AddPolySphere(bpy.types.Operator):
|
||||
|
||||
bl_idname = "mesh.primitive_polysphere_add"
|
||||
bl_label = "Add PolySphere"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
Add_PolySphere()
|
||||
return {'FINISHED'}
|
|
@ -1,35 +1,4 @@
|
|||
# ***** 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 LICENCE BLOCK *****
|
||||
|
||||
# (c) 2011 Phil Cote (cotejrp1)
|
||||
'''
|
||||
bl_info = {
|
||||
"name": "Mesh Pyramid",
|
||||
"author": "Phil Cote, cotejrp1, (http://www.blenderaddons.com)",
|
||||
"version": (0, 5),
|
||||
"blender": (2, 63, 0),
|
||||
"location": "View3D > Add > Mesh",
|
||||
"description": "Create an egyption-style step pyramid",
|
||||
"warning": "", # used for warning icon and text in addons panel
|
||||
"category": "Add Mesh",
|
||||
}
|
||||
'''
|
||||
# GPL # "author": "Phil Cote, cotejrp1, (http://www.blenderaddons.com)"
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
|
@ -163,21 +132,3 @@ class AddPyramid(bpy.types.Operator, AddObjectHelper):
|
|||
def execute(self, context):
|
||||
add_pyramid_object(self, context)
|
||||
return {'FINISHED'}
|
||||
|
||||
'''
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(AddPyramid.bl_idname, icon='PLUGIN')
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(AddPyramid)
|
||||
bpy.types.INFO_MT_mesh_add.append(menu_func)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(AddPyramid)
|
||||
bpy.types.INFO_MT_mesh_add.remove(menu_func)
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
'''
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
# GPL "author": "Dominic Kröper, (dommetysk)"
|
||||
|
||||
import bpy
|
||||
from math import pi, sin, cos, tan
|
||||
from bpy.types import Operator
|
||||
from bpy.props import IntProperty, FloatProperty, BoolProperty
|
||||
from mathutils import Vector, Euler
|
||||
|
||||
# mesh/object generating function, returns final object
|
||||
def addBrilliant(context, s, table_w, crown_h, girdle_t, pavi_d, bezel_f,
|
||||
pavi_f, culet, girdle_real, keep_lga, g_real_smooth):
|
||||
|
||||
# # possible user inputs ( output 100% = 2 blender units )
|
||||
# s # no. of girdle facets (steps) default: 16
|
||||
# table_w # table width default: 0.530
|
||||
# crown_h # crown height default: 0.162
|
||||
# girdle_t # girdle thickness default: 0.017
|
||||
# pavi_d # pavillion depth default: 0.431
|
||||
# bezel_f # bezel factor default: 0.250
|
||||
# pavi_f # pavillion factor default: 0.400
|
||||
# culet # culet size default: 0.000
|
||||
# girdle_real # type of girdle flat/real default: True
|
||||
# g_real_smooth # smooth or flat shading default: False
|
||||
# keep_lga # when culet > 0, keep lga default: False
|
||||
|
||||
# variables / shortcuts
|
||||
if s % 2: # prevent odd number of steps (messes up mesh)
|
||||
s = s - 1
|
||||
if not girdle_real:
|
||||
g_real_smooth = False
|
||||
ang = 2*pi/s # angle step size
|
||||
Verts = [] # collect all vertices
|
||||
Faces = [] # collect all faces
|
||||
ca = cos(ang)
|
||||
ca2 = cos(ang/2)
|
||||
sa4 = sin(ang/4)
|
||||
ta4 = tan(ang/4)
|
||||
ta8 = tan(ang/8)
|
||||
|
||||
def fa(*vs): # shortcut Faces.append
|
||||
v = []
|
||||
for u in vs:
|
||||
v.append(u)
|
||||
Faces.append(v)
|
||||
|
||||
def va(vx, vz, iang, sang, n): # shortcut Verts.append
|
||||
for i in range(n):
|
||||
v = Vector((vx, 0, vz))
|
||||
ai = sang + iang*i
|
||||
E_rot = Euler((0, 0, ai), 'XYZ')
|
||||
v.rotate(E_rot)
|
||||
Verts.append((v.x, v.y, v.z))
|
||||
|
||||
|
||||
# upper girdle angle
|
||||
uga = (1-bezel_f) * crown_h*2 / (ca2 -
|
||||
(table_w + (1-table_w) * bezel_f) * ca2/ca)
|
||||
|
||||
# lower girdle angle
|
||||
if keep_lga:
|
||||
if pavi_f > 0 and pavi_f < 1:
|
||||
lga = (1-pavi_f) * pavi_d*2 / (ca2 - pavi_f*ca2 / ca)
|
||||
elif pavi_f == 1:
|
||||
lga = 0
|
||||
else:
|
||||
lga = 2*pavi_d*ca
|
||||
else:
|
||||
lga = (1-pavi_f) * pavi_d*2 / (ca2 -
|
||||
(culet + (1-culet) * pavi_f) * ca2/ca)
|
||||
|
||||
# append girdle vertices
|
||||
va(1, 0, ang, 0, s)
|
||||
va(1, 2*girdle_t, ang, 0, s)
|
||||
|
||||
# append real girdle vertices
|
||||
if girdle_real:
|
||||
dnu = uga * (1 - ca2)
|
||||
dfu = uga * (ta8 + ta4) * sa4
|
||||
dnl = lga * (1 - ca2)
|
||||
dfl = lga * (ta8 + ta4) * sa4
|
||||
if abs(dnu) + abs(dnl) > 2*girdle_t or dnu < 0 or dnl < 0:
|
||||
girdle_real = False
|
||||
else:
|
||||
va(1, dnl, ang, ang/2, s)
|
||||
va(1, 2*girdle_t - dnu, ang, ang/2, s)
|
||||
va(1, dfl, ang/2, ang/4, 2*s)
|
||||
va(1, 2*girdle_t - dfu, ang/2, ang/4, 2*s)
|
||||
|
||||
# make girdle faces
|
||||
l1 = len(Verts) # 2*s / 8*s
|
||||
for i in range(l1):
|
||||
if girdle_real:
|
||||
if i < s:
|
||||
fa(i, i + s, 2*i + 6*s, 2*i + 4*s)
|
||||
if i == 0:
|
||||
fa(i, s, l1 - 1, 6*s - 1)
|
||||
else:
|
||||
fa(i, i + s, 2*i + 6*s - 1, 2*i + 4*s - 1)
|
||||
elif i > 2*s - 1 and i < 3*s:
|
||||
fa(i, i + s, 2 * (i+s), 2*i)
|
||||
fa(i, i + s, 2 * (i+s) + 1, 2*i + 1)
|
||||
else:
|
||||
if i < s - 1:
|
||||
fa(i, i + s, i + s + 1, i + 1)
|
||||
elif i == s - 1:
|
||||
fa(i, i + s, s, 0)
|
||||
|
||||
# append upper girdle facet vertices
|
||||
va((table_w + (1-table_w) * bezel_f) / ca, (1-bezel_f) * 2*crown_h +
|
||||
2*girdle_t, 2*ang, ang, int(s/2))
|
||||
|
||||
# make upper girdle facet faces
|
||||
l2 = len(Verts) # 2.5*s / 8.5*s
|
||||
for i in range(l2):
|
||||
if i > s and i < 2*s - 1 and i % 2 != 0:
|
||||
if girdle_real:
|
||||
fa(i, 2 * (i + 2*s), i + 2*s, 2 * (i + 2*s) + 1, i + 1,
|
||||
int(7.5*s) + int((i-1) / 2))
|
||||
fa(i, 2 * (i + 2*s) - 1, i + 2*s - 1, 2 * (i + 2*s - 1),
|
||||
i - 1, int(7.5*s) + int((i-1) / 2))
|
||||
else:
|
||||
fa(i, i + 1, int((i + 3*s) / 2))
|
||||
fa(i, i - 1, int((i + 3*s) / 2))
|
||||
elif i == s:
|
||||
if girdle_real:
|
||||
fa(i, l1 - 1, 4*s - 1, l1 - 2, 2*i - 1, l2 - 1)
|
||||
fa(2*i - 2, l1 - 4, 4*s - 2, l1 - 3, 2*i - 1, l2 - 1)
|
||||
else:
|
||||
fa(i, 2*i - 1, l2 - 1)
|
||||
fa(2*i - 1, 2*i - 2, l2 - 1)
|
||||
|
||||
# append table vertices
|
||||
va(table_w, (crown_h + girdle_t)*2, 2*ang, 0, int(s/2))
|
||||
|
||||
# make bezel facet faces and star facet faces
|
||||
l3 = len(Verts) # 3*s / 9*s
|
||||
for i in range(l3):
|
||||
if i > l2 - 1 and i < l3 - 1:
|
||||
fa(i, i + 1, i - int(s/2))
|
||||
fa(i + 1, i - int(s/2), 2 * (i-l2) + 2 + s, i - int(s/2) + 1)
|
||||
elif i == l3 - 1:
|
||||
fa(i, l2, l2 - 1)
|
||||
fa(s, l2 - 1, l2, l2 - int(s/2))
|
||||
|
||||
# make table facet face
|
||||
tf = []
|
||||
for i in range(l3):
|
||||
if i > l2 - 1:
|
||||
tf.append(i)
|
||||
fa(*tf)
|
||||
|
||||
# append lower girdle facet vertices
|
||||
if keep_lga:
|
||||
va(pavi_f/ca, (pavi_f-1) * pavi_d*2, 2*ang, ang, int(s/2))
|
||||
else:
|
||||
va((pavi_f * (1-culet) + culet) / ca, (pavi_f-1) * pavi_d*2, 2*ang,
|
||||
ang, int(s/2))
|
||||
|
||||
# make lower girdle facet faces
|
||||
l4 = len(Verts) # 3.5*s / 9.5*s
|
||||
for i in range(l4):
|
||||
if i > 0 and i < s - 1 and i % 2 == 0:
|
||||
if girdle_real:
|
||||
fa(i, 2 * (i + 2*s), i + 2*s, 2 * (i + 2*s) + 1, i + 1,
|
||||
int(i/2) + 9*s)
|
||||
fa(i, 2 * (i + 2*s) - 1, i + 2*s - 1, 2 * (i + 2*s - 1),
|
||||
i-1, int(i/2) + 9*s - 1)
|
||||
else:
|
||||
fa(i, i + 1, int(i/2) + l4 - int(s/2))
|
||||
fa(i, i - 1, int(i/2) + l4 - int(s/2) - 1)
|
||||
elif i == 0:
|
||||
if girdle_real:
|
||||
fa(0, 4*s, 2*s, 4*s + 1, 1, 9*s)
|
||||
fa(0, 6*s - 1, 3*s - 1, 6*s - 2, s - 1, l4 - 1)
|
||||
else:
|
||||
fa(0, 1, l4 - int(s/2))
|
||||
fa(0, s - 1, l4 - 1)
|
||||
|
||||
# append culet vertice(s)
|
||||
if culet == 0:
|
||||
va(0, pavi_d*(-2), 0, 0, 1)
|
||||
else:
|
||||
if keep_lga:
|
||||
va(culet * pavi_f / ca, pavi_d*(-2) + culet * pavi_f * 2 * pavi_d,
|
||||
2*ang, ang, int(s/2))
|
||||
else:
|
||||
va(culet/ca, pavi_d*(-2), 2*ang, ang, int(s/2))
|
||||
|
||||
# make pavillion facet face
|
||||
l5 = len(Verts) # 4*s / 10*s //if !culet: 3.5*s+1 / 9.5*s+1
|
||||
for i in range(l5):
|
||||
if i > 0 and i < s - 1 and i % 2 == 0:
|
||||
if culet:
|
||||
fa(i, l3 + int(i/2), l3 + int((s+i) / 2),
|
||||
l3 + int((s+i) / 2) - 1, l3 + int(i/2) - 1)
|
||||
else:
|
||||
fa(i, l3 + int(i/2), l5 - 1, l3 + int(i/2) - 1)
|
||||
elif i == 0:
|
||||
if culet:
|
||||
fa(i, l3, l4, l5 - 1, l4 - 1)
|
||||
else:
|
||||
fa(i, l3, l5 - 1, l4 - 1)
|
||||
|
||||
# make culet facet face
|
||||
if culet:
|
||||
cf = []
|
||||
for i in range(l5):
|
||||
if i > l4 - 1:
|
||||
cf.append(i)
|
||||
fa(*cf)
|
||||
|
||||
# bpy variables / shortcuts
|
||||
scene = bpy.context.scene
|
||||
|
||||
# deactivate possible active Objects
|
||||
bpy.context.scene.objects.active = None
|
||||
|
||||
# create actual mesh and object based on Verts and Faces given
|
||||
dmesh = bpy.data.meshes.new("dmesh")
|
||||
dmesh.from_pydata(Verts, [], Faces)
|
||||
dmesh.update()
|
||||
dobj = bpy.data.objects.new("dobj", dmesh)
|
||||
|
||||
# link object into scene
|
||||
scene.objects.link(dobj)
|
||||
|
||||
# activate and select object
|
||||
scene.objects.active = dobj
|
||||
dobj.select = True
|
||||
obj = bpy.context.active_object
|
||||
|
||||
# flip all face normals outside
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
sel_mode = bpy.context.tool_settings.mesh_select_mode
|
||||
bpy.context.tool_settings.mesh_select_mode = [False, False, True]
|
||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
||||
for i, face in enumerate(obj.data.polygons):
|
||||
face.select = True
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
bpy.ops.mesh.normals_make_consistent(inside=False)
|
||||
bpy.context.tool_settings.mesh_select_mode = sel_mode
|
||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
||||
|
||||
# make girdle smooth for complex girdle
|
||||
if girdle_real and g_real_smooth:
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
|
||||
bpy.ops.mesh.select_all(action='DESELECT') # deselect all mesh data
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
pls = []
|
||||
dp = obj.data.polygons[:4*s] # only consider faces of girdle
|
||||
ov = obj.data.vertices
|
||||
|
||||
for i, p in enumerate(dp):
|
||||
pls.extend(p.vertices) # list all verts of girdle
|
||||
|
||||
for i, e in enumerate(obj.data.edges): # select egdes to mark sharp
|
||||
if e.vertices[0] in pls and e.vertices[1] in pls and abs(
|
||||
ov[e.vertices[0]].co.x - ov[e.vertices[1]].co.x):
|
||||
obj.data.edges[i].select = True
|
||||
continue
|
||||
obj.data.edges[i].select = False
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
bpy.ops.mesh.mark_sharp()
|
||||
|
||||
bpy.context.tool_settings.mesh_select_mode = [False, False, True]
|
||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for i, face in enumerate(obj.data.polygons):
|
||||
if i < 4*s:
|
||||
face.select = True
|
||||
continue
|
||||
face.select = False
|
||||
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
|
||||
bpy.ops.mesh.faces_shade_smooth()
|
||||
|
||||
bpy.ops.object.modifier_add(type='EDGE_SPLIT')
|
||||
|
||||
bpy.context.tool_settings.mesh_select_mode = sel_mode
|
||||
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
|
||||
|
||||
bpy.ops.object.modifier_apply(apply_as='DATA', modifier="EdgeSplit")
|
||||
|
||||
|
||||
return dobj
|
||||
|
||||
|
||||
# add new operator for object
|
||||
class MESH_OT_primitive_brilliant_add(bpy.types.Operator):
|
||||
bl_idname = "mesh.primitive_brilliant_add"
|
||||
bl_label = "Custom Brilliant"
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
# set user options
|
||||
s = IntProperty(name="Segments",
|
||||
description="Longitudial segmentation",
|
||||
step=1,
|
||||
min=6,
|
||||
max=128,
|
||||
default=16,
|
||||
subtype='FACTOR')
|
||||
table_w = FloatProperty(name="Table width",
|
||||
description="Width of table",
|
||||
min=0.001,
|
||||
max=1.0,
|
||||
default=0.53,
|
||||
subtype='PERCENTAGE')
|
||||
crown_h = FloatProperty(name="Crown height",
|
||||
description="Heigth of crown",
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
default=0.162,
|
||||
subtype='PERCENTAGE')
|
||||
girdle_t = FloatProperty(name="Girdle height",
|
||||
description="Height of girdle",
|
||||
min=0.0,
|
||||
max=0.5,
|
||||
default=0.017,
|
||||
subtype='PERCENTAGE')
|
||||
girdle_real = BoolProperty(name="Real girdle",
|
||||
description="More beautiful girdle; has more polygons",
|
||||
default=True)
|
||||
g_real_smooth = BoolProperty(name="Smooth girdle",
|
||||
description=
|
||||
"smooth shading for girdle, only available for real girdle",
|
||||
default=False)
|
||||
pavi_d = FloatProperty(name="Pavilion depth",
|
||||
description="Height of pavillion",
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
default=0.431,
|
||||
subtype='PERCENTAGE')
|
||||
bezel_f = FloatProperty(name="Upper facet factor",
|
||||
description=
|
||||
"Determines the form of bezel and upper girdle facets",
|
||||
min=0.0,
|
||||
max=1.0,
|
||||
default=0.250,
|
||||
subtype='PERCENTAGE')
|
||||
pavi_f = FloatProperty(name="Lower facet factor",
|
||||
description=
|
||||
"Determines the form of pavillion and lower girdle facets",
|
||||
min=0.001,
|
||||
max=1.0,
|
||||
default=0.400,
|
||||
subtype='PERCENTAGE')
|
||||
culet = FloatProperty(name="Culet size",
|
||||
description="0: no culet (default)",
|
||||
min=0.0,
|
||||
max=0.999,
|
||||
default=0.0,
|
||||
subtype='PERCENTAGE')
|
||||
keep_lga = BoolProperty(name="Retain lower angle",
|
||||
description="If culet > 0, retains angle of pavillion facets",
|
||||
default=False)
|
||||
|
||||
# call mesh/object generator function with user inputs
|
||||
def execute(self, context):
|
||||
ob = addBrilliant(context, self.s, self.table_w, self.crown_h,
|
||||
self.girdle_t, self.pavi_d, self.bezel_f,
|
||||
self.pavi_f, self.culet, self.girdle_real,
|
||||
self.keep_lga, self.g_real_smooth)
|
||||
return {'FINISHED'}
|
|
@ -0,0 +1,479 @@
|
|||
# GPL # 'author': 'Alain Ducharme (Phymec)'
|
||||
|
||||
import bpy
|
||||
from bpy_extras import object_utils
|
||||
from itertools import permutations
|
||||
from math import copysign, pi, sqrt
|
||||
|
||||
def round_cube(radius=1.0, arcdiv=4, lindiv=0., size=(0. ,0. ,0.), div_type='CORNERS', odd_axis_align=False, info_only=False):
|
||||
# subdiv bitmasks
|
||||
CORNERS, EDGES, ALL = 0, 1, 2
|
||||
try:
|
||||
subdiv = ('CORNERS', 'EDGES', 'ALL').index(div_type)
|
||||
except ValueError:
|
||||
subdiv = CORNERS # fallback
|
||||
|
||||
radius = max(radius, 0.)
|
||||
if not radius:
|
||||
arcdiv = 1
|
||||
|
||||
if arcdiv <= 0:
|
||||
arcdiv = max(round(pi * radius * lindiv * 0.5), 1)
|
||||
arcdiv = max(round(arcdiv), 1)
|
||||
if lindiv <= 0.:
|
||||
if radius:
|
||||
lindiv = 1. / (pi / (arcdiv * 2.) * radius)
|
||||
lindiv = max(lindiv, 0.)
|
||||
if not lindiv:
|
||||
subdiv = CORNERS
|
||||
|
||||
odd = arcdiv % 2 # even = arcdiv % 2 ^ 1
|
||||
step_size = 2. / arcdiv
|
||||
|
||||
odd_aligned = 0
|
||||
vi = -1.
|
||||
steps = arcdiv + 1
|
||||
if odd_axis_align and odd:
|
||||
odd_aligned = 1
|
||||
vi += 0.5 * step_size
|
||||
steps = arcdiv
|
||||
axis_aligned = not odd or odd_aligned
|
||||
|
||||
if arcdiv == 1 and not odd_aligned and subdiv == EDGES:
|
||||
subdiv = CORNERS
|
||||
|
||||
half_chord = 0. # ~ spherical cap base radius
|
||||
sagitta = 0. # ~ spherical cap height
|
||||
if not axis_aligned:
|
||||
half_chord = sqrt(3.) * radius / (3. * arcdiv)
|
||||
id2 = 1. / (arcdiv * arcdiv)
|
||||
sagitta = radius - radius * sqrt(id2 * id2 / 3. - id2 + 1.)
|
||||
|
||||
# Extrusion per axis
|
||||
exyz = [0. if s < 2. * (radius - sagitta) else (s - 2. * (radius - sagitta)) * 0.5 for s in size]
|
||||
ex, ey, ez = exyz
|
||||
|
||||
dxyz = [0, 0, 0] # extrusion divisions per axis
|
||||
dssxyz = [0., 0., 0.] # extrusion division step sizes per axis
|
||||
|
||||
for i in range(3):
|
||||
sc = 2. * (exyz[i] + half_chord)
|
||||
dxyz[i] = round(sc * lindiv) if subdiv else 0
|
||||
if dxyz[i]:
|
||||
dssxyz[i] = sc / dxyz[i]
|
||||
dxyz[i] -= 1
|
||||
else:
|
||||
dssxyz[i] = sc
|
||||
|
||||
if info_only:
|
||||
ec = sum(1 for n in exyz if n)
|
||||
if subdiv:
|
||||
fxyz = [d + (e and axis_aligned) for d, e in zip(dxyz, exyz)]
|
||||
dvc = arcdiv * 4 * sum(fxyz)
|
||||
if subdiv == ALL:
|
||||
dvc += sum(p1 * p2 for p1, p2 in permutations(fxyz, 2))
|
||||
elif subdiv == EDGES:
|
||||
# (0, 0, 2, 4) * sum(dxyz) + (0, 0, 2, 6)
|
||||
dvc += ec * ec // 2 * sum(dxyz) + ec * (ec - 1) if axis_aligned else 0
|
||||
else:
|
||||
dvc = (arcdiv * 4) * ec + ec * (ec - 1) if axis_aligned else 0
|
||||
vert_count = int(6 * arcdiv*arcdiv + (0 if odd_aligned else 2) + dvc)
|
||||
if not radius and not max(size) > 0:
|
||||
vert_count = 1
|
||||
return arcdiv, lindiv, vert_count
|
||||
|
||||
if not radius and not max(size) > 0:
|
||||
return [(0,0,0)], []
|
||||
|
||||
# uv lookup table
|
||||
uvlt = []
|
||||
v = vi
|
||||
for j in range(1, steps + 1):
|
||||
v2 = v*v
|
||||
uvlt.append((v, v2, radius * sqrt(18. - 6. * v2) / 6.))
|
||||
v = vi + j * step_size # v += step_size # instead of accumulating errors
|
||||
# clear precision errors / signs at axis
|
||||
if abs(v) < 1e-10:
|
||||
v = 0.0
|
||||
|
||||
# Round cube sides built left to right bottom up
|
||||
# xp yp zp xd yd zd
|
||||
sides = ((0, 2, 1, (-1, 1, 1)), # Y+ Front
|
||||
(1, 2, 0, (-1, -1, 1)), # X- Left
|
||||
(0, 2, 1, ( 1, -1, 1)), # Y- Back
|
||||
(1, 2, 0, ( 1, 1, 1)), # X+ Right
|
||||
(0, 1, 2, (-1, 1, -1)), # Z- Bottom
|
||||
(0, 1, 2, (-1, -1, 1))) # Z+ Top
|
||||
|
||||
# side vertex index table
|
||||
svit = [[[] for i in range(steps)] for i in range(6)]
|
||||
# Extend rows for extrusion
|
||||
if ey:
|
||||
yer = axis_aligned + (dxyz[1] if subdiv else 0)
|
||||
svit[4].extend([[] for i in range(yer)])
|
||||
svit[5].extend([[] for i in range(yer)])
|
||||
if ez:
|
||||
zer = axis_aligned + (dxyz[2] if subdiv else 0)
|
||||
for side in range(4):
|
||||
svit[side].extend([[] for i in range(zer)])
|
||||
ryi = rzi = 0 # row vertex indices
|
||||
# Extend rows for odd_aligned
|
||||
if odd_aligned:
|
||||
for side in range(4):
|
||||
svit[side].append([])
|
||||
|
||||
hemi = steps // 2
|
||||
|
||||
# Create vertices and svit without dups
|
||||
vert = [0., 0., 0.]
|
||||
verts = []
|
||||
|
||||
if arcdiv == 1 and not odd_aligned and subdiv == ALL:
|
||||
# Special case: 3D Grid Cuboid
|
||||
for side, (xp, yp, zp, dir) in enumerate(sides):
|
||||
svitc = svit[side]
|
||||
rows = len(svitc)
|
||||
if rows < dxyz[yp] + 2:
|
||||
svitc.extend([[] for i in range(dxyz[yp] + 2 - rows)])
|
||||
vert[zp] = (half_chord + exyz[zp]) * dir[zp]
|
||||
print(dssxyz, half_chord, exyz, dir)
|
||||
for j in range(dxyz[yp] + 2):
|
||||
vert[yp] = (j * dssxyz[yp] - half_chord - exyz[yp]) * dir[yp]
|
||||
for i in range(dxyz[xp] + 2):
|
||||
vert[xp] = (i * dssxyz[xp] - half_chord - exyz[xp]) * dir[xp]
|
||||
if (side == 5) or ((i < dxyz[xp] + 1 and j < dxyz[yp] + 1) and (side < 4 or (i and j))):
|
||||
print(side, vert)
|
||||
svitc[j].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
else:
|
||||
for j in range(steps):
|
||||
v, v2, mv2 = uvlt[j]
|
||||
tv2mh = 1./3. * v2 - 0.5
|
||||
hv2 = 0.5 * v2
|
||||
|
||||
if j == hemi:
|
||||
# Jump over non-edge row vertex indices
|
||||
if ey:
|
||||
ryi += yer
|
||||
if ez:
|
||||
rzi += zer
|
||||
|
||||
for i in range(steps):
|
||||
u, u2, mu2 = uvlt[i]
|
||||
x = u * mv2
|
||||
y = v * mu2
|
||||
z = radius * sqrt(u2 * tv2mh - hv2 + 1.)
|
||||
|
||||
for side, (xp, yp, zp, dir) in enumerate(sides):
|
||||
svitc = svit[side]
|
||||
ri = rzi if side < 4 else ryi
|
||||
|
||||
vert[xp] = x
|
||||
vert[yp] = y
|
||||
vert[zp] = z
|
||||
exr = exyz[xp]
|
||||
eyr = exyz[yp]
|
||||
|
||||
if (side == 5) or (i < arcdiv and j < arcdiv and (side < 4 or (i and j or odd_aligned))):
|
||||
vert[0] = (vert[0] + copysign(ex, vert[0])) * dir[0]
|
||||
vert[1] = (vert[1] + copysign(ey, vert[1])) * dir[1]
|
||||
vert[2] = (vert[2] + copysign(ez, vert[2])) * dir[2]
|
||||
rv = tuple(vert)
|
||||
|
||||
if exr and i == hemi:
|
||||
rx = vert[xp] # save xp
|
||||
vert[xp] = rxi = (-exr - half_chord) * dir[xp]
|
||||
if axis_aligned:
|
||||
svitc[ri].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
if subdiv:
|
||||
offsetx = dssxyz[xp] * dir[xp]
|
||||
for k in range(dxyz[xp]):
|
||||
vert[xp] += offsetx
|
||||
svitc[ri].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
if eyr and j == hemi and axis_aligned:
|
||||
vert[xp] = rxi
|
||||
vert[yp] = -eyr * dir[yp]
|
||||
svitc[hemi].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
if subdiv:
|
||||
offsety = dssxyz[yp] * dir[yp]
|
||||
ry = vert[yp]
|
||||
for k in range(dxyz[yp]):
|
||||
vert[yp] += offsety
|
||||
svitc[hemi + axis_aligned + k].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
vert[yp] = ry
|
||||
for k in range(dxyz[xp]):
|
||||
vert[xp] += offsetx
|
||||
svitc[hemi].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
if subdiv & ALL:
|
||||
for l in range(dxyz[yp]):
|
||||
vert[yp] += offsety
|
||||
svitc[hemi + axis_aligned + l].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
vert[yp] = ry
|
||||
vert[xp] = rx # restore
|
||||
|
||||
if eyr and j == hemi:
|
||||
vert[yp] = (-eyr - half_chord) * dir[yp]
|
||||
if axis_aligned:
|
||||
svitc[hemi].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
if subdiv:
|
||||
offsety = dssxyz[yp] * dir[yp]
|
||||
for k in range(dxyz[yp]):
|
||||
vert[yp] += offsety
|
||||
if exr and i == hemi and not axis_aligned and subdiv & ALL:
|
||||
vert[xp] = rxi
|
||||
for l in range(dxyz[xp]):
|
||||
vert[xp] += offsetx
|
||||
svitc[hemi + k].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
vert[xp] = rx
|
||||
svitc[hemi + axis_aligned + k].append(len(verts))
|
||||
verts.append(tuple(vert))
|
||||
|
||||
svitc[ri].append(len(verts))
|
||||
verts.append(rv)
|
||||
ryi += 1
|
||||
rzi += 1
|
||||
|
||||
# Complete svit edges (shared vertices)
|
||||
# Sides' right edge
|
||||
for side, rows in enumerate(svit[:4]):
|
||||
for j, row in enumerate(rows[:-1]):
|
||||
svit[3 if not side else side - 1][j].append(row[0])
|
||||
# Sides' top edge
|
||||
for j, row in enumerate(svit[5]):
|
||||
if not j:
|
||||
for col in row:
|
||||
svit[0][-1].append(col)
|
||||
if j == len(svit[5]) - 1:
|
||||
for col in reversed(row):
|
||||
svit[2][-1].append(col)
|
||||
svit[3][-1].insert(0, row[0])
|
||||
svit[1][-1].append(row[-1])
|
||||
if odd_aligned:
|
||||
for side in svit[:4]:
|
||||
side[-1].append(-1)
|
||||
# Bottom edges
|
||||
if odd_aligned:
|
||||
svit[4].insert(0, [-1] + svit[2][0][-2::-1] + [-1])
|
||||
for i, col in enumerate(svit[3][0][:-1]):
|
||||
svit[4][i + 1].insert(0, col)
|
||||
svit[4][i + 1].append(svit[1][0][-i - 2])
|
||||
svit[4].append([-1] + svit[0][0][:-1] + [-1])
|
||||
else:
|
||||
svit[4][0].extend(svit[2][0][::-1])
|
||||
for i, col in enumerate(svit[3][0][1:-1]):
|
||||
svit[4][i + 1].insert(0, col)
|
||||
svit[4][i + 1].append(svit[1][0][-i - 2])
|
||||
svit[4][-1].extend(svit[0][0])
|
||||
|
||||
# Build faces
|
||||
faces = []
|
||||
if not axis_aligned:
|
||||
hemi -= 1
|
||||
for side, rows in enumerate(svit):
|
||||
xp, yp = sides[side][:2]
|
||||
oa4 = odd_aligned and side == 4
|
||||
if oa4: # special case
|
||||
hemi += 1
|
||||
for j, row in enumerate(rows[:-1]):
|
||||
tri = odd_aligned and (oa4 and not j or rows[j+1][-1] < 0)
|
||||
for i, vi in enumerate(row[:-1]):
|
||||
# odd_aligned triangle corners
|
||||
if vi < 0:
|
||||
if not j and not i:
|
||||
faces.append((row[i+1], rows[j+1][i+1], rows[j+1][i]))
|
||||
elif oa4 and not i and j == len(rows) - 2:
|
||||
faces.append((vi, row[i+1], rows[j+1][i+1]))
|
||||
elif tri and i == len(row) - 2:
|
||||
if j:
|
||||
faces.append((vi, row[i+1], rows[j+1][i]))
|
||||
else:
|
||||
if oa4 or arcdiv > 1:
|
||||
faces.append((vi, rows[j+1][i+1], rows[j+1][i]))
|
||||
else:
|
||||
faces.append((vi, row[i+1], rows[j+1][i]))
|
||||
# subdiv = EDGES (not ALL)
|
||||
elif subdiv and len(rows[j + 1]) < len(row) and (i >= hemi):
|
||||
if (i == hemi):
|
||||
faces.append((vi, row[i+1+dxyz[xp]], rows[j+1+dxyz[yp]][i+1+dxyz[xp]], rows[j+1+dxyz[yp]][i]))
|
||||
elif i > hemi + dxyz[xp]:
|
||||
faces.append((vi, row[i+1], rows[j+1][i+1-dxyz[xp]], rows[j+1][i-dxyz[xp]]))
|
||||
elif subdiv and len(rows[j + 1]) > len(row) and (i >= hemi):
|
||||
if (i > hemi):
|
||||
faces.append((vi, row[i+1], rows[j+1][i+1+dxyz[xp]], rows[j+1][i+dxyz[xp]]))
|
||||
elif subdiv and len(row) < len(rows[0]) and i == hemi:
|
||||
pass
|
||||
else:
|
||||
# Most faces...
|
||||
faces.append((vi, row[i+1], rows[j+1][i+1], rows[j+1][i]))
|
||||
if oa4:
|
||||
hemi -= 1
|
||||
|
||||
return verts, faces
|
||||
|
||||
from bpy.props import BoolProperty, EnumProperty, FloatProperty, FloatVectorProperty, IntProperty
|
||||
|
||||
class AddRoundCube(bpy.types.Operator):
|
||||
"""Add Round Cube Primitive"""
|
||||
bl_idname = 'mesh.primitive_round_cube_add'
|
||||
bl_label = 'Add Round Cube'
|
||||
bl_description = 'Add mesh primitives: Quadsphere, Capsule, Rounded Cuboid, 3D Grid'
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
sanity_check_verts = 200000
|
||||
|
||||
radius = FloatProperty(
|
||||
name = 'Radius',
|
||||
description = 'Radius of vertices for sphere, capsule or cuboid bevel',
|
||||
default = 1.0, min = 0.0, soft_min=0.01, step=10
|
||||
)
|
||||
|
||||
size = FloatVectorProperty(
|
||||
name = 'Size',
|
||||
description = 'Size',
|
||||
subtype = 'XYZ',
|
||||
)
|
||||
|
||||
arc_div = IntProperty(
|
||||
name = 'Arc Divisions',
|
||||
description = 'Arc curve divisions, per quadrant; 0 = derive from Linear',
|
||||
default = 4, min = 0
|
||||
)
|
||||
|
||||
lin_div = FloatProperty(
|
||||
name = 'Linear Divisions',
|
||||
description = 'Linear unit divisions (Edges/Faces); 0 = derive from Arc',
|
||||
default = 0.0, min = 0.0, step=100, precision=1
|
||||
)
|
||||
|
||||
div_type = EnumProperty(
|
||||
name = 'Type',
|
||||
description = 'Division type',
|
||||
items = (
|
||||
('CORNERS', 'Corners', 'Sphere / Corners'),
|
||||
('EDGES', 'Edges', 'Sphere / Corners and extruded edges (size)'),
|
||||
('ALL', 'All', 'Sphere / Corners, extruded edges and faces (size)')),
|
||||
default = 'CORNERS',
|
||||
)
|
||||
|
||||
odd_axis_align = BoolProperty(
|
||||
name='Odd Axis Align',
|
||||
description = 'Align odd arc divisions with axes (Note: triangle corners!)',
|
||||
)
|
||||
|
||||
no_limit = BoolProperty(
|
||||
name='No Limit',
|
||||
description = 'Do not limit to '+str(sanity_check_verts)+' vertices (sanity check)',
|
||||
)
|
||||
|
||||
preset = EnumProperty(
|
||||
name = 'Presets',
|
||||
items = (
|
||||
('CUSTOM', 'Custom', 'Round Cube'),
|
||||
('SPHERE', 'Sphere', 'Quadsphere'),
|
||||
('CAPSULE', 'Capsule', 'Capsule'),
|
||||
('CUBOID', 'Cube', 'Rounded Cuboid'),
|
||||
('3DGRID', 'Grid', '3D Grid Cube')),
|
||||
default = 'CUSTOM', options={'HIDDEN'}
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
if self.preset == 'SPHERE':
|
||||
self.radius = 1.0
|
||||
self.size = (0.,0.,0.)
|
||||
self.arc_div = max(self.arc_div, 4)
|
||||
self.lin_div = 0.
|
||||
self.div_type = 'CORNERS'
|
||||
elif self.preset == 'CAPSULE':
|
||||
self.radius = 0.5
|
||||
self.size = (0.,0.,3.)
|
||||
self.arc_div = max(self.arc_div, 4)
|
||||
self.lin_div = 0.
|
||||
self.div_type = 'CORNERS'
|
||||
elif self.preset == 'CUBOID':
|
||||
self.radius = 0.25
|
||||
self.size = (2.,2.,2.)
|
||||
self.arc_div = max(self.arc_div, 4)
|
||||
self.lin_div = 0.
|
||||
self.div_type = 'CORNERS'
|
||||
elif self.preset == '3DGRID':
|
||||
self.radius = 1.0
|
||||
self.arc_div = 1
|
||||
self.lin_div = max(self.lin_div, 5.)
|
||||
self.div_type = 'ALL'
|
||||
self.size = (2.,2.,2.)
|
||||
self.odd_axis_align = False
|
||||
self.preset = 'CUSTOM'
|
||||
|
||||
if self.arc_div <=0 and self.lin_div <= 0:
|
||||
self.report({'ERROR'}, 'Either Arc Divisions or Linear Divisions must be greater than zero!')
|
||||
return {'CANCELLED'}
|
||||
|
||||
if not self.no_limit:
|
||||
arcdiv, lindiv, vert_count = round_cube(self.radius, self.arc_div, self.lin_div, self.size, self.div_type, self.odd_axis_align, True)
|
||||
if vert_count > self.sanity_check_verts:
|
||||
self.report({'ERROR'}, 'More than '+str(self.sanity_check_verts)+' vertices! Check "No Limit" to proceed')
|
||||
return {'CANCELLED'}
|
||||
|
||||
verts, faces = round_cube(self.radius, self.arc_div, self.lin_div, self.size, self.div_type, self.odd_axis_align)
|
||||
|
||||
mesh = bpy.data.meshes.new('Roundcube')
|
||||
mesh.from_pydata(verts,[],faces)
|
||||
object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def draw(self, context):
|
||||
|
||||
arcdiv, lindiv, vert_count = round_cube(self.radius, self.arc_div, self.lin_div, self.size, self.div_type, self.odd_axis_align, True)
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.prop(self, 'radius')
|
||||
row = layout.row()
|
||||
row.column().prop(self, 'size', expand=True)
|
||||
|
||||
box = layout.box()
|
||||
row = box.row()
|
||||
row.alignment = 'CENTER'
|
||||
row.scale_y = 0.1
|
||||
row.label('Divisions')
|
||||
row = box.row()# align=True)
|
||||
col = row.column()
|
||||
col.alignment = 'RIGHT'
|
||||
col.label('Arc:')
|
||||
col.prop(self, 'arc_div', text="")
|
||||
col.label('[ {} ]'.format(arcdiv))
|
||||
col = row.column()
|
||||
col.alignment = 'RIGHT'
|
||||
col.label('Linear:')
|
||||
col.prop(self, 'lin_div', text="")
|
||||
col.label('[ {:.3g} ]'.format(lindiv))
|
||||
box.row().prop(self, 'div_type')
|
||||
row = box.row()
|
||||
row.active = arcdiv % 2
|
||||
row.prop(self, 'odd_axis_align')
|
||||
|
||||
row = layout.row()
|
||||
row.alert = vert_count > self.sanity_check_verts
|
||||
row.prop(self, 'no_limit', text='No limit ({})'.format(vert_count))
|
||||
|
||||
class INFO_MT_mesh_round_cube_add(bpy.types.Menu):
|
||||
bl_idname = 'INFO_MT_mesh_round_cube_add'
|
||||
bl_label = 'Round Cube'
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.operator_context = 'INVOKE_REGION_WIN'
|
||||
layout.operator(AddRoundCube.bl_idname, text = 'Custom', icon='MOD_SUBSURF')
|
||||
layout.operator(AddRoundCube.bl_idname, text = 'Sphere', icon='META_BALL').preset = 'SPHERE'
|
||||
layout.operator(AddRoundCube.bl_idname, text = 'Capsule', icon='META_ELLIPSOID').preset = 'CAPSULE'
|
||||
layout.operator(AddRoundCube.bl_idname, text = 'Cube', icon='META_CUBE').preset = 'CUBOID'
|
||||
layout.operator(AddRoundCube.bl_idname, text = 'Grid', icon='META_CUBE').preset = '3DGRID'
|
||||
|
|
@ -1,26 +1,5 @@
|
|||
# ***** 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 LICENCE BLOCK *****
|
||||
'''
|
||||
"name": "Regular Solids",
|
||||
"author": "DreamPainter",
|
||||
"version": (2, 0),
|
||||
'''
|
||||
# GPL # "author": "DreamPainter"
|
||||
|
||||
import bpy
|
||||
from bpy.props import FloatProperty,EnumProperty,BoolProperty
|
||||
from math import sqrt
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
# GPL Original by Fourmadmen
|
||||
|
||||
import bpy
|
||||
from mathutils import *
|
||||
from math import *
|
||||
from bpy.props import *
|
||||
|
||||
# Create a new mesh (object) from verts/edges/faces.
|
||||
# verts/edges/faces ... List of vertices/edges/faces for the
|
||||
# new mesh (as used in from_pydata).
|
||||
# name ... Name of the new mesh (& object).
|
||||
def create_mesh_object(context, verts, edges, faces, name):
|
||||
|
||||
# Create new mesh
|
||||
mesh = bpy.data.meshes.new(name)
|
||||
|
||||
# Make a mesh from a list of verts/edges/faces.
|
||||
mesh.from_pydata(verts, edges, faces)
|
||||
|
||||
# Update mesh geometry after adding stuff.
|
||||
mesh.update()
|
||||
|
||||
from bpy_extras import object_utils
|
||||
return object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
if not vertIdx1 or not vertIdx2:
|
||||
return None
|
||||
|
||||
if len(vertIdx1) < 2 and len(vertIdx2) < 2:
|
||||
return None
|
||||
|
||||
fan = False
|
||||
if (len(vertIdx1) != len(vertIdx2)):
|
||||
if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
|
||||
fan = True
|
||||
else:
|
||||
return None
|
||||
|
||||
total = len(vertIdx2)
|
||||
|
||||
if closed:
|
||||
# Bridge the start with the end.
|
||||
if flipped:
|
||||
face = [
|
||||
vertIdx1[0],
|
||||
vertIdx2[0],
|
||||
vertIdx2[total - 1]]
|
||||
if not fan:
|
||||
face.append(vertIdx1[total - 1])
|
||||
faces.append(face)
|
||||
|
||||
else:
|
||||
face = [vertIdx2[0], vertIdx1[0]]
|
||||
if not fan:
|
||||
face.append(vertIdx1[total - 1])
|
||||
face.append(vertIdx2[total - 1])
|
||||
faces.append(face)
|
||||
|
||||
# Bridge the rest of the faces.
|
||||
for num in range(total - 1):
|
||||
if flipped:
|
||||
if fan:
|
||||
face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
|
||||
else:
|
||||
face = [vertIdx2[num], vertIdx1[num],
|
||||
vertIdx1[num + 1], vertIdx2[num + 1]]
|
||||
faces.append(face)
|
||||
else:
|
||||
if fan:
|
||||
face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
|
||||
else:
|
||||
face = [vertIdx1[num], vertIdx2[num],
|
||||
vertIdx2[num + 1], vertIdx1[num + 1]]
|
||||
faces.append(face)
|
||||
|
||||
return faces
|
||||
|
||||
|
||||
# @todo Clean up vertex&face creation process a bit.
|
||||
|
||||
def add_star(points, outer_radius, inner_radius, height):
|
||||
PI_2 = pi * 2
|
||||
z_axis = (0, 0, 1)
|
||||
|
||||
verts = []
|
||||
faces = []
|
||||
|
||||
segments = points * 2
|
||||
|
||||
half_height = height / 2.0
|
||||
|
||||
vert_idx_top = len(verts)
|
||||
verts.append(Vector((0.0, 0.0, half_height)))
|
||||
|
||||
vert_idx_bottom = len(verts)
|
||||
verts.append(Vector((0.0, 0.0, -half_height)))
|
||||
|
||||
edgeloop_top = []
|
||||
edgeloop_bottom = []
|
||||
|
||||
for index in range(segments):
|
||||
quat = Quaternion(z_axis, (index / segments) * PI_2)
|
||||
|
||||
if index % 2:
|
||||
# Uneven
|
||||
radius = outer_radius
|
||||
else:
|
||||
# Even
|
||||
radius = inner_radius
|
||||
|
||||
edgeloop_top.append(len(verts))
|
||||
vec = quat * Vector((radius, 0, half_height))
|
||||
verts.append(vec)
|
||||
|
||||
edgeloop_bottom.append(len(verts))
|
||||
vec = quat * Vector((radius, 0, -half_height))
|
||||
verts.append(vec)
|
||||
|
||||
|
||||
|
||||
faces_top = createFaces([vert_idx_top], edgeloop_top, closed=True)
|
||||
faces_outside = createFaces(edgeloop_top, edgeloop_bottom, closed=True)
|
||||
faces_bottom = createFaces([vert_idx_bottom], edgeloop_bottom,
|
||||
flipped=True, closed=True)
|
||||
|
||||
faces.extend(faces_top)
|
||||
faces.extend(faces_outside)
|
||||
faces.extend(faces_bottom)
|
||||
|
||||
return verts, faces
|
||||
|
||||
class AddStar(bpy.types.Operator):
|
||||
"""Add a star mesh"""
|
||||
bl_idname = "mesh.primitive_star_add"
|
||||
bl_label = "Simple Star"
|
||||
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
|
||||
|
||||
points = IntProperty(name="Points",
|
||||
description="Number of points for the star",
|
||||
min=2,
|
||||
max=256,
|
||||
default=5)
|
||||
outer_radius = FloatProperty(name="Outer Radius",
|
||||
description="Outer radius of the star",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=1.0)
|
||||
innter_radius = FloatProperty(name="Inner Radius",
|
||||
description="Inner radius of the star",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=0.5)
|
||||
height = FloatProperty(name="Height",
|
||||
description="Height of the star",
|
||||
min=0.01,
|
||||
max=9999.0,
|
||||
default=0.5)
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
verts, faces = add_star(
|
||||
self.points,
|
||||
self.outer_radius,
|
||||
self.innter_radius,
|
||||
self.height)
|
||||
|
||||
obj = create_mesh_object(context, verts, [], faces, "Star")
|
||||
|
||||
return {'FINISHED'}
|
|
@ -1,8 +1,5 @@
|
|||
'''
|
||||
"name": "Add Mesh: SuperToroid",
|
||||
"author": "DreamPainter",
|
||||
"version": (1, 0, 0),
|
||||
'''
|
||||
# GPL # "author": "DreamPainter"
|
||||
|
||||
import bpy
|
||||
from bpy.props import FloatProperty,BoolProperty,IntProperty
|
||||
from math import pi, cos, sin
|
||||
|
@ -28,18 +25,7 @@ def create_mesh_object(context, verts, edges, faces, name):
|
|||
return object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
# Connects two equally long vertex rows with faces.
|
||||
# Returns a list of the new faces (list of lists)
|
||||
#
|
||||
# vertIdx1 ... First vertex list (list of vertex indices).
|
||||
# vertIdx2 ... Second vertex list (list of vertex indices).
|
||||
# closed ... Creates a loop (first & last are closed).
|
||||
# flipped ... Invert the normal of the face(s).
|
||||
#
|
||||
# Note: You can set vertIdx1 to a single vertex index to create
|
||||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
||||
|
|
|
@ -1,30 +1,4 @@
|
|||
# +---------------------------------------------------------+
|
||||
# | Copyright (c) 2005-2010 Anthony D'Agostino |
|
||||
# | http://home.comcast.net/~chronosphere |
|
||||
# | scorpius@netzero.com |
|
||||
# | February 12, 2005 |
|
||||
# | Newell Teapot Generator |
|
||||
# | Adds the famous missing primitive to Blender |
|
||||
# +---------------------------------------------------------+
|
||||
|
||||
# ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# "version": (1, 0, 0)
|
||||
# GPL # Author, Anthony D'Agostino
|
||||
|
||||
import bpy
|
||||
from bpy.props import IntProperty
|
||||
|
|
|
@ -1,30 +1,5 @@
|
|||
# +---------------------------------------------------------+
|
||||
# | Copyright (c) 2005-2010 Anthony D'Agostino |
|
||||
# | http://home.comcast.net/~chronosphere |
|
||||
# | scorpius@netzero.com |
|
||||
# | February 12, 2005 |
|
||||
# | Torus Knot Generator |
|
||||
# | Adds the famous missing primitive to Blender |
|
||||
# +---------------------------------------------------------+
|
||||
# GPL # Author, Anthony D'Agostino
|
||||
|
||||
# ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# "version": (1, 0, 0)
|
||||
import bpy, mathutils, math
|
||||
|
||||
def create_mesh_object(context, verts, edges, faces, name):
|
||||
|
|
|
@ -1,34 +1,5 @@
|
|||
# add_mesh_twisted_torus.py Copyright (C) 2009-2010, Paulo Gomes
|
||||
# tuga3d {at} gmail {dot} com
|
||||
# add twisted torus to the blender 2.50 add->mesh menu
|
||||
# ***** 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 LICENCE BLOCK *****
|
||||
#twisted torus by Paulo_Gomes
|
||||
# "version": (0, 11, 1)
|
||||
# GPL # by Paulo_Gomes
|
||||
|
||||
"""
|
||||
Usage:
|
||||
|
||||
* Launch from Add Mesh menu
|
||||
|
||||
* Modify parameters as desired or keep defaults
|
||||
"""
|
||||
import bpy
|
||||
from bpy.props import *
|
||||
|
||||
|
@ -54,18 +25,6 @@ def create_mesh_object(context, verts, edges, faces, name):
|
|||
return object_utils.object_data_add(context, mesh, operator=None)
|
||||
|
||||
# A very simple "bridge" tool.
|
||||
# Connects two equally long vertex rows with faces.
|
||||
# Returns a list of the new faces (list of lists)
|
||||
#
|
||||
# vertIdx1 ... First vertex list (list of vertex indices).
|
||||
# vertIdx2 ... Second vertex list (list of vertex indices).
|
||||
# closed ... Creates a loop (first & last are closed).
|
||||
# flipped ... Invert the normal of the face(s).
|
||||
#
|
||||
# Note: You can set vertIdx1 to a single vertex index to create
|
||||
# a fan/star of faces.
|
||||
# Note: If both vertex idx list are the same length they have
|
||||
# to have at least 2 vertices.
|
||||
|
||||
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
|
||||
faces = []
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
# GPL # Originals by meta-androcto, Pablo Vazquez, Liero, Richard Wilks
|
||||
|
||||
import bpy
|
||||
import bmesh
|
||||
from bpy.props import StringProperty, FloatProperty, BoolProperty, FloatVectorProperty
|
||||
|
||||
# add the mesh as an object into the scene with this utility module
|
||||
from bpy_extras import object_utils
|
||||
|
||||
|
||||
|
||||
def object_origin(width, height, depth):
|
||||
"""
|
||||
This function takes inputs and returns vertex and face arrays.
|
||||
no actual mesh data creation is done here.
|
||||
"""
|
||||
|
||||
verts = [(+0.0, +0.0, +0.0)
|
||||
]
|
||||
|
||||
faces = []
|
||||
|
||||
# apply size
|
||||
for i, v in enumerate(verts):
|
||||
verts[i] = v[0] * width, v[1] * depth, v[2] * height
|
||||
|
||||
return verts, faces
|
||||
|
||||
class AddVert(bpy.types.Operator):
|
||||
'''Add a Single Vertice to Edit Mode'''
|
||||
bl_idname = "mesh.primitive_vert_add"
|
||||
bl_label = "Single Vert"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
mesh = bpy.data.meshes.new("Vert")
|
||||
mesh.vertices.add(1)
|
||||
|
||||
from bpy_extras import object_utils
|
||||
object_utils.object_data_add(context, mesh, operator=None)
|
||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
class AddEmptyVert(bpy.types.Operator):
|
||||
'''Add an Object Origin to Edit Mode'''
|
||||
bl_idname = "mesh.primitive_emptyvert_add"
|
||||
bl_label = "Empty Object Origin"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
mesh = bpy.data.meshes.new("Vert")
|
||||
mesh.vertices.add(1)
|
||||
|
||||
from bpy_extras import object_utils
|
||||
object_utils.object_data_add(context, mesh, operator=None)
|
||||
bpy.ops.object.mode_set(mode = 'EDIT')
|
||||
bpy.ops.mesh.delete(type='VERT')
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
def Add_Symmetrical_Empty():
|
||||
|
||||
bpy.ops.mesh.primitive_plane_add(enter_editmode = True)
|
||||
|
||||
sempty = bpy.context.object
|
||||
sempty.name = "SymmEmpty"
|
||||
|
||||
# check if we have a mirror modifier, otherwise add
|
||||
if (sempty.modifiers and sempty.modifiers['Mirror']):
|
||||
pass
|
||||
else:
|
||||
bpy.ops.object.modifier_add(type ='MIRROR')
|
||||
|
||||
# Delete all!
|
||||
bpy.ops.mesh.select_all(action='TOGGLE')
|
||||
bpy.ops.mesh.select_all(action='TOGGLE')
|
||||
bpy.ops.mesh.delete(type ='VERT')
|
||||
|
||||
def Add_Symmetrical_Vert():
|
||||
|
||||
bpy.ops.mesh.primitive_plane_add(enter_editmode = True)
|
||||
|
||||
sempty = bpy.context.object
|
||||
sempty.name = "SymmVert"
|
||||
|
||||
# check if we have a mirror modifier, otherwise add
|
||||
if (sempty.modifiers and sempty.modifiers['Mirror']):
|
||||
pass
|
||||
else:
|
||||
bpy.ops.object.modifier_add(type ='MIRROR')
|
||||
|
||||
# Delete all!
|
||||
bpy.ops.mesh.select_all(action='TOGGLE')
|
||||
bpy.ops.mesh.select_all(action='TOGGLE')
|
||||
bpy.ops.mesh.merge(type='CENTER')
|
||||
|
||||
class AddSymmetricalEmpty(bpy.types.Operator):
|
||||
|
||||
bl_idname = "mesh.primitive_symmetrical_empty_add"
|
||||
bl_label = "Add Symmetrical Object Origin"
|
||||
bl_description = "Object Origin with a Mirror Modifier for symmetrical modeling"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
mirror = bpy.context.object.modifiers['Mirror']
|
||||
|
||||
layout.prop(mirror,'use_clip', text="Use Clipping")
|
||||
|
||||
layout.label("Mirror Axis")
|
||||
row = layout.row(align=True)
|
||||
row.prop(mirror, "use_x")
|
||||
row.prop(mirror, "use_y")
|
||||
row.prop(mirror, "use_z")
|
||||
|
||||
def execute(self, context):
|
||||
Add_Symmetrical_Empty()
|
||||
return {'FINISHED'}
|
||||
|
||||
class AddSymmetricalVert(bpy.types.Operator):
|
||||
|
||||
bl_idname = "mesh.primitive_symmetrical_vert_add"
|
||||
bl_label = "Add Symmetrical Origin & Vert"
|
||||
bl_description = "Object Origin with a Mirror Modifier for symmetrical modeling"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
mirror = bpy.context.object.modifiers['Mirror']
|
||||
|
||||
layout.prop(mirror,'use_clip', text="Use Clipping")
|
||||
|
||||
layout.label("Mirror Axis")
|
||||
row = layout.row(align=True)
|
||||
row.prop(mirror, "use_x")
|
||||
row.prop(mirror, "use_y")
|
||||
row.prop(mirror, "use_z")
|
||||
|
||||
def execute(self, context):
|
||||
Add_Symmetrical_Vert()
|
||||
return {'FINISHED'}
|
Loading…
Reference in New Issue