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:
Brendon Murphy 2015-05-01 10:52:03 +08:00 committed by Sybren A. Stüvel
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
20 changed files with 1502 additions and 960 deletions

View File

@ -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():

View File

@ -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'}

View File

@ -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 = []

View File

@ -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'}

View File

@ -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 = []

View File

@ -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 = []

View File

@ -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()
'''

View File

@ -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'}

View File

@ -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'}
################################

View File

@ -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'}

View File

@ -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()
'''

View File

@ -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'}

View File

@ -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'

View File

@ -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

View File

@ -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'}

View File

@ -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 = []

View File

@ -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

View File

@ -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):

View File

@ -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 = []

View File

@ -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'}