Newer
Older
# GPL # "author": "Pontiac, Fourmadmen, Dreampainter"
Martin Buerbaum
committed
import bpy
from bpy.types import Operator
from mathutils import (
Vector,
Quaternion,
)
from math import cos, sin, pi
from bpy.props import (
FloatProperty,
IntProperty,
Spivak Vladimir (cwolf3d)
committed
BoolProperty,
StringProperty,
from bpy_extras import object_utils
Martin Buerbaum
committed
# 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)
Spivak Vladimir (cwolf3d)
committed
def create_mesh_object(context, self, verts, edges, faces, name):
Martin Buerbaum
committed
# 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()
Martin Buerbaum
committed
Campbell Barton
committed
from bpy_extras import object_utils
Spivak Vladimir (cwolf3d)
committed
return object_utils.object_data_add(context, mesh, operator=self)
Martin Buerbaum
committed
Martin Buerbaum
committed
# A very simple "bridge" tool.
Martin Buerbaum
committed
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
Martin Buerbaum
committed
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
Martin Buerbaum
committed
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
Martin Buerbaum
committed
# @todo Clean up vertex&face creation process a bit.
def add_gem(r1, r2, seg, h1, h2):
"""
r1 = pavilion radius
r2 = crown radius
seg = number of segments
h1 = pavilion height
h2 = crown height
Generates the vertices and faces of the gem
"""
verts = []
Martin Buerbaum
committed
offset = a / 2.0 # Middle between segments
r3 = ((r1 + r2) / 2.0) / cos(offset) # Middle of crown
r4 = (r1 / 2.0) / cos(offset) # Middle of pavilion
h3 = h2 / 2.0 # Middle of crown height
h4 = -h1 / 2.0 # Middle of pavilion height
# Tip
vert_tip = len(verts)
verts.append(Vector((0.0, 0.0, -h1)))
Martin Buerbaum
committed
# Middle vertex of the flat side (crown)
vert_flat = len(verts)
verts.append(Vector((0.0, 0.0, h2)))
Martin Buerbaum
committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
edgeloop_flat = []
for i in range(seg):
s1 = sin(i * a)
s2 = sin(offset + i * a)
c1 = cos(i * a)
c2 = cos(offset + i * a)
verts.append((r4 * s1, r4 * c1, h4)) # Middle of pavilion
verts.append((r1 * s2, r1 * c2, 0.0)) # Pavilion
verts.append((r3 * s1, r3 * c1, h3)) # Middle crown
edgeloop_flat.append(len(verts))
verts.append((r2 * s2, r2 * c2, h2)) # Crown
faces = []
for index in range(seg):
i = index * 4
j = ((index + 1) % seg) * 4
faces.append([j + 2, vert_tip, i + 2, i + 3]) # Tip -> Middle of pav
faces.append([j + 2, i + 3, j + 3]) # Middle of pav -> pav
faces.append([j + 3, i + 3, j + 4]) # Pav -> Middle crown
faces.append([j + 4, i + 3, i + 4, i + 5]) # Crown quads
faces.append([j + 4, i + 5, j + 5]) # Middle crown -> crown
faces_flat = createFaces([vert_flat], edgeloop_flat, closed=True)
faces.extend(faces_flat)
return verts, faces
Martin Buerbaum
committed
def add_diamond(segments, girdle_radius, table_radius,
crown_height, pavilion_height):
Martin Buerbaum
committed
PI_2 = pi * 2.0
z_axis = (0.0, 0.0, -1.0)
verts = []
faces = []
height_flat = crown_height
height_middle = 0.0
height_tip = -pavilion_height
# Middle vertex of the flat side (crown)
vert_flat = len(verts)
verts.append(Vector((0.0, 0.0, height_flat)))
Martin Buerbaum
committed
# Tip
vert_tip = len(verts)
verts.append(Vector((0.0, 0.0, height_tip)))
Martin Buerbaum
committed
verts_flat = []
verts_girdle = []
for index in range(segments):
quat = Quaternion(z_axis, (index / segments) * PI_2)
Martin Buerbaum
committed
# Row for flat side
verts_flat.append(len(verts))
vec = quat @ Vector((table_radius, 0.0, height_flat))
Martin Buerbaum
committed
verts.append(vec)
# Row for the middle/girdle
verts_girdle.append(len(verts))
vec = quat @ Vector((girdle_radius, 0.0, height_middle))
Martin Buerbaum
committed
verts.append(vec)
# Flat face
faces_flat = createFaces([vert_flat], verts_flat, closed=True,
flipped=True)
# Side face
faces_side = createFaces(verts_girdle, verts_flat, closed=True)
# Tip faces
faces_tip = createFaces([vert_tip], verts_girdle, closed=True)
faces.extend(faces_tip)
faces.extend(faces_side)
faces.extend(faces_flat)
return verts, faces
class AddDiamond(Operator, object_utils.AddObjectHelper):
Martin Buerbaum
committed
bl_idname = "mesh.primitive_diamond_add"
bl_label = "Add Diamond"
bl_description = "Construct a diamond mesh"
Martin Buerbaum
committed
Spivak Vladimir (cwolf3d)
committed
Diamond : BoolProperty(name = "Diamond",
default = True,
description = "Diamond")
#### change properties
name : StringProperty(name = "Name",
description = "Name")
change : BoolProperty(name = "Change",
default = False,
description = "change Diamond")
name="Segments",
description="Number of segments for the diamond",
min=3,
max=256,
default=32
)
name="Girdle Radius",
description="Girdle radius of the diamond",
min=0.01,
max=9999.0,
default=1.0
)
name="Table Radius",
description="Girdle radius of the diamond",
min=0.01,
max=9999.0,
default=0.6
)
name="Crown Height",
description="Crown height of the diamond",
min=0.01,
max=9999.0,
default=0.35
)
name="Pavilion Height",
description="Pavilion height of the diamond",
min=0.01,
max=9999.0,
default=0.8
)
Martin Buerbaum
committed
Spivak Vladimir (cwolf3d)
committed
def draw(self, context):
layout = self.layout
box = layout.box()
box.prop(self, "segments")
box.prop(self, "girdle_radius")
box.prop(self, "table_radius")
box.prop(self, "crown_height")
box.prop(self, "pavilion_height")
Martin Buerbaum
committed
if self.change == False:
# generic transform props
box = layout.box()
Spivak Vladimir (cwolf3d)
committed
box.prop(self, 'align', expand=True)
box.prop(self, 'location', expand=True)
box.prop(self, 'rotation', expand=True)
Spivak Vladimir (cwolf3d)
committed
def execute(self, context):
# turn off 'Enter Edit Mode'
use_enter_edit_mode = bpy.context.preferences.edit.use_enter_edit_mode
bpy.context.preferences.edit.use_enter_edit_mode = False
Spivak Vladimir (cwolf3d)
committed
if bpy.context.mode == "OBJECT":
Spivak Vladimir (cwolf3d)
committed
if context.selected_objects != [] and context.active_object and \
('Diamond' in context.active_object.data.keys()) and (self.change == True):
Spivak Vladimir (cwolf3d)
committed
obj = context.active_object
Spivak Vladimir (cwolf3d)
committed
oldmesh = obj.data
oldmeshname = obj.data.name
verts, faces = add_diamond(self.segments,
self.girdle_radius,
self.table_radius,
self.crown_height,
self.pavilion_height)
mesh = bpy.data.meshes.new("TMP")
mesh.from_pydata(verts, [], faces)
mesh.update()
obj.data = mesh
Spivak Vladimir (cwolf3d)
committed
for material in oldmesh.materials:
obj.data.materials.append(material)
bpy.data.meshes.remove(oldmesh)
obj.data.name = oldmeshname
Spivak Vladimir (cwolf3d)
committed
else:
verts, faces = add_diamond(self.segments,
self.girdle_radius,
self.table_radius,
self.crown_height,
self.pavilion_height)
Spivak Vladimir (cwolf3d)
committed
obj = create_mesh_object(context, self, verts, [], faces, "Diamond")
Spivak Vladimir (cwolf3d)
committed
obj.data["Diamond"] = True
obj.data["change"] = False
for prm in DiamondParameters():
obj.data[prm] = getattr(self, prm)
Spivak Vladimir (cwolf3d)
committed
if bpy.context.mode == "EDIT_MESH":
active_object = context.active_object
name_active_object = active_object.name
bpy.ops.object.mode_set(mode='OBJECT')
verts, faces = add_diamond(self.segments,
self.girdle_radius,
self.table_radius,
self.crown_height,
self.pavilion_height)
Spivak Vladimir (cwolf3d)
committed
obj = create_mesh_object(context, self, verts, [], faces, "TMP")
Spivak Vladimir (cwolf3d)
committed
obj.select_set(True)
active_object.select_set(True)
bpy.ops.object.join()
context.active_object.name = name_active_object
bpy.ops.object.mode_set(mode='EDIT')
Martin Buerbaum
committed
if use_enter_edit_mode:
bpy.ops.object.mode_set(mode = 'EDIT')
# restore pre operator state
bpy.context.preferences.edit.use_enter_edit_mode = use_enter_edit_mode
Martin Buerbaum
committed
return {'FINISHED'}
Spivak Vladimir (cwolf3d)
committed
def DiamondParameters():
DiamondParameters = [
"segments",
"girdle_radius",
"table_radius",
"crown_height",
"pavilion_height",
]
return DiamondParameters
class AddGem(Operator, object_utils.AddObjectHelper):
Martin Buerbaum
committed
bl_idname = "mesh.primitive_gem_add"
bl_label = "Add Gem"
bl_description = "Construct an offset faceted gem mesh"
Martin Buerbaum
committed
Spivak Vladimir (cwolf3d)
committed
Gem : BoolProperty(name = "Gem",
default = True,
description = "Gem")
#### change properties
name : StringProperty(name = "Name",
description = "Name")
change : BoolProperty(name = "Change",
default = False,
description = "change Gem")
name="Segments",
description="Longitudial segmentation",
min=3,
max=265,
default=8
)
name="Radius",
description="Radius of the gem",
min=0.01,
max=9999.0,
default=1.0
)
name="Table Radius",
description="Radius of the table(top)",
min=0.01,
max=9999.0,
default=0.6
)
name="Table height",
description="Height of the top half",
min=0.01,
max=9999.0,
default=0.35
)
name="Pavilion height",
description="Height of bottom half",
min=0.01,
max=9999.0,
default=0.8
)
Martin Buerbaum
committed
Spivak Vladimir (cwolf3d)
committed
def draw(self, context):
layout = self.layout
box = layout.box()
box.prop(self, "segments")
box.prop(self, "pavilion_radius")
box.prop(self, "crown_radius")
box.prop(self, "crown_height")
box.prop(self, "pavilion_height")
if self.change == False:
# generic transform props
box = layout.box()
Spivak Vladimir (cwolf3d)
committed
box.prop(self, 'align', expand=True)
box.prop(self, 'location', expand=True)
box.prop(self, 'rotation', expand=True)
Martin Buerbaum
committed
def execute(self, context):
# turn off 'Enter Edit Mode'
use_enter_edit_mode = bpy.context.preferences.edit.use_enter_edit_mode
bpy.context.preferences.edit.use_enter_edit_mode = False
Spivak Vladimir (cwolf3d)
committed
if bpy.context.mode == "OBJECT":
Spivak Vladimir (cwolf3d)
committed
if context.selected_objects != [] and context.active_object and \
('Gem' in context.active_object.data.keys()) and (self.change == True):
Spivak Vladimir (cwolf3d)
committed
obj = context.active_object
Spivak Vladimir (cwolf3d)
committed
oldmesh = obj.data
oldmeshname = obj.data.name
verts, faces = add_gem(
self.pavilion_radius,
self.crown_radius,
self.segments,
self.pavilion_height,
self.crown_height)
mesh = bpy.data.meshes.new("TMP")
mesh.from_pydata(verts, [], faces)
mesh.update()
obj.data = mesh
for material in oldmesh.materials:
obj.data.materials.append(material)
bpy.data.meshes.remove(oldmesh)
obj.data.name = oldmeshname
Spivak Vladimir (cwolf3d)
committed
else:
verts, faces = add_gem(
self.pavilion_radius,
self.crown_radius,
self.segments,
self.pavilion_height,
self.crown_height)
Spivak Vladimir (cwolf3d)
committed
obj = create_mesh_object(context, self, verts, [], faces, "Gem")
Spivak Vladimir (cwolf3d)
committed
obj.data["Gem"] = True
obj.data["change"] = False
for prm in GemParameters():
obj.data[prm] = getattr(self, prm)
Spivak Vladimir (cwolf3d)
committed
if bpy.context.mode == "EDIT_MESH":
active_object = context.active_object
name_active_object = active_object.name
bpy.ops.object.mode_set(mode='OBJECT')
verts, faces = add_gem(
self.pavilion_radius,
self.crown_radius,
self.segments,
self.pavilion_height,
self.crown_height)
Spivak Vladimir (cwolf3d)
committed
obj = create_mesh_object(context, self, verts, [], faces, "TMP")
Spivak Vladimir (cwolf3d)
committed
obj.select_set(True)
active_object.select_set(True)
bpy.ops.object.join()
context.active_object.name = name_active_object
bpy.ops.object.mode_set(mode='EDIT')
Martin Buerbaum
committed
if use_enter_edit_mode:
bpy.ops.object.mode_set(mode = 'EDIT')
# restore pre operator state
bpy.context.preferences.edit.use_enter_edit_mode = use_enter_edit_mode
Martin Buerbaum
committed
return {'FINISHED'}