Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'add_mesh_extra_objects/add_mesh_menger_sponge.py')
-rw-r--r--add_mesh_extra_objects/add_mesh_menger_sponge.py185
1 files changed, 185 insertions, 0 deletions
diff --git a/add_mesh_extra_objects/add_mesh_menger_sponge.py b/add_mesh_extra_objects/add_mesh_menger_sponge.py
new file mode 100644
index 00000000..43c8c57d
--- /dev/null
+++ b/add_mesh_extra_objects/add_mesh_menger_sponge.py
@@ -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'}