1 # SPDX-License-Identifier: MIT
2 # Copyright 2015 Sugiany
6 from bpy_extras
.object_utils
import (
11 from bpy
.props
import (
23 class MengerSponge(object):
33 def __init__(self
, level
):
35 self
.__max
_point
_number
= 3 ** level
36 self
.__vertices
_map
= {}
38 self
.__face
_visibility
= {}
44 self
.__face
_visibility
[(x
, y
, z
)] = [
45 x
== 0 or x
== 2 and (y
== 1 or z
== 1),
46 x
== 2 or x
== 0 and (y
== 1 or z
== 1),
47 y
== 0 or y
== 2 and (x
== 1 or z
== 1),
48 y
== 2 or y
== 0 and (x
== 1 or z
== 1),
49 z
== 0 or z
== 2 and (y
== 1 or x
== 1),
50 z
== 2 or z
== 0 and (y
== 1 or x
== 1),
53 def create(self
, width
, height
):
54 m
= self
.__max
_point
_number
65 self
.__make
_sub
_sponge
(points
, None, self
.__level
)
66 vertices
= self
.__make
_vertices
(width
, height
)
67 return vertices
, self
.__faces
69 def __get_vindex(self
, p
):
70 if p
in self
.__vertices
_map
:
71 return self
.__vertices
_map
[p
]
72 index
= len(self
.__vertices
_map
)
73 self
.__vertices
_map
[p
] = index
76 def __make_vertices(self
, width
, height
):
77 vertices
= [None] * len(self
.__vertices
_map
)
80 w_step
= width
/ self
.__max
_point
_number
81 h_step
= height
/ self
.__max
_point
_number
82 for p
, i
in sorted(self
.__vertices
_map
.items(), key
=lambda x
: x
[1]):
83 vertices
[i
] = mathutils
.Vector([
90 def __make_sub_sponge(self
, cur_points
, face_vis
, depth
):
94 cur_point_indices
= []
96 cur_point_indices
.append(self
.__get
_vindex
(p
))
97 for i
, vis
in enumerate(face_vis
):
100 for vi
in self
.FACE_INDICES
[i
]:
101 f
.append(cur_point_indices
[vi
])
102 self
.__faces
.append(f
)
106 width
= (cur_points
[1][0] - base
[0]) / 3
111 local_vert_map
[(x
, y
, z
)] = (
120 if [x
, y
, z
].count(1) > 1:
123 local_vert_map
[(x
, y
, z
)],
124 local_vert_map
[(x
+ 1, y
, z
)],
125 local_vert_map
[(x
+ 1, y
, z
+ 1)],
126 local_vert_map
[(x
, y
, z
+ 1)],
127 local_vert_map
[(x
, y
+ 1, z
)],
128 local_vert_map
[(x
+ 1, y
+ 1, z
)],
129 local_vert_map
[(x
+ 1, y
+ 1, z
+ 1)],
130 local_vert_map
[(x
, y
+ 1, z
+ 1)],
132 visibility
= copy
.copy(self
.__face
_visibility
[(x
, y
, z
)])
134 visibility
[0] = visibility
[0] and (face_vis
[0] or x
!= 0)
135 visibility
[1] = visibility
[1] and (face_vis
[1] or x
!= 2)
136 visibility
[2] = visibility
[2] and (face_vis
[2] or y
!= 0)
137 visibility
[3] = visibility
[3] and (face_vis
[3] or y
!= 2)
138 visibility
[4] = visibility
[4] and (face_vis
[4] or z
!= 0)
139 visibility
[5] = visibility
[5] and (face_vis
[5] or z
!= 2)
140 self
.__make
_sub
_sponge
(
146 class AddMengerSponge(bpy
.types
.Operator
, AddObjectHelper
):
147 bl_idname
= "mesh.menger_sponge_add"
148 bl_label
= "Menger Sponge"
149 bl_description
= "Construct a menger sponge mesh"
150 bl_options
= {'REGISTER', 'UNDO'}
154 description
="Sponge Level",
158 radius
: FloatProperty(
160 description
="Sponge Radius",
164 layers
: BoolVectorProperty(
168 options
={'HIDDEN', 'SKIP_SAVE'},
171 def execute(self
, context
):
172 sponger
= MengerSponge(self
.level
)
173 vertices
, faces
= sponger
.create(self
.radius
* 2, self
.radius
* 2)
176 mesh
= bpy
.data
.meshes
.new(name
='Sponge')
177 mesh
.from_pydata(vertices
, [], faces
)
178 uvs
= [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]
180 for i
, uvloop
in enumerate(mesh
.uv_layers
.active
.data
):
181 uvloop
.uv
= uvs
[i
% 4]
183 object_data_add(context
, mesh
, operator
=self
)