diff options
author | meta-androcto <meta.androcto1@gmail.com> | 2017-05-22 02:29:20 +0300 |
---|---|---|
committer | meta-androcto <meta.androcto1@gmail.com> | 2017-05-22 02:29:20 +0300 |
commit | 768bddf8dc839bd16d8533d8d2fbb86621ebb477 (patch) | |
tree | 8f24599d82890dced8b3092fe7aae50914678e32 /object_fracture_crack | |
parent | 48a69db5444591ba88ca9794dbdb2b8d3a2c9984 (diff) |
initial commit object_fracture_crack by Nobuyuki Hirakata
Diffstat (limited to 'object_fracture_crack')
-rw-r--r-- | object_fracture_crack/__init__.py | 158 | ||||
-rw-r--r-- | object_fracture_crack/crack_it.py | 183 | ||||
-rw-r--r-- | object_fracture_crack/materials/materials1.blend | bin | 0 -> 237466 bytes | |||
-rw-r--r-- | object_fracture_crack/operator.py | 111 |
4 files changed, 452 insertions, 0 deletions
diff --git a/object_fracture_crack/__init__.py b/object_fracture_crack/__init__.py new file mode 100644 index 00000000..38739dfc --- /dev/null +++ b/object_fracture_crack/__init__.py @@ -0,0 +1,158 @@ +#====================== BEGIN GPL LICENSE BLOCK ====================== +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +#======================= END GPL LICENSE BLOCK ======================== + +''' + The addon makes a cracked object based on selected object. Also you can use material preset for cracked objects. + + WARNING1: Please enable 'Object: Cell Fracture' addon before use the addon!! + WARNING2: Obejects which have many vertices or complex shape could take huge amount of time to make crack. + So I recommend using simple object, or simplifying object by applying decimate modifier in advance. + + Besic Usage: + 1. Select an object. + 2. Find the addon's location in create tab in the toolshelf left. It's usually the same tab of 'Add Primitive'. + 3. Click 'Crack It' button. It makes cracked object with some modifiers. + 4. Tweak modifier setting. Decimate modifeir to simplify shape, Smooth modifier to smooth shape. + 5. Select material preset and click 'Apply Material' button. + + Crack Option: + 'From Child Verts': Use child's vertices and position for origin of crack. + 'Scale X/Y/Z': Scale of crack. To make long crack like bark of tree, decrease scale of an axis. + 'Max Crack': Max number of crack. Notice that if you increase it too much, calculation will take long time. + 'Margin Size': Margin of crack. To make more gap of crack, increase it. + 'Extrude': Extrusion size along with object's normal. + 'Random': Randomness of crack' rotation and scale. + + Material Preset: + 'Excrement': Poop/shit material + 'Mud': Mud Material + 'Tree': Tree Material + 'Rock': Rock Material +''' + +if 'bpy' in locals(): + import imp + imp.reload(operator) + +else: + from . import operator + +import bpy +import os + +bl_info = { + "name": "Cell Fracture Crack It", + "author": "Nobuyuki Hirakata", + "version": (0, 1, 0), + "blender": (2, 77, 0), + "location": "View3D > Toolshelf > Creat Tab", + "description": "Displaced Cell Fracture Addon", + "warning": "Make sure to enable 'Object: Cell Fracture' Addon", + #"support": "TESTING", + "wiki_url": "http://gappyfacets.com/2016/08/11/blender-crack-addon-basic-tutorial/", + "tracker_url": "", + "category": "Object" +} + +def register(): + bpy.utils.register_module(__name__) + + # Input on toolshelf before execution -------------------------- + # In Panel subclass, In bpy.types.Operator subclass, reference them by context.scene.~. + + bpy.types.Scene.crackit_fracture_childverts = bpy.props.BoolProperty( + name = 'From Child Verts', + description = "Use child object's vertices and position for origin of crack.", + default = False + ) + bpy.types.Scene.crackit_fracture_scalex = bpy.props.FloatProperty( + name = 'Scale X', + description = "Scale X", + default = 1.00, + min = 0.00, + max = 1.00 + ) + bpy.types.Scene.crackit_fracture_scaley = bpy.props.FloatProperty( + name = 'Scale Y', + description = "Scale Y", + default = 1.00, + min = 0.00, + max = 1.00 + ) + bpy.types.Scene.crackit_fracture_scalez = bpy.props.FloatProperty( + name = 'Scale Z', + description = "Scale Z", + default = 1.00, + min = 0.00, + max = 1.00 + ) + bpy.types.Scene.crackit_fracture_div = bpy.props.IntProperty( + name = 'Max Crack', + description = "Max Crack", + default = 100, + min = 0, + max = 10000 + ) + bpy.types.Scene.crackit_fracture_margin = bpy.props.FloatProperty( + name = 'Margin Size', + description = "Margin Size", + default = 0.001, + min = 0.000, + max = 1.000 + ) + bpy.types.Scene.crackit_extrude_offset = bpy.props.FloatProperty( + name = 'Extrude', + description = "Extrude Offset", + default = 0.10, + min = 0.00, + max = 2.00 + ) + bpy.types.Scene.crackit_extrude_random = bpy.props.FloatProperty( + name = 'Random', + description = "Extrude Random", + default = 0.30, + min = -1.00, + max = 1.00 + ) + # Path of the addon. + bpy.types.Scene.crackit_material_addonpath = os.path.dirname(__file__) + # Selection of material preset. + bpy.types.Scene.crackit_material_preset = bpy.props.EnumProperty( + name = 'Preset', + description = "Material Preset", + items = [('crackit_organic_mud', 'Organic Mud', "Mud material"), + ('crackit_mud1', 'Mud', "Mud material"), + ('crackit_tree1_moss1', 'Tree1_moss', "Tree Material"), + ('crackit_tree2_dry1', 'Tree2_dry', "Tree Material"), + ('crackit_tree3_red1', 'Tree3_red', "Tree Material"), + ('crackit_rock1', 'Rock', "Rock Material")] + ) + +def unregister(): + # Delete bpy.types.Scene.~. + del bpy.types.Scene.crackit_fracture_scalex + del bpy.types.Scene.crackit_fracture_scaley + del bpy.types.Scene.crackit_fracture_scalez + del bpy.types.Scene.crackit_fracture_div + del bpy.types.Scene.crackit_fracture_margin + del bpy.types.Scene.crackit_extrude_offset + + bpy.utils.unregister_module(__name__) + +if __name__ == "__main__": + register() diff --git a/object_fracture_crack/crack_it.py b/object_fracture_crack/crack_it.py new file mode 100644 index 00000000..6d0cd571 --- /dev/null +++ b/object_fracture_crack/crack_it.py @@ -0,0 +1,183 @@ +import bpy + +import bmesh, mathutils, random +from random import gauss +from math import radians +from mathutils import Euler, Vector + +import addon_utils + +# ---------------------Crack------------------- +# Cell fracture and post-process: +def makeFracture(child_verts=False, division=100, noise=0.00, scaleX=1.00, scaleY=1.00, scaleZ=1.00, recursion=0, margin=0.001): + # Get active object name and active layer. + active_name = bpy.context.scene.objects.active.name + active_layer = bpy.context.scene.active_layer + + # source method of whether use child verts. + if child_verts == True: + crack_source = 'VERT_CHILD' + else: + crack_source = 'PARTICLE_OWN' + + bpy.ops.object.add_fracture_cell_objects(source={crack_source}, source_limit=division, source_noise=noise, + cell_scale=(scaleX, scaleY, scaleZ), recursion=recursion, recursion_source_limit=8, recursion_clamp=250, recursion_chance=0.25, recursion_chance_select='SIZE_MIN', + use_smooth_faces=False, use_sharp_edges=False, use_sharp_edges_apply=True, use_data_match=True, use_island_split=True, + margin=margin, material_index=0, use_interior_vgroup=False, mass_mode='VOLUME', mass=1, use_recenter=True, use_remove_original=True, use_layer_index=0, use_layer_next=False, + group_name="", use_debug_points=False, use_debug_redraw=True, use_debug_bool=False) + + _makeJoin(active_name, active_layer) + +# Join fractures into an object. +def _makeJoin(active_name, active_layer): + # Get object by name. + #bpy.context.scene.layers[active_layer+1] = True + bpy.ops.object.select_all(action='DESELECT') + bpy.ops.object.select_pattern(pattern=active_name + '_cell*') + fractures = bpy.context.selected_objects + + # Execute join. + bpy.context.scene.objects.active = fractures[0] + fractures[0].select = True + bpy.ops.object.join() + + # Change name. + bpy.context.scene.objects.active.name = active_name + '_crack' + + # Change origin. + bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN') + + # Turn off the layer where original object is. + #bpy.context.scene.layers[active_layer] = False + +# Add modifier and setting. +def addModifiers(): + bpy.ops.object.modifier_add(type='DECIMATE') + decimate = bpy.context.object.modifiers[-1] + decimate.name = 'DECIMATE_crackit' + decimate.ratio = 0.4 + + bpy.ops.object.modifier_add(type='SUBSURF') + subsurf = bpy.context.object.modifiers[-1] + subsurf.name = 'SUBSURF_crackit' + + bpy.ops.object.modifier_add(type='SMOOTH') + smooth = bpy.context.object.modifiers[-1] + smooth.name = 'SMOOTH_crackit' + + + +# --------------multi extrude-------------------- +# var1=random offset, var2=random rotation, var3=random scale. +def multiExtrude(off=0.1, rotx=0, roty=0, rotz=0, sca=1.0, var1=0.01, var2=0.3, var3=0.3, num=1, ran=0): + obj = bpy.context.object + data, om = obj.data, obj.mode + bpy.context.tool_settings.mesh_select_mode = [False, False, True] + + # bmesh operations + bpy.ops.object.mode_set() + bm = bmesh.new() + bm.from_mesh(obj.data) + sel = [f for f in bm.faces if f.select] + + # faces loop + for i, of in enumerate(sel): + rot = _vrot(r=i, ran=ran, rotx=rotx, var2=var2, roty=roty, rotz=rotz) + off = _vloc(r=i, ran=ran, off=off, var1=var1) + of.normal_update() + + # extrusion loop + for r in range(num): + nf = of.copy() + nf.normal_update() + no = nf.normal.copy() + ce = nf.calc_center_bounds() + s = _vsca(r=i+r, ran=ran, var3=var3, sca=sca) + + for v in nf.verts: + v.co -= ce + v.co.rotate(rot) + v.co += ce + no * off + v.co = v.co.lerp(ce, 1 - s) + + # extrude code from TrumanBlending + for a, b in zip(of.loops, nf.loops): + sf = bm.faces.new((a.vert, a.link_loop_next.vert, \ + b.link_loop_next.vert, b.vert)) + sf.normal_update() + + bm.faces.remove(of) + of = nf + + for v in bm.verts: v.select = False + for e in bm.edges: e.select = False + bm.to_mesh(obj.data) + obj.data.update() + + if not len(sel): + self.report({'INFO'}, "Select one or more faces...") + return{'FINISHED'} + +def _vloc(r, ran, off, var1): + random.seed(ran + r) + return off * (1 + random.gauss(0, var1 / 3)) + +def _vrot(r, ran, rotx, var2, roty, rotz): + random.seed(ran + r) + return Euler((radians(rotx) + random.gauss(0, var2 / 3), \ + radians(roty) + random.gauss(0, var2 / 3), \ + radians(rotz) + random.gauss(0, var2 / 3)), 'XYZ') + +def _vsca(r, ran, sca, var3): + random.seed(ran + r) + return sca * (1 + random.gauss(0, var3 / 3)) + +# centroide de una seleccion de vertices +def _centro(ver): + vvv = [v for v in ver if v.select] + if not vvv or len(vvv) == len(ver): return ('error') + x = sum([round(v.co[0],4) for v in vvv]) / len(vvv) + y = sum([round(v.co[1],4) for v in vvv]) / len(vvv) + z = sum([round(v.co[2],4) for v in vvv]) / len(vvv) + return (x,y,z) + +# recuperar el estado original del objeto +def _volver(obj, copia, om, msm, msv): + for i in copia: obj.data.vertices[i].select = True + bpy.context.tool_settings.mesh_select_mode = msm + for i in range(len(msv)): + obj.modifiers[i].show_viewport = msv[i] + + + +# --------------Material preset-------------------------- +def appendMaterial(addon_path, material_name): + # Load material from the addon directory. + file_path = _makeFilePath(addon_path=addon_path) + bpy.ops.wm.append(filename=material_name, directory=file_path) + + # If material is loaded some times, select the last-loaded material. + last_material = _getAppendedMaterial(material_name) + mat = bpy.data.materials[last_material] + + # Apply Only one material in the material slot. + for m in bpy.context.object.data.materials: + bpy.ops.object.material_slot_remove() + bpy.context.object.data.materials.append(mat) + +# Make file path of addon. +def _makeFilePath(addon_path): + material_folder = "/materials" + blend_file = "/materials1.blend" + category = "\\Material\\" + + file_path = addon_path + material_folder + blend_file + category + return file_path + +# Get last-loaded material, such as ~.002. +def _getAppendedMaterial(material_name): + # Get material name list. + material_names = [m.name for m in bpy.data.materials if material_name in m.name] + # Return last material in the sorted order. + material_names.sort() + return material_names[-1] diff --git a/object_fracture_crack/materials/materials1.blend b/object_fracture_crack/materials/materials1.blend Binary files differnew file mode 100644 index 00000000..969f2068 --- /dev/null +++ b/object_fracture_crack/materials/materials1.blend diff --git a/object_fracture_crack/operator.py b/object_fracture_crack/operator.py new file mode 100644 index 00000000..5f1b51e7 --- /dev/null +++ b/object_fracture_crack/operator.py @@ -0,0 +1,111 @@ +import bpy +from . import crack_it + +# Class for input and execution settings. +class FractureOperation(bpy.types.Operator): + + bl_idname = 'mesh.crackit_fracture' # Access by bpy.ops.mesh.crackit_fracture. + bl_label = "Crack It!" # Label of button on menu. + bl_description = "Make crack by cell fracture addon." + bl_options = {'REGISTER', 'UNDO'} + + # Input after execution------------------------ + # Reference by self.~ in execute(). + + # ----------------------------------------- + + ''' + @classmethod + def poll(cls, context): + return (context.object is not None) + + ''' + + def execute(self, context): + sce = context.scene + + crack_it.makeFracture(child_verts=sce.crackit_fracture_childverts, division=sce.crackit_fracture_div, + scaleX=sce.crackit_fracture_scalex, scaleY=sce.crackit_fracture_scaley, scaleZ=sce.crackit_fracture_scalez, + margin=sce.crackit_fracture_margin) + crack_it.addModifiers() + crack_it.multiExtrude(off=sce.crackit_extrude_offset, + var2=sce.crackit_extrude_random, var3=sce.crackit_extrude_random) + bpy.ops.object.shade_smooth() + return {'FINISHED'} + +# Apply material preset. +class MaterialOperation(bpy.types.Operator): + + bl_idname = 'mesh.crackit_material' # Access by bpy.ops.mesh.crackit_material. + bl_label = "Apply Material" # Label of button on menu. + bl_description = "Apply a preset material" + bl_options = {'REGISTER', 'UNDO'} + + # Input after execution------------------------ + # Reference by self.~ in execute(). + + # ----------------------------------------- + + ''' + @classmethod + def poll(cls, context): + return (context.object is not None) + + ''' + + def execute(self, context): + sce = context.scene + + crack_it.appendMaterial(addon_path=sce.crackit_material_addonpath, material_name=sce.crackit_material_preset) + return {'FINISHED'} + +# Menu settings. +class crackitPanel(bpy.types.Panel): + bl_label = "Crack it!" # title. + bl_idname = 'crack_it' # id to reference. + bl_space_type = 'VIEW_3D' # 3Dview. + bl_region_type = 'TOOLS' # make menu on tool shelf. + bl_category = 'Create' # Tab name on tool shelf. + bl_context = (('objectmode')) # Mode to show the menu. + + # Menu. + def draw(self, context): + obj = context.object + sce = context.scene + layout = self.layout + + # Crack input + box = layout.box() + row = box.row() + row.label("Crack") + # Warning if fracture cell addon is not enabled. + if 'object_fracture_cell' not in bpy.context.user_preferences.addons.keys(): + row = box.row() + row.label("Note: Please enable 'Object: Cell Fracture' addon!") + row = box.row() + row.prop(sce, 'crackit_fracture_childverts') + row = box.row() + row.prop(sce, 'crackit_fracture_scalex') # bpy.types.Scene.crackit_fracture_scalex. + row = box.row() + row.prop(sce, 'crackit_fracture_scaley') + row = box.row() + row.prop(sce, 'crackit_fracture_scalez') + row = box.row() + row.prop(sce, 'crackit_fracture_div') + row = box.row() + row.prop(sce, 'crackit_fracture_margin') + row = box.row() + row.prop(sce, 'crackit_extrude_offset') + row = box.row() + row.prop(sce, 'crackit_extrude_random') + row = box.row() + row.operator(FractureOperation.bl_idname) # Execute button. + + # material Preset: + box = layout.box() + row = box.row() + row.label("Material Preset") + row = box.row() + row.prop(sce, 'crackit_material_preset') + row = box.row() + row.operator(MaterialOperation.bl_idname) # Execute button.
\ No newline at end of file |