-
Campbell Barton authored
Some files needed to be changed manually.
Campbell Barton authoredSome files needed to be changed manually.
add_mesh_beam_builder.py 24.21 KiB
# SPDX-License-Identifier: GPL-2.0-or-later
# Author: revolt_randy, Jambay
# Create "Beam" primitives. Based on original script by revolt_randy
import bpy
from bpy.types import Operator
from bpy.props import (
BoolProperty,
EnumProperty,
FloatProperty,
IntProperty,
StringProperty,
)
from bpy_extras import object_utils
# #####################
# Create vertices for end of mesh
#
# y_off - verts y-axis origin
#
# returns:
# endVs - x,y,z list
def beamEndVs(sRef, y_off):
thick = sRef.beamW * 2
if sRef.Type == '2': # swap width and height for C shape
bEndX2 = sRef.beamZ / 2
bEndXInr = ((sRef.beamZ - thick) / 2)
bEndZ2 = sRef.beamX / 2
bEndZInr = ((sRef.beamX - thick) / 2)
else:
bEndX2 = sRef.beamX / 2
bEndXInr = ((sRef.beamX - thick) / 2)
bEndZ2 = sRef.beamZ / 2
bEndZInr = ((sRef.beamZ - thick) / 2)
endVs = []
# outer ...
endVs.append((bEndX2, y_off, bEndZ2))
endVs.append((-bEndX2, y_off, bEndZ2))
endVs.append((-bEndX2, y_off, -bEndZ2))
endVs.append((bEndX2, y_off, -bEndZ2))
# innner ...
endVs.append((bEndXInr, y_off, bEndZInr))
endVs.append((-bEndXInr, y_off, bEndZInr))
endVs.append((-bEndXInr, y_off, -bEndZInr))
endVs.append((bEndXInr, y_off, -bEndZInr))
return endVs
# #####################
# Create End Faces
#
# verts_list - list of vertices
#
# returns:
# beamFs, a list of tuples defining the end faces.
def beamEndFaces(verts_list):
beamFs = []
num_of_verts = int(len(verts_list) / 2)
# Create list of faces
for index in range(num_of_verts):
faces_temp = []
if index == (num_of_verts - 1):
faces_temp.append(verts_list[index])
faces_temp.append(verts_list[index - index])
faces_temp.append(verts_list[index + 1])
faces_temp.append(verts_list[index * 2 + 1])
else:
faces_temp.append(verts_list[index])
faces_temp.append(verts_list[index + 1])
faces_temp.append(verts_list[index + num_of_verts + 1])
faces_temp.append(verts_list[index + num_of_verts])
beamFs.append(tuple(faces_temp))
return beamFs
# #####################
# Bridge vertices to create side faces.
#
# front_verts - front face vertices
# back_verts - back face vertices
# front & back must be ordered in same direction
# with respect to y-axis
#
# returns:
# sideFaces, a list of the bridged faces
def beamSides(front_verts, back_verts):
sideFaces = []
num_of_faces = (len(front_verts))
# add first value to end of lists for looping
front_verts.append(front_verts[0])
back_verts.append(back_verts[0])
# Build the faces
for index in range(num_of_faces):
facestemp = (front_verts[index], front_verts[index + 1], back_verts[index + 1], back_verts[index])
sideFaces.append(facestemp)
return sideFaces
# #####################
# Creates a box beam
#
# returns:
# beamVs - x, y, z, location of each vertice
# beamFs - vertices that make up each face
def create_beam(sRef):
frontVs = []
frontFs = []
backVs = []
y_off = sRef.beamY / 2 # offset from center for vertices
frontVs = beamEndVs(sRef, y_off)
backVs = beamEndVs(sRef, -y_off)
# Combine vertices
beamVs = frontVs + backVs
# Create front face
numofverts = len(frontVs)
verts_front_list = []
for index in range(numofverts):
verts_front_list.append(index)
frontFs = beamEndFaces(verts_front_list)
# Create back face
faces_back_temp = []
verts_back_list = []
numofverts = len(backVs)
for index in range(numofverts):
verts_back_list.append(index + numofverts)
faces_back_temp = beamEndFaces(verts_back_list)
# Create side faces
faces_side_temp = []
# Object has thickness, create list of outside vertices
numofverts = len(verts_front_list)
halfVerts = int(numofverts / 2)
frontVs = verts_front_list[0:halfVerts]
backVs = verts_back_list[0:halfVerts]
faces_side_temp = beamSides(frontVs, backVs)
# Create list of inside vertices
frontVs = verts_front_list[halfVerts:numofverts]
backVs = verts_back_list[halfVerts:numofverts]
faces_side_temp += beamSides(frontVs, backVs)
# Combine all faces
beamFs = frontFs + faces_back_temp + faces_side_temp
return beamVs, beamFs
# #####################
# Taper/angle faces of beam.
# inner vert toward outer vert
# based on percentage of taper.
#
# returns:
# adVert - the calculated vertex
def beamSlant(sRef, outV, inV):
bTaper = 100 - sRef.edgeA
# calculate variance & adjust vertex
deltaV = ((inV - outV) / 100)
adVert = outV + (deltaV * bTaper)
return adVert
# #####################
# Modify location to shape beam.
#
# verts - tuples for one end of beam
#
# returns:
# verts - modified tuples for beam shape.
def beamSquareEnds(sRef, verts):
# match 5th & 6th z locations to 1st & 2nd
vert_orig = verts[0]
vert_temp = verts[4]
vert_x = beamSlant(sRef, vert_orig[0], vert_temp[0])
verts[4] = (vert_x, vert_temp[1], vert_orig[2])
vert_orig = verts[1]
vert_temp = verts[5]
vert_x = beamSlant(sRef, vert_orig[0], vert_temp[0])
verts[5] = (vert_x, vert_temp[1], vert_orig[2])
return verts
# #####################
#
# Create U shaped beam
# Shared with C shape - see beamEndVs
# for sizing and rotate in addBeamObj.
#
# returns:
# beamVs - vertice x, y, z, locations
# beamFs - face vertices
def create_u_beam(sRef):
# offset vertices from center
y_off = sRef.beamY / 2
frontVtemp = []
frontFtemp = []
frontVlist = []
backVtemp = []
backFtemp = []
backVlist = []
sideFs = []
frontVtemp = beamEndVs(sRef, y_off) # Box beam
frontVtemp = beamSquareEnds(sRef, frontVtemp) # U shape
backVtemp = beamEndVs(sRef, -y_off)
backVtemp = beamSquareEnds(sRef, backVtemp)
beamVs = frontVtemp + backVtemp
# Create front face
for index in range(len(frontVtemp)): # Build vert list
frontVlist.append(index)
frontFtemp = beamEndFaces(frontVlist)
frontFtemp = frontFtemp[1:4] # Remove 1st face
# Create back face
numofverts = len(backVtemp)
for index in range(numofverts): # Build vertex list
backVlist.append(index + numofverts)
backFtemp = beamEndFaces(backVlist)
backFtemp = backFtemp[1:4] # Remove face
# Create list vertices for outside faces
numofverts = int(len(frontVlist))
halfVerts = int(numofverts / 2)
frontVtemp = frontVlist[0:halfVerts]
backVtemp = backVlist[0:halfVerts]
sideFs = beamSides(frontVtemp, backVtemp)
sideFs = sideFs[1:] # Remove face
# Create inside verts
frontVtemp = frontVlist[halfVerts:numofverts]
backVtemp = backVlist[halfVerts:numofverts]
sideFs += beamSides(frontVtemp, backVtemp)
sideFs = sideFs[0:3] + sideFs[4:] # Remove face
# fill in faces
sideFs.append((0, 4, 12, 8))
sideFs.append((5, 1, 9, 13))
beamFs = frontFtemp + backFtemp + sideFs # Combine faces
return beamVs, beamFs
# #####################
# returns:
# verts_final - x, y, z, location of each vertice
# faces_final - vertices that make up each face
def create_L_beam(sRef):
thick = sRef.beamW
# offset vertices from center
x_off = sRef.beamX / 2
y_off = sRef.beamY / 2
z_off = sRef.beamZ / 2
# Create temporarylists to hold vertices locations
verts_front_temp = []
verts_back_temp = []
# Create front vertices by calculation
verts_front_temp = [
(-x_off, -y_off, z_off),
(-(x_off - thick), -y_off, z_off),
(-(x_off - thick), -y_off, -(z_off - thick)),
(x_off, -y_off, -(z_off - thick)),
(x_off, -y_off, -z_off),
(-x_off, -y_off, -z_off)
]
# Adjust taper
vert_outside = verts_front_temp[0]
vert_inside = verts_front_temp[1]
vert_taper = beamSlant(sRef, vert_outside[0], vert_inside[0])
verts_front_temp[1] = [vert_taper, vert_inside[1], vert_inside[2]]
vert_outside = verts_front_temp[4]
vert_inside = verts_front_temp[3]
vert_taper = beamSlant(sRef, vert_outside[2], vert_inside[2])
verts_front_temp[3] = [vert_inside[0], vert_inside[1], vert_taper]
# Create back vertices by calculation
verts_back_temp = [
(-x_off, y_off, z_off),
(-(x_off - thick), y_off, z_off),
(-(x_off - thick), y_off, -(z_off - thick)),
(x_off, y_off, -(z_off - thick)),
(x_off, y_off, -z_off),
(-x_off, y_off, -z_off)
]
# Adjust taper
vert_outside = verts_back_temp[0]
vert_inside = verts_back_temp[1]
vert_taper = beamSlant(sRef, vert_outside[0], vert_inside[0])
verts_back_temp[1] = [vert_taper, vert_inside[1], vert_inside[2]]
vert_outside = verts_back_temp[4]
vert_inside = verts_back_temp[3]
vert_taper = beamSlant(sRef, vert_outside[2], vert_inside[2])
verts_back_temp[3] = [vert_inside[0], vert_inside[1], vert_taper]
verts_final = verts_front_temp + verts_back_temp
# define end faces, only 4 so just coded
faces_front_temp = []
faces_back_temp = []
faces_side_temp = []
faces_front_temp = [(0, 1, 2, 5), (2, 3, 4, 5)]
faces_back_temp = [(6, 7, 8, 11), (8, 9, 10, 11)]
verts_front_list = []
verts_back_list = []
num_of_verts = len(verts_front_temp)
# build lists of back and front verts for beamSides function
for index in range(num_of_verts):
verts_front_list.append(index)
for index in range(num_of_verts):
verts_back_list.append(index + 6)
faces_side_temp = beamSides(verts_front_list, verts_back_list)
faces_final = faces_front_temp + faces_back_temp + faces_side_temp
return verts_final, faces_final
# #####################
# returns:
# verts_final - a list of tuples of the x, y, z, location of each vertice
# faces_final - a list of tuples of the vertices that make up each face
def create_T_beam(sRef):
thick = sRef.beamW
# Get offset of vertices from center
x_off = sRef.beamX / 2
y_off = sRef.beamY / 2
z_off = sRef.beamZ / 2
thick_off = thick / 2
# Create temporarylists to hold vertices locations
verts_front_temp = []
verts_back_temp = []
# Create front vertices
verts_front_temp = [
(-x_off, -y_off, z_off),
(-thick_off, -y_off, z_off),
(thick_off, -y_off, z_off),
(x_off, -y_off, z_off),
(x_off, -y_off, z_off - thick),
(thick_off, -y_off, z_off - thick),
(thick_off, -y_off, -z_off),
(-thick_off, -y_off, -z_off),
(-thick_off, -y_off, z_off - thick),
(-x_off, -y_off, z_off - thick)
]
# Adjust taper
vert_outside = verts_front_temp[0]
vert_inside = verts_front_temp[9]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_front_temp[9] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_front_temp[3]
vert_inside = verts_front_temp[4]
verts_front_temp[4] = [vert_inside[0], vert_inside[1], vert_taper]
# Adjust taper of bottom of beam, so 0 the center
# now becomes vert_outside, and vert_inside is calculated
# 1/2 way towards center
vert_outside = (0, -y_off, -z_off)
vert_inside = verts_front_temp[6]
vert_taper = (beamSlant(sRef, vert_outside[0], vert_inside[0]))
verts_front_temp[6] = [vert_taper, vert_inside[1], vert_inside[2]]
vert_outside = (0, -y_off, -z_off)
vert_inside = verts_front_temp[7]
vert_taper = beamSlant(sRef, vert_outside[0], vert_inside[0])
verts_front_temp[7] = [vert_taper, vert_inside[1], vert_inside[2]]
# Create fack vertices by calculation
verts_back_temp = [
(-x_off, y_off, z_off),
(-thick_off, y_off, z_off),
(thick_off, y_off, z_off),
(x_off, y_off, z_off),
(x_off, y_off, z_off - thick),
(thick_off, y_off, z_off - thick),
(thick_off, y_off, -z_off),
(-thick_off, y_off, -z_off),
(-thick_off, y_off, z_off - thick),
(-x_off, y_off, z_off - thick)
]
# Adjust taper
vert_outside = verts_back_temp[0]
vert_inside = verts_back_temp[9]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_back_temp[9] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_back_temp[3]
vert_inside = verts_back_temp[4]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_back_temp[4] = [vert_inside[0], vert_inside[1], vert_taper]
# Adjust taper of bottom of beam, so 0 the center
# now becomes vert_outside, and vert_inside is calculated
# 1/2 way towards center
vert_outside = (0, -y_off, -z_off)
vert_inside = verts_back_temp[6]
vert_taper = (beamSlant(sRef, vert_outside[0], vert_inside[0]))
verts_back_temp[6] = [vert_taper, vert_inside[1], vert_inside[2]]
vert_outside = (0, -y_off, -z_off)
vert_inside = verts_back_temp[7]
vert_taper = (beamSlant(sRef, vert_outside[0], vert_inside[0]))
verts_back_temp[7] = [vert_taper, vert_inside[1], vert_inside[2]]
verts_final = verts_front_temp + verts_back_temp
# define end faces, only 8 so just coded
faces_front_temp = []
faces_back_temp = []
faces_side_temp = []
faces_front_temp = [(0, 1, 8, 9), (1, 2, 5, 8),
(2, 3, 4, 5), (5, 6, 7, 8)]
faces_back_temp = [(10, 11, 18, 19), (11, 12, 15, 18),
(12, 13, 14, 15), (15, 16, 17, 18)]
verts_front_list = []
verts_back_list = []
num_of_verts = len(verts_front_temp)
# build lists of back and front verts for beamSides function
for index in range(num_of_verts):
verts_front_list.append(index)
for index in range(num_of_verts):
verts_back_list.append(index + 10)
faces_side_temp = beamSides(verts_front_list, verts_back_list)
faces_final = faces_front_temp + faces_back_temp + faces_side_temp
return verts_final, faces_final
# #####################
# returns:
# verts_final - a list of tuples of the x, y, z, location of each vertice
# faces_final - a list of tuples of the vertices that make up each face
def create_I_beam(sRef):
thick = sRef.beamW
# Get offset of vertices from center
x_off = sRef.beamX / 2
y_off = sRef.beamY / 2
z_off = sRef.beamZ / 2
thick_off = thick / 2
# Create temporarylists to hold vertices locations
verts_front_temp = []
verts_back_temp = []
# Create front vertices by calculation
verts_front_temp = [
(-x_off, -y_off, z_off),
(-thick_off, -y_off, z_off),
(thick_off, -y_off, z_off),
(x_off, -y_off, z_off),
(x_off, -y_off, z_off - thick),
(thick_off, -y_off, z_off - thick),
(thick_off, -y_off, -z_off + thick),
(x_off, -y_off, -z_off + thick),
(x_off, -y_off, -z_off),
(thick_off, -y_off, -z_off),
(-thick_off, -y_off, -z_off),
(-x_off, -y_off, -z_off),
(-x_off, -y_off, -z_off + thick),
(-thick_off, -y_off, -z_off + thick),
(-thick_off, -y_off, z_off - thick),
(-x_off, -y_off, z_off - thick)
]
# Adjust taper
vert_outside = verts_front_temp[0]
vert_inside = verts_front_temp[15]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_front_temp[15] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_front_temp[3]
vert_inside = verts_front_temp[4]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_front_temp[4] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_front_temp[8]
vert_inside = verts_front_temp[7]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_front_temp[7] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_front_temp[11]
vert_inside = verts_front_temp[12]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_front_temp[12] = [vert_inside[0], vert_inside[1], vert_taper]
# Create back vertices by calculation
verts_back_temp = [
(-x_off, y_off, z_off),
(-thick_off, y_off, z_off),
(thick_off, y_off, z_off),
(x_off, y_off, z_off),
(x_off, y_off, z_off - thick),
(thick_off, y_off, z_off - thick),
(thick_off, y_off, -z_off + thick),
(x_off, y_off, -z_off + thick),
(x_off, y_off, -z_off),
(thick_off, y_off, -z_off),
(-thick_off, y_off, -z_off),
(-x_off, y_off, -z_off),
(-x_off, y_off, -z_off + thick),
(-thick_off, y_off, -z_off + thick),
(-thick_off, y_off, z_off - thick),
(-x_off, y_off, z_off - thick)
]
# Adjust taper
vert_outside = verts_back_temp[0]
vert_inside = verts_back_temp[15]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_back_temp[15] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_back_temp[3]
vert_inside = verts_back_temp[4]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_back_temp[4] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_back_temp[8]
vert_inside = verts_back_temp[7]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_back_temp[7] = [vert_inside[0], vert_inside[1], vert_taper]
vert_outside = verts_back_temp[11]
vert_inside = verts_back_temp[12]
vert_taper = (beamSlant(sRef, vert_outside[2], vert_inside[2]))
verts_back_temp[12] = [vert_inside[0], vert_inside[1], vert_taper]
verts_final = verts_front_temp + verts_back_temp
# define end faces, only 7 per end, so just coded
faces_front_temp = []
faces_back_temp = []
faces_side_temp = []
faces_front_temp = [(0, 1, 14, 15), (1, 2, 5, 14),
(2, 3, 4, 5), (6, 7, 8, 9),
(6, 9, 10, 13), (12, 13, 10, 11),
(5, 6, 13, 14)]
faces_back_temp = [(16, 17, 30, 31), (17, 18, 21, 30),
(18, 19, 20, 21), (22, 23, 24, 25),
(22, 25, 26, 29), (28, 29, 26, 27),
(21, 22, 29, 30)]
verts_front_list = []
verts_back_list = []
num_of_verts = len(verts_front_temp)
# build lists of back and front verts for beamSides function
for index in range(num_of_verts):
verts_front_list.append(index)
for index in range(num_of_verts):
verts_back_list.append(index + 16)
faces_side_temp = beamSides(verts_front_list, verts_back_list)
faces_final = faces_front_temp + faces_back_temp + faces_side_temp
return verts_final, faces_final
# ######################
#
# Generate beam mesh.
def addBeamMesh(sRef, context):
verts = []
faces = []
# type of beam to add
if sRef.Type == '0':
verts, faces = create_beam(sRef)
elif sRef.Type == '1':
verts, faces = create_u_beam(sRef)
elif sRef.Type == '2':
verts, faces = create_u_beam(sRef)
elif sRef.Type == '3':
verts, faces = create_L_beam(sRef)
elif sRef.Type == '4':
verts, faces = create_I_beam(sRef)
elif sRef.Type == '5':
verts, faces = create_T_beam(sRef)
else: # unknown type, use default.
verts, faces = create_beam(sRef)
beamMesh = bpy.data.meshes.new("Beam")
beamMesh.from_pydata(verts, [], faces)
beamMesh.update(calc_edges=True)
return beamMesh
# ######################
# Create a beam primitive.
#
# UI functions and object creation.
class addBeam(Operator, object_utils.AddObjectHelper):
bl_idname = "mesh.add_beam"
bl_label = "Beam Builder"
bl_description = "Create beam meshes of various profiles"
bl_options = {'REGISTER', 'UNDO', 'PRESET'}
Beam : BoolProperty(name = "Beam",
default = True,
description = "Beam")
change : BoolProperty(name = "Change",
default = False,
description = "change Beam")
Type: EnumProperty(
items=(
('0', "Box Profile", "Square Beam"),
("1", "U Profile", "U Profile Beam"),
("2", "C Profile", "C Profile Beam"),
("3", "L Profile", "L Profile Beam"),
("4", "I Profile", "I Profile Beam"),
("5", "T Profile", "T Profile Beam")
),
description="Beam form"
)
beamZ: FloatProperty(
name="Height",
min=0.01,
#max=100,
default=1
)
beamX: FloatProperty(
name="Width",
min=0.01,
#max=100,
default=.5
)
beamY: FloatProperty(
name="Depth",
min=0.01,
#max=100,
default=2
)
beamW: FloatProperty(
name="Thickness",
min=0.01,
#max=1,
default=0.1
)
edgeA: IntProperty(
name="Taper",
min=0,
#max=100,
default=0,
description="Angle beam edges"
)
def draw(self, context):
layout = self.layout
box = layout.box()
split = box.split(factor=0.85, align=True)
split.prop(self, "Type", text="")
box.prop(self, "beamZ")
box.prop(self, "beamX")
box.prop(self, "beamY")
box.prop(self, "beamW")
if self.Type != '0':
box.prop(self, "edgeA")
if self.change == False:
# generic transform props
box = layout.box()
box.prop(self, 'align', expand=True)
box.prop(self, 'location', expand=True)
box.prop(self, 'rotation', expand=True)
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
if bpy.context.mode == "OBJECT":
if context.selected_objects != [] and context.active_object and \
(context.active_object.data is not None) and ('Beam' in context.active_object.data.keys()) and \
(self.change == True):
obj = context.active_object
oldmesh = obj.data
oldmeshname = obj.data.name
mesh = addBeamMesh(self, context)
obj.data = mesh
for material in oldmesh.materials:
obj.data.materials.append(material)
bpy.data.meshes.remove(oldmesh)
obj.data.name = oldmeshname
else:
mesh = addBeamMesh(self, context)
obj = object_utils.object_data_add(context, mesh, operator=self)
if self.Type == '2': # Rotate C shape
bpy.ops.transform.rotate(value=1.570796, constraint_axis=[False, True, False])
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
obj.data["Beam"] = True
obj.data["change"] = False
for prm in BeamParameters():
obj.data[prm] = getattr(self, prm)
if bpy.context.mode == "EDIT_MESH":
active_object = context.active_object
name_active_object = active_object.name
bpy.ops.object.mode_set(mode='OBJECT')
mesh = addBeamMesh(self, context)
obj = object_utils.object_data_add(context, mesh, operator=self)
obj.select_set(True)
active_object.select_set(True)
bpy.context.view_layer.objects.active = active_object
bpy.ops.object.join()
context.active_object.name = name_active_object
bpy.ops.object.mode_set(mode='EDIT')
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
return {'FINISHED'}
def BeamParameters():
BeamParameters = [
"Type",
"beamZ",
"beamX",
"beamY",
"beamW",
"edgeA",
]
return BeamParameters