1 # SPDX-FileCopyrightText: 2015 Sugiany
3 # SPDX-License-Identifier: MIT
7 from bpy_extras
.object_utils
import (
12 from bpy
.props
import (
24 class MengerSponge(object):
34 def __init__(self
, level
):
36 self
.__max
_point
_number
= 3 ** level
37 self
.__vertices
_map
= {}
39 self
.__face
_visibility
= {}
45 self
.__face
_visibility
[(x
, y
, z
)] = [
46 x
== 0 or x
== 2 and (y
== 1 or z
== 1),
47 x
== 2 or x
== 0 and (y
== 1 or z
== 1),
48 y
== 0 or y
== 2 and (x
== 1 or z
== 1),
49 y
== 2 or y
== 0 and (x
== 1 or z
== 1),
50 z
== 0 or z
== 2 and (y
== 1 or x
== 1),
51 z
== 2 or z
== 0 and (y
== 1 or x
== 1),
54 def create(self
, width
, height
):
55 m
= self
.__max
_point
_number
66 self
.__make
_sub
_sponge
(points
, None, self
.__level
)
67 vertices
= self
.__make
_vertices
(width
, height
)
68 return vertices
, self
.__faces
70 def __get_vindex(self
, p
):
71 if p
in self
.__vertices
_map
:
72 return self
.__vertices
_map
[p
]
73 index
= len(self
.__vertices
_map
)
74 self
.__vertices
_map
[p
] = index
77 def __make_vertices(self
, width
, height
):
78 vertices
= [None] * len(self
.__vertices
_map
)
81 w_step
= width
/ self
.__max
_point
_number
82 h_step
= height
/ self
.__max
_point
_number
83 for p
, i
in sorted(self
.__vertices
_map
.items(), key
=lambda x
: x
[1]):
84 vertices
[i
] = mathutils
.Vector([
91 def __make_sub_sponge(self
, cur_points
, face_vis
, depth
):
95 cur_point_indices
= []
97 cur_point_indices
.append(self
.__get
_vindex
(p
))
98 for i
, vis
in enumerate(face_vis
):
101 for vi
in self
.FACE_INDICES
[i
]:
102 f
.append(cur_point_indices
[vi
])
103 self
.__faces
.append(f
)
107 width
= (cur_points
[1][0] - base
[0]) / 3
112 local_vert_map
[(x
, y
, z
)] = (
121 if [x
, y
, z
].count(1) > 1:
124 local_vert_map
[(x
, y
, z
)],
125 local_vert_map
[(x
+ 1, y
, z
)],
126 local_vert_map
[(x
+ 1, y
, z
+ 1)],
127 local_vert_map
[(x
, y
, z
+ 1)],
128 local_vert_map
[(x
, y
+ 1, z
)],
129 local_vert_map
[(x
+ 1, y
+ 1, z
)],
130 local_vert_map
[(x
+ 1, y
+ 1, z
+ 1)],
131 local_vert_map
[(x
, y
+ 1, z
+ 1)],
133 visibility
= copy
.copy(self
.__face
_visibility
[(x
, y
, z
)])
135 visibility
[0] = visibility
[0] and (face_vis
[0] or x
!= 0)
136 visibility
[1] = visibility
[1] and (face_vis
[1] or x
!= 2)
137 visibility
[2] = visibility
[2] and (face_vis
[2] or y
!= 0)
138 visibility
[3] = visibility
[3] and (face_vis
[3] or y
!= 2)
139 visibility
[4] = visibility
[4] and (face_vis
[4] or z
!= 0)
140 visibility
[5] = visibility
[5] and (face_vis
[5] or z
!= 2)
141 self
.__make
_sub
_sponge
(
147 class AddMengerSponge(bpy
.types
.Operator
, AddObjectHelper
):
148 bl_idname
= "mesh.menger_sponge_add"
149 bl_label
= "Menger Sponge"
150 bl_description
= "Construct a menger sponge mesh"
151 bl_options
= {'REGISTER', 'UNDO'}
155 description
="Sponge Level",
159 radius
: FloatProperty(
161 description
="Sponge Radius",
165 layers
: BoolVectorProperty(
169 options
={'HIDDEN', 'SKIP_SAVE'},
172 def execute(self
, context
):
173 sponger
= MengerSponge(self
.level
)
174 vertices
, faces
= sponger
.create(self
.radius
* 2, self
.radius
* 2)
177 mesh
= bpy
.data
.meshes
.new(name
='Sponge')
178 mesh
.from_pydata(vertices
, [], faces
)
179 uvs
= [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)]
181 for i
, uvloop
in enumerate(mesh
.uv_layers
.active
.data
):
182 uvloop
.uv
= uvs
[i
% 4]
184 object_data_add(context
, mesh
, operator
=self
)