Skip to content
Snippets Groups Projects
add_mesh_archimedean_solids.py 49.8 KiB
Newer Older
  • Learn to ignore specific revisions
  •     #tri_xp_yn_zn.append(vb_idx)
        top_down_1_1 = [va1_idx, vb1_idx]
        top_down_1_2 = [va2_idx, vb2_idx]
        quad_15 = [va1_idx, vb1_idx, vb2_idx, va2_idx]
        hex_1_zp.extend([va1_idx, va2_idx])
        hex_1_zn.extend([vb1_idx, vb2_idx])
    
        va, vb = subdivide_edge_2_cuts(verts_cube[2], verts_cube[6], oside)
        va1, vb1 = va + Vector((bevel_size, 0, 0)), vb + Vector((bevel_size, 0, 0))
        va2, vb2 = va + Vector((0, bevel_size, 0)), vb + Vector((0, bevel_size, 0))
        va1_idx, vb1_idx = len(verts), len(verts) + 1
        va2_idx, vb2_idx = len(verts) + 2, len(verts) + 3
        verts.extend([va1, vb1, va2, vb2])
        #tri_xn_yn_zp.append(va_idx)
        #tri_xn_yn_zn.append(vb_idx)
        top_down_2_1 = [va1_idx, vb1_idx]
        top_down_2_2 = [va2_idx, vb2_idx]
        quad_26 = [vb1_idx, va1_idx, va2_idx, vb2_idx]
        hex_2_zp.extend([va2_idx, va1_idx])
        hex_2_zn.extend([vb2_idx, vb1_idx])
    
        va, vb = subdivide_edge_2_cuts(verts_cube[3], verts_cube[7], oside)
        va1, vb1 = va + Vector((bevel_size, 0, 0)), vb + Vector((bevel_size, 0, 0))
        va2, vb2 = va + Vector((0, -bevel_size, 0)), vb + Vector((0, -bevel_size, 0))
        va1_idx, vb1_idx = len(verts), len(verts) + 1
        va2_idx, vb2_idx = len(verts) + 2, len(verts) + 3
        verts.extend([va1, vb1, va2, vb2])
        #tri_xn_yp_zp.append(va_idx)
        #tri_xn_yp_zn.append(vb_idx)
        top_down_3_1 = [va1_idx, vb1_idx]
        top_down_3_2 = [va2_idx, vb2_idx]
        quad_37 = [va1_idx, vb1_idx, vb2_idx, va2_idx]
        hex_3_zp.extend([va1_idx, va2_idx])
        hex_3_zn.extend([vb1_idx, vb2_idx])
        
        # Bottom edges ####
        bevel_z = Vector((0.0, 0.0, bevel_size))
    
        va, vb = subdivide_edge_2_cuts(verts_cube[4], verts_cube[5], oside)
        va1, vb1 = va + Vector((-bevel_size, 0, 0)), vb + Vector((-bevel_size, 0, 0))
        va2, vb2 = va + bevel_z, vb + bevel_z
        va1_idx, vb1_idx = len(verts), len(verts) + 1
        va2_idx, vb2_idx = len(verts) + 2, len(verts) + 3
        verts.extend([va1, vb1, va2, vb2])
        #tri_xp_yp_zn.append(va_idx)
        #tri_xp_yn_zn.append(vb_idx)
        oct_bot.extend([va1_idx, vb1_idx])
        quad_45_zn = [vb1_idx, va1_idx, va2_idx, vb2_idx]
        hex_0_zn.extend([va2_idx, va1_idx])
        hex_1_zn.extend([vb2_idx, vb1_idx])
    
        va, vb = subdivide_edge_2_cuts(verts_cube[5], verts_cube[6], oside)
        va1, vb1 = va + Vector((0, bevel_size, 0)), vb + Vector((0, bevel_size, 0))
        va2, vb2 = va + bevel_z, vb + bevel_z
        va1_idx, vb1_idx = len(verts), len(verts) + 1
        va2_idx, vb2_idx = len(verts) + 2, len(verts) + 3
        verts.extend([va1, vb1, va2, vb2])
        #tri_xp_yn_zn.append(va_idx)
        #tri_xn_yn_zn.append(vb_idx)
        oct_bot.extend([va1_idx, vb1_idx])
        quad_56_zn = [vb1_idx, va1_idx, va2_idx, vb2_idx]
        hex_1_zn.extend([va1_idx, va2_idx])
        hex_2_zn.extend([vb2_idx, vb1_idx])
    
        va, vb = subdivide_edge_2_cuts(verts_cube[6], verts_cube[7], oside)
        va1, vb1 = va + Vector((bevel_size, 0, 0)), vb + Vector((bevel_size, 0, 0))
        va2, vb2 = va + bevel_z, vb + bevel_z
        va1_idx, vb1_idx = len(verts), len(verts) + 1
        va2_idx, vb2_idx = len(verts) + 2, len(verts) + 3
        verts.extend([va1, vb1, va2, vb2])
        #tri_xn_yn_zn.append(va_idx)
        #tri_xn_yp_zn.append(vb_idx)
        oct_bot.extend([va1_idx, vb1_idx])
        quad_67_zn = [vb1_idx, va1_idx, va2_idx, vb2_idx]
        hex_2_zn.extend([va1_idx, va2_idx])
        hex_3_zn.extend([vb2_idx, vb1_idx])
    
        va, vb = subdivide_edge_2_cuts(verts_cube[7], verts_cube[4], oside)
        va1, vb1 = va + Vector((0, -bevel_size, 0)), vb + Vector((0, -bevel_size, 0))
        va2, vb2 = va + bevel_z, vb + bevel_z
        va1_idx, vb1_idx = len(verts), len(verts) + 1
        va2_idx, vb2_idx = len(verts) + 2, len(verts) + 3
        verts.extend([va1, vb1, va2, vb2])
        #tri_xn_yp_zn.append(va_idx)
        #tri_xp_yp_zn.append(vb_idx)
        oct_bot.extend([va1_idx, vb1_idx])
        quad_74_zn = [vb1_idx, va1_idx, va2_idx, vb2_idx]
        hex_3_zn.extend([va1_idx, va2_idx])
        hex_0_zn.extend([vb1_idx, vb2_idx])
    
        # Octagon polygons (n-gons)
        oct_0 = [
            top_down_0_2[1], top_down_0_2[0], quad_01_zp[3], quad_01_zp[2],
            top_down_1_2[0], top_down_1_2[1], quad_45_zn[3], quad_45_zn[2]]
        oct_1 = [
            top_down_1_1[1], top_down_1_1[0], quad_12_zp[3], quad_12_zp[2],
            top_down_2_1[0], top_down_2_1[1], quad_56_zn[3], quad_56_zn[2]]
        oct_2 = [
            top_down_2_2[1], top_down_2_2[0], quad_23_zp[3], quad_23_zp[2],
            top_down_3_2[0], top_down_3_2[1], quad_67_zn[3], quad_67_zn[2]]
        oct_3 = [
            top_down_3_1[1], top_down_3_1[0], quad_30_zp[3], quad_30_zp[2],
            top_down_0_1[0], top_down_0_1[1], quad_74_zn[3], quad_74_zn[2]]
    
        # Invert face normals where needed.
        oct_top = invert_face_normal(oct_top)
        hex_0_zp = invert_face_normal(hex_0_zp)
        hex_1_zn = invert_face_normal(hex_1_zn)
        hex_2_zn = invert_face_normal(hex_2_zn)
        hex_3_zn = invert_face_normal(hex_3_zn)
    
        # Quads
        faces.extend([quad_01_zp, quad_12_zp, quad_23_zp, quad_30_zp])
        faces.extend([quad_04, quad_15, quad_26, quad_37])
        faces.extend([quad_45_zn, quad_56_zn, quad_67_zn, quad_74_zn])
    
        if star_ngons:
            # Create stars from octagons.
            ngons = [oct_top, oct_bot, oct_bot, oct_0, oct_1, oct_2, oct_3]
    
            verts, faces_star = get_polygon_center(verts, ngons)
            faces.extend(faces_star)
            
            # Create stars from hexagons.
            # @todo
    
        else:
            # Create quads from octagons.
    
            # The top octagon is the only polygon we don't need to offset.
            oct_quads = ngon_fill(oct_top)
            faces.extend(oct_quads)
    
            ngons = [oct_bot, oct_0, oct_1, oct_2, oct_3]
            for ngon in ngons:
                # offset=1 Offset vertices so QUADS are created with
                # orthagonal edges. Superficial change - Could be omitted.
                oct_quads = ngon_fill(ngon, offset=1)
                faces.extend(oct_quads)
            
            # Create quads from hexagons.
            ngons = [hex_0_zp, hex_1_zp, hex_2_zp, hex_3_zp]
            for ngon in ngons:
                hex_quads = ngon_fill(ngon)
                faces.extend(hex_quads)
    
            hex_quads = ngon_fill(hex_0_zn, offset=2)
            faces.extend(hex_quads)
    
            ngons = [hex_1_zn, hex_2_zn, hex_3_zn]
            for ngon in ngons:
                hex_quads = ngon_fill(ngon, offset=1)
                faces.extend(hex_quads)
    
        return verts, faces
    
    
    class AddTruncatedTetrahedron(bpy.types.Operator):
        '''Add a mesh for a truncated tetrahedron.'''
        bl_idname = 'mesh.primitive_truncated_tetrahedron_add'
        bl_label = 'Add Truncated Tetrahedron'
        bl_description = 'Create a mesh for a truncated tetrahedron.'
        bl_options = {'REGISTER', 'UNDO'}
    
        # edit - Whether to add or update.
        edit = BoolProperty(name='',
            description='',
            default=False,
            options={'HIDDEN'})
        hexagon_side = FloatProperty(name='Hexagon Side',
            description='One length of the hexagon side' \
                ' (on the original tetrahedron edge).',
            min=0.01,
            max=2.0 * sqrt(2.0) - 0.01,
            default=2.0 * sqrt(2.0) / 3.0)
        star_ngons = BoolProperty(name='Star N-Gon',
            description='Create star-shaped hexagons.',
            default=False)
    
        align_matrix = Matrix()
    
    
        def execute(self, context):
            props = self.properties
    
            verts, faces = add_truncated_tetrahedron(
                props.hexagon_side,
                props.star_ngons)
    
    
            if not verts:
                return {'CANCELLED'}
    
    
            obj = create_mesh_object(context, verts, [], faces,
    
                'TrTetrahedron', props.edit, self.align_matrix)
    
    
            # Store 'recall' properties in the object.
            recall_args_list = {
                'edit': True,
                'hexagon_side': props.hexagon_side,
                'star_ngons': props.star_ngons}
            store_recall_properties(obj, self, recall_args_list)
    
            return {'FINISHED'}
    
    
        def invoke(self, context, event):
            self.align_matrix = align_matrix(context)
            self.execute(context)
            return {'FINISHED'}
    
    
    class AddCuboctahedron(bpy.types.Operator):
        '''Add a mesh for a cuboctahedron (truncated cube).'''
        bl_idname = 'mesh.primitive_cuboctahedron_add'
    
        bl_label = 'Add Cuboctahedron or Truncated Cube'
        bl_description = 'Create a mesh for a cuboctahedron (or truncated cube).'
    
        bl_options = {'REGISTER', 'UNDO'}
    
        # edit - Whether to add or update.
        edit = BoolProperty(name='',
            description='',
            default=False,
            options={'HIDDEN'})
        octagon_side = FloatProperty(name='Octagon Side',
            description='One length of the octagon side' \
    
                ' (on the original cube edge).' \
                ' 0: Cuboctahedron, >0: Truncated Cube',
    
            min=0.00,
            max=1.99,
            default=0.0)
        star_ngons = BoolProperty(name='Star N-Gon',
            description='Create star-shaped octagons.',
            default=False)
    
        align_matrix = Matrix()
    
    
        def execute(self, context):
            props = self.properties
    
            verts, faces, name = add_cuboctahedron(
                props.octagon_side,
                props.star_ngons)
    
            if not verts:
                return {'CANCELLED'}
    
    
            obj = create_mesh_object(context, verts, [], faces, name, props.edit, self.align_matrix)
    
    
            # Store 'recall' properties in the object.
            recall_args_list = {
                'edit': True,
                'octagon_side': props.octagon_side,
                'star_ngons': props.star_ngons}
            store_recall_properties(obj, self, recall_args_list)
    
            return {'FINISHED'}
    
    
        def invoke(self, context, event):
            self.align_matrix = align_matrix(context)
            self.execute(context)
            return {'FINISHED'}
    
    
    
    class AddRhombicuboctahedron(bpy.types.Operator):
    
        '''Add a mesh for a rhombicuboctahedron.'''
        bl_idname = 'mesh.primitive_rhombicuboctahedron_add'
    
        bl_label = 'Add Rhombicuboctahedron'
    
        bl_description = 'Create a mesh for a rhombicuboctahedron.'
    
        bl_options = {'REGISTER', 'UNDO'}
    
        # edit - Whether to add or update.
        edit = BoolProperty(name='',
            description='',
            default=False,
            options={'HIDDEN'})
        quad_size = FloatProperty(name="Quad Size",
            description="Size of the orthogonal quad faces.",
            min=0.01,
            max=1.99,
            default=sqrt(2.0) / (1.0 + sqrt(2) / 2.0))
    
        align_matrix = Matrix()
    
    
        def execute(self, context):
            props = self.properties
    
            verts, faces = add_rhombicuboctahedron(props.quad_size)
    
            if not verts:
                return {'CANCELLED'}
    
            obj = create_mesh_object(context, verts, [], faces,
    
                'Rhombicuboctahedron', props.edit, self.align_matrix)
    
    
            # Store 'recall' properties in the object.
            recall_args_list = {
                'edit': True,
                'quad_size': props.quad_size}
            store_recall_properties(obj, self, recall_args_list)
    
            return {'FINISHED'}
    
    
        def invoke(self, context, event):
            self.align_matrix = align_matrix(context)
            self.execute(context)
            return {'FINISHED'}
    
    
    class AddTruncatedOctahedron(bpy.types.Operator):
        '''Add a mesh for a truncated octahedron.'''
        bl_idname = 'mesh.primitive_truncated_octahedron_add'
        bl_label = 'Add Truncated Octahedron'
        bl_description = 'Create a mesh for a truncated octahedron.'
        bl_options = {'REGISTER', 'UNDO'}
    
        # edit - Whether to add or update.
        edit = BoolProperty(name='',
            description='',
            default=False,
            options={'HIDDEN'})
        hexagon_side = FloatProperty(name='Hexagon Side',
            description='One length of the hexagon side' \
                ' (on the original octahedron edge).',
            min=0.01,
            max=sqrt(2) - 0.1,
            default=sqrt(2) / 3.0)
        star_ngons = BoolProperty(name='Star N-Gon',
            description='Create star-shaped hexagons.',
            default=False)
    
        align_matrix = Matrix()
    
    
        def execute(self, context):
            props = self.properties
    
            verts, faces = add_truncated_octahedron(
                props.hexagon_side,
                props.star_ngons)
    
            if not verts:
                return {'CANCELLED'}
    
            obj = create_mesh_object(context, verts, [], faces,
    
                'TrOctahedron', props.edit, self.align_matrix)
    
    
            # Store 'recall' properties in the object.
            recall_args_list = {
                'edit': True,
                'hexagon_side': props.hexagon_side,
                'star_ngons': props.star_ngons}
            store_recall_properties(obj, self, recall_args_list)
    
            return {'FINISHED'}
    
    
        def invoke(self, context, event):
            self.align_matrix = align_matrix(context)
            self.execute(context)
            return {'FINISHED'}
    
    
    class AddTruncatedCuboctahedron(bpy.types.Operator):
        '''Add a mesh for a truncated cuboctahedron.'''
        bl_idname = 'mesh.primitive_truncated_cuboctahedron_add'
        bl_label = 'Add Truncated Cuboctahedron'
        bl_description = 'Create a mesh for a truncated cuboctahedron.'
        bl_options = {'REGISTER', 'UNDO'}
    
        # edit - Whether to add or update.
        edit = BoolProperty(name='',
            description='',
            default=False,
            options={'HIDDEN'})
        octagon_size = FloatProperty(name='Octagon Size',
            description='The size (height/width) of the octagon.',
            min=0.02,
            max=1.99,
            default=2.0 - (2.0 / sqrt(2.0)) * (2.0 / (4.0 / sqrt(2.0) + 1.0)))
        octagon_side = FloatProperty(name='Octagon Side',
            description='One length of the octagon side' \
                ' (on the original cube edge).',
            min=0.01,
            max=1.98,
            default=2.0 / (4.0 / sqrt(2.0) + 1.0))
        star_ngons = BoolProperty(name='Star N-Gon',
            description='Create star-shaped octagons.',
            default=False)
    
        align_matrix = Matrix()
    
    
        def execute(self, context):
            props = self.properties
    
            verts, faces = add_truncated_cuboctahedron(
                props.octagon_size,
                props.octagon_side,
                props.star_ngons)
    
            if not verts:
                return {'CANCELLED'}
    
            obj = create_mesh_object(context, verts, [], faces,
    
                'TrCuboctahedron', props.edit, self.align_matrix)
    
    
            # Store 'recall' properties in the object.
            recall_args_list = {
                'edit': True,
                'octagon_size': props.octagon_size,
                'octagon_side': props.octagon_side,
                'star_ngons': props.star_ngons}
            store_recall_properties(obj, self, recall_args_list)
    
            return {'FINISHED'}
    
    
        def invoke(self, context, event):
            self.align_matrix = align_matrix(context)
            self.execute(context)
            return {'FINISHED'}
    
    class INFO_MT_mesh_archimedean_solids_add(bpy.types.Menu):
        # Define the "Archimedean Solids" menu
        bl_idname = "INFO_MT_mesh_archimedean_solids_add"
        bl_label = "Archimedean Solids"
    
        def draw(self, context):
            layout = self.layout
            layout.operator_context = 'INVOKE_REGION_WIN'
            layout.operator("mesh.primitive_truncated_tetrahedron_add",
                text="Truncated Tetrahedron")
    
            layout.operator("mesh.primitive_cuboctahedron_add",
    
                text="Cuboctahedron or Truncated Cube")
            layout.operator("mesh.primitive_rhombicuboctahedron_add",
    
                text="Rhombicuboctahedron")
    
            layout.operator("mesh.primitive_truncated_octahedron_add",
                text="Truncated Octahedron")
    
            layout.operator("mesh.primitive_truncated_cuboctahedron_add",
                text="Truncated Cuboctahedron")
    
    import space_info
    
    # Define "Archimedean Solids" menu
    menu_func = (lambda self, context: self.layout.menu(
        "INFO_MT_mesh_archimedean_solids_add", icon="PLUGIN"))
    
    
    def register():
        # Register the operators/menus.
        bpy.types.register(AddTruncatedTetrahedron)
    
        bpy.types.register(AddCuboctahedron)
        bpy.types.register(AddRhombicuboctahedron)
    
        bpy.types.register(AddTruncatedOctahedron)
    
        bpy.types.register(AddTruncatedCuboctahedron)
    
        bpy.types.register(INFO_MT_mesh_archimedean_solids_add)
    
        # Add "Archimedean Solids" menu to the "Add Mesh" menu
        space_info.INFO_MT_mesh_add.append(menu_func)
    
    
    def unregister():
        # Unregister the operators/menus.
        bpy.types.unregister(AddTruncatedTetrahedron)
    
        bpy.types.unregister(AddCuboctahedron)
        bpy.types.unregister(AddRhombicuboctahedron)
    
        bpy.types.unregister(AddTruncatedOctahedron)
    
        bpy.types.unregister(AddTruncatedCuboctahedron)
    
        bpy.types.unregister(INFO_MT_mesh_archimedean_solids_add)
    
        # Remove "Archimedean Solids" menu from the "Add Mesh" menu.
        space_info.INFO_MT_mesh_add.remove(menu_func)
    
    if __name__ == "__main__":
        register()