ea7c0e8296e8b104d016e937ac554796d258fa9f
[blender-addons-contrib.git] / add_advanced_objects_menu / pixelate_3d.py
1 # gpl author: liero
2 # very simple 'pixelization' or 'voxelization' engine #
3
4 bl_info = {
5     "name": "3D Pixelate",
6     "author": "liero",
7     "version": (0, 5, 3),
8     "blender": (2, 74, 0),
9     "location": "View3D > Tool Shelf",
10     "description": "Creates a 3d pixelated version of the object",
11     "category": "Object"}
12
13 # Note: winmgr properties are moved to the operator
14
15
16 import bpy
17 from bpy.types import Operator
18 from bpy.props import (
19         FloatProperty,
20         IntProperty,
21         )
22
23
24 def pix(self, obj):
25     sce = bpy.context.scene
26     obj.hide = obj.hide_render = True
27     mes = obj.to_mesh(sce, True, 'RENDER')
28     mes.transform(obj.matrix_world)
29     dup = bpy.data.objects.new('dup', mes)
30     sce.objects.link(dup)
31     dup.instance_type = 'VERTS'
32     sce.objects.active = dup
33     bpy.ops.object.mode_set()
34     ver = mes.vertices
35
36     for i in range(250):
37         fin = True
38         for i in dup.data.edges:
39             d = ver[i.vertices[0]].co - ver[i.vertices[1]].co
40             if d.length > self.size:
41                 ver[i.vertices[0]].select = True
42                 ver[i.vertices[1]].select = True
43                 fin = False
44         bpy.ops.object.editmode_toggle()
45         bpy.ops.mesh.subdivide(number_cuts=1, smoothness=self.smooth)
46         bpy.ops.mesh.select_all(action='DESELECT')
47         bpy.ops.object.editmode_toggle()
48         if fin:
49             break
50
51     for i in ver:
52         for n in range(3):
53             i.co[n] -= (.001 + i.co[n]) % self.size
54
55     bpy.ops.object.mode_set(mode='EDIT', toggle=False)
56     bpy.ops.mesh.select_all(action='SELECT')
57     bpy.ops.mesh.remove_doubles(threshold=0.0001)
58     bpy.ops.mesh.delete(type='EDGE_FACE')
59     bpy.ops.object.mode_set()
60     sca = self.size * (100 - self.gap) * .005
61     bpy.ops.mesh.primitive_cube_add(layers=[True] + [False] * 19)
62     bpy.ops.transform.resize(value=[sca] * 3)
63     bpy.context.view_layer.objects.active = dup
64     bpy.ops.object.parent_set(type='OBJECT')
65
66
67 class Pixelate(Operator):
68     bl_idname = "object.pixelate"
69     bl_label = "Pixelate Object"
70     bl_description = ("Create a 3d pixelated version of the object\n"
71                       "using a Duplivert Box around each copied vertex\n"
72                       "With high poly objects, it can take some time\n"
73                       "Needs an existing Active Mesh Object")
74     bl_options = {'REGISTER', 'UNDO'}
75
76     size: FloatProperty(
77             name="Size",
78             min=.05, max=5,
79             default=.25,
80             description="Size of the cube / grid \n"
81                         "Small values (below 0.1) can create a high polygon count"
82             )
83     gap: IntProperty(
84             name="Gap",
85             min=0, max=90,
86             default=10,
87             subtype='PERCENTAGE',
88             description="Separation - percent of size"
89             )
90     smooth: FloatProperty(
91             name="Smooth",
92             min=0, max=1,
93             default=.0,
94             description="Smooth factor when subdividing mesh"
95             )
96
97     @classmethod
98     def poll(cls, context):
99         return (context.active_object and
100                 context.active_object.type == 'MESH' and
101                 context.mode == 'OBJECT')
102
103     def draw(self, context):
104         layout = self.layout
105
106         col = layout.column(align=True)
107         col.prop(self, "size")
108         col.prop(self, "gap")
109         layout.prop(self, "smooth")
110
111     def execute(self, context):
112         objeto = bpy.context.object
113         try:
114             pix(self, objeto)
115
116         except Exception as e:
117             self.report({'WARNING'},
118                         "Some operations could not be performed (See Console for more info)")
119
120             print("\n[Add Advanced  Objects]\nOperator: "
121                   "object.pixelate\nError: {}".format(e))
122
123             return {'CANCELLED'}
124
125         return {'FINISHED'}
126
127
128 def register():
129     bpy.utils.register_class(Pixelate)
130
131
132 def unregister():
133     bpy.utils.unregister_class(Pixelate)
134
135
136 if __name__ == '__main__':
137     register()