Skip to content
Snippets Groups Projects
add_mesh_pipe_joint.py 42.7 KiB
Newer Older
            locY = cos(curVertAngle) * radius
            locZ = 0.0

            # Rotate circle
            locZ = locX * cos(pi / 2.0 + angle2)
            locX = locX * sin(pi / 2.0 + angle2)

            loopArm2.append(len(verts))
            # Add translated circle
            verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])

        # Create end circle (center pipe)
        baseEndLocX = branch3Length * sin(angle3)
        baseEndLocZ = branch3Length * cos(angle3)
        for vertIdx in range(div):
            curVertAngle = vertIdx * (2.0 * pi / div)
            # Create circle
            locX = sin(curVertAngle) * radius
            locY = cos(curVertAngle) * radius
            locZ = 0.0

            # Rotate circle
            locZ = locX * cos(pi / 2.0 + angle3)
            locX = locX * sin(pi / 2.0 + angle3)

            loopArm3.append(len(verts))
            # Add translated circle
            verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])

        # Create faces
        faces.extend(createFaces(loopMainStart, loopJoint1))
        faces.extend(createFaces(loopJoint2, loopArm1))
        faces.extend(createFaces(loopJoint3, loopArm2))
        faces.extend(createFaces(loopJoint4, loopArm3))

Martin Buerbaum's avatar
Martin Buerbaum committed
        obj = createObject(context, verts, faces, "Cross Joint", edit)

        # Store 'recall' properties in the object.
        recall_prop_list = {
Martin Buerbaum's avatar
Martin Buerbaum committed
            "edit": True,
            "radius": radius,
            "div": div,
            "angle1": angle1,
            "angle2": angle2,
            "angle3": angle3,
            "startLength": startLength,
            "branch1Length": branch1Length,
            "branch2Length": branch2Length,
            "branch3Length": branch3Length}
        obj_store_recall_properties(obj, self, recall_prop_list)

        return {'FINISHED'}


class AddNJoint(bpy.types.Operator):
    '''Add a N-Joint mesh'''
    # Create the vertices and polygons for a regular n-joint.
    bl_idname = "mesh.primitive_n_joint_add"
    bl_label = "Add Pipe N-Joint"
    bl_options = {'REGISTER', 'UNDO'}

Martin Buerbaum's avatar
Martin Buerbaum committed
    # edit - Whether to add or update.
    edit = BoolProperty(name="",
        description="", 
        default=False,
        options={'HIDDEN'})

    radius = FloatProperty(name="Radius",
        description="The radius of the pipe.",
        default=1.0,
        min=0.01,
        max=100.0,
        unit="LENGTH")
    div = IntProperty(name="Divisions",
        description="Number of vertices (divisions).",
        default=32,
        min=4,
        max=256)
    number = IntProperty(name="Arms/Joints",
        description="Number of joints/arms",
        default=5,
        min=2,
        max=99999)
    length = FloatProperty(name="Length",
        description="Length of each joint/arm",
        default=3.0,
        min=0.01,
        max=100.0,
        unit="LENGTH")

    def execute(self, context):
Martin Buerbaum's avatar
Martin Buerbaum committed
        edit = self.properties.edit
        radius = self.properties.radius
        div = self.properties.div
        number = self.properties.number
        length = self.properties.length

        if (div % 2):
            # Odd vertice number not supported (yet).
            return {'CANCELLED'}

        if (number < 2):
            return {'CANCELLED'}

        verts = []
        faces = []

        loopsEndCircles = []
        loopsJointsTemp = []
        loopsJoints = []

        vertTemp1 = None
        vertTemp2 = None

        angleDiv = (2.0 * pi / number)

        # Create vertices for the end circles.
        for num in range(number):
            circle = []
            # Create start circle
            angle = num * angleDiv

            baseEndLocX = length * sin(angle)
            baseEndLocZ = length * cos(angle)
            for vertIdx in range(div):
                curVertAngle = vertIdx * (2.0 * pi / div)
                # Create circle
                locX = sin(curVertAngle) * radius
                locY = cos(curVertAngle) * radius
                locZ = 0.0

                # Rotate circle
                locZ = locX * cos(pi / 2.0 + angle)
                locX = locX * sin(pi / 2.0 + angle)

                circle.append(len(verts))
                # Add translated circle
                verts.append([baseEndLocX + locX, locY, baseEndLocZ + locZ])

            loopsEndCircles.append(circle)

            # Create vertices for the joint circles.
            loopJoint = []
            for vertIdx in range(div):
                curVertAngle = vertIdx * (2.0 * pi / div)
                locX = sin(curVertAngle)
                locY = cos(curVertAngle)

                skipVert = False
                # Store pole vertices
                if vertIdx == 0:
                    if (num == 0):
                        vertTemp2 = len(verts)
                    else:
                        skipVert = True
                elif vertIdx == div / 2:
                    # @todo: This will possibly break if we
                    # ever support odd divisions.
                    if (num == 0):
                        vertTemp1 = len(verts)
                    else:
                        skipVert = True

                if not skipVert:
                    if (vertIdx > div / 2):
                        locZ = -locX * tan((pi - angleDiv) / 2.0)
                        loopJoint.append(len(verts))

                        # Rotate the vert
                        cosAng = cos(-angle)
                        sinAng = sin(-angle)
                        LocXnew = locX * cosAng - locZ * sinAng
                        LocZnew = locZ * cosAng + locX * sinAng
                        locZ = LocZnew
                        locX = LocXnew

                        verts.append([
                            locX * radius,
                            locY * radius,
                            locZ * radius])
                    else:
                        # These two vertices will only be
                        # added the very first time.
                        if vertIdx == 0 or vertIdx == div / 2:
                            verts.append([locX * radius, locY * radius, locZ])

            loopsJointsTemp.append(loopJoint)

        # Create complete loops (loopsJoints) out of the
        # double number of half loops in loopsJointsTemp.
        for halfLoopIdx in range(len(loopsJointsTemp)):
            if (halfLoopIdx == len(loopsJointsTemp) - 1):
                idx1 = halfLoopIdx
                idx2 = 0
            else:
                idx1 = halfLoopIdx
                idx2 = halfLoopIdx + 1

            loopJoint = []
            loopJoint.append(vertTemp2)
            loopJoint.extend(reversed(loopsJointsTemp[idx2]))
            loopJoint.append(vertTemp1)
            loopJoint.extend(loopsJointsTemp[idx1])

            loopsJoints.append(loopJoint)

        # Create faces from the two
        # loop arrays (loopsJoints -> loopsEndCircles).
        for loopIdx in range(len(loopsEndCircles)):
            faces.extend(
                createFaces(loopsJoints[loopIdx],
                loopsEndCircles[loopIdx]))

Martin Buerbaum's avatar
Martin Buerbaum committed
        obj = createObject(context, verts, faces, "N Joint", edit)

        # Store 'recall' properties in the object.
        recall_prop_list = {
Martin Buerbaum's avatar
Martin Buerbaum committed
            "edit": True,
            "radius": radius,
            "div": div,
            "number": number,
            "length": length}
        obj_store_recall_properties(obj, self, recall_prop_list)

        return {'FINISHED'}


class INFO_MT_mesh_pipe_joints_add(bpy.types.Menu):
    # Define the "Pipe Joints" menu
    bl_idname = "INFO_MT_mesh_pipe_joints_add"
    bl_label = "Pipe Joints"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_REGION_WIN'
        layout.operator("mesh.primitive_elbow_joint_add",
            text="Pipe Elbow")
        layout.operator("mesh.primitive_tee_joint_add",
            text="Pipe T-Joint")
        layout.operator("mesh.primitive_wye_joint_add",
            text="Pipe Y-Joint")
        layout.operator("mesh.primitive_cross_joint_add",
            text="Pipe Cross-Joint")
        layout.operator("mesh.primitive_n_joint_add",

################################

import space_info

# Define "Pipe Joints" menu
menu_func = (lambda self,
    context: self.layout.menu("INFO_MT_mesh_pipe_joints_add", icon="PLUGIN"))


def register():
    # Register the operators/menus.
    bpy.types.register(AddElbowJoint)
    bpy.types.register(AddTeeJoint)
    bpy.types.register(AddWyeJoint)
    bpy.types.register(AddCrossJoint)
    bpy.types.register(AddNJoint)
    bpy.types.register(INFO_MT_mesh_pipe_joints_add)

    # Add "Pipe Joints" menu to the "Add Mesh" menu
    space_info.INFO_MT_mesh_add.append(menu_func)


def unregister():
    # Unregister the operators/menus.
    bpy.types.unregister(AddElbowJoint)
    bpy.types.unregister(AddTeeJoint)
    bpy.types.unregister(AddWyeJoint)
    bpy.types.unregister(AddCrossJoint)
    bpy.types.unregister(AddNJoint)
    bpy.types.unregister(INFO_MT_mesh_pipe_joints_add)

    # Remove "Pipe Joints" menu from the "Add Mesh" menu.
    space_info.INFO_MT_mesh_add.remove(menu_func)

if __name__ == "__main__":
    register()