mesh_tissue: initial update 2.80
This commit is contained in:
parent
fffaf5d275
commit
498d912a9d
Notes:
blender-bot
2023-02-14 19:17:41 +01:00
Referenced by commit d142dc2d: mesh_tissue: add comment to object.tessellate.working_on Referenced by commit 582119a5: mesh_tissue: revert version bump rBA498d912a9d58 Referenced by commitd142dc2d
, mesh_tissue: add comment to object.tessellate.working_on Referenced by commit582119a5
, mesh_tissue: revert version bump rBA498d912a9d58 Referenced by issue #63477, Update Tissue addon 2.8
|
@ -1,14 +1,38 @@
|
|||
# Tissue
|
||||
![cover](http://www.co-de-it.com/wordpress/wp-content/uploads/2015/07/tissue_graphics.jpg)
|
||||
Tissue - Blender's add-on for computational design by Co-de-iT
|
||||
http://www.co-de-it.com/wordpress/code/blender-tissue
|
||||
|
||||
Latest version (master): https://github.com/alessandro-zomparelli/tissue/archive/master.zip
|
||||
### Blender 2.79
|
||||
|
||||
Releases: https://github.com/alessandro-zomparelli/tissue/releases
|
||||
Official version (master): https://github.com/alessandro-zomparelli/tissue/archive/master.zip
|
||||
|
||||
Installation:
|
||||
Latest development version (dev1): https://github.com/alessandro-zomparelli/tissue/tree/dev1
|
||||
(Includes animatable Tessellation)
|
||||
|
||||
### Blender 2.80
|
||||
|
||||
Latest development version (b280-dev): https://github.com/alessandro-zomparelli/tissue/tree/b280-dev
|
||||
(Includes animatable Tessellation and Patch method)
|
||||
|
||||
|
||||
|
||||
### Installation:
|
||||
|
||||
1. Start Blender. Open User Preferences, the addons tab
|
||||
2. Click "install from file" and point Blender at the downloaded zip
|
||||
3. Activate Tissue add-on from user preferences
|
||||
3. Save user preferences if you want to have it on at startup.
|
||||
|
||||
|
||||
### Contribute
|
||||
Please help me keeping Tissue stable and updated, report any issue here: https://github.com/alessandro-zomparelli/tissue/issues
|
||||
|
||||
Tissue is free and open-source. I really think that this is the power of Blender and I wanted to give my small contribution to it.
|
||||
If you like my work and you want to help to continue the development of Tissue, please consider to make a small donation. Any small contribution is really appreciated, thanks! :-D
|
||||
|
||||
Alessandro
|
||||
|
||||
|
||||
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ARSDJWXVFZ346)
|
||||
|
||||
|
|
|
@ -33,14 +33,13 @@
|
|||
bl_info = {
|
||||
"name": "Tissue",
|
||||
"author": "Alessandro Zomparelli (Co-de-iT)",
|
||||
"version": (0, 3, 4),
|
||||
"blender": (2, 79, 0),
|
||||
"version": (0, 3, 25),
|
||||
"blender": (2, 80, 0),
|
||||
"location": "",
|
||||
"description": "Tools for Computational Design",
|
||||
"warning": "",
|
||||
"wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
|
||||
"Py/Scripts/Mesh/Tissue",
|
||||
"tracker_url": "https://plus.google.com/u/0/+AlessandroZomparelli/",
|
||||
"wiki_url": "https://github.com/alessandro-zomparelli/tissue/wiki",
|
||||
"tracker_url": "https://github.com/alessandro-zomparelli/tissue/issues",
|
||||
"category": "Mesh"}
|
||||
|
||||
|
||||
|
@ -51,6 +50,7 @@ if "bpy" in locals():
|
|||
importlib.reload(dual_mesh)
|
||||
importlib.reload(lattice)
|
||||
importlib.reload(uv_to_mesh)
|
||||
importlib.reload(utils)
|
||||
|
||||
else:
|
||||
from . import tessellate_numpy
|
||||
|
@ -58,24 +58,76 @@ else:
|
|||
from . import dual_mesh
|
||||
from . import lattice
|
||||
from . import uv_to_mesh
|
||||
from . import utils
|
||||
|
||||
import bpy
|
||||
from bpy.props import PointerProperty
|
||||
from bpy.props import PointerProperty, CollectionProperty, BoolProperty
|
||||
|
||||
classes = (
|
||||
tessellate_numpy.tissue_tessellate_prop,
|
||||
tessellate_numpy.tessellate,
|
||||
tessellate_numpy.update_tessellate,
|
||||
tessellate_numpy.TISSUE_PT_tessellate,
|
||||
tessellate_numpy.rotate_face,
|
||||
tessellate_numpy.TISSUE_PT_tessellate_object,
|
||||
|
||||
colors_groups_exchanger.face_area_to_vertex_groups,
|
||||
colors_groups_exchanger.vertex_colors_to_vertex_groups,
|
||||
colors_groups_exchanger.vertex_group_to_vertex_colors,
|
||||
colors_groups_exchanger.TISSUE_PT_weight,
|
||||
colors_groups_exchanger.TISSUE_PT_color,
|
||||
colors_groups_exchanger.weight_contour_curves,
|
||||
colors_groups_exchanger.weight_contour_mask,
|
||||
colors_groups_exchanger.weight_contour_displace,
|
||||
colors_groups_exchanger.harmonic_weight,
|
||||
colors_groups_exchanger.edges_deformation,
|
||||
colors_groups_exchanger.edges_bending,
|
||||
colors_groups_exchanger.weight_laplacian,
|
||||
colors_groups_exchanger.reaction_diffusion,
|
||||
colors_groups_exchanger.start_reaction_diffusion,
|
||||
colors_groups_exchanger.TISSUE_PT_reaction_diffusion,
|
||||
colors_groups_exchanger.reset_reaction_diffusion_weight,
|
||||
colors_groups_exchanger.formula_prop,
|
||||
colors_groups_exchanger.reaction_diffusion_prop,
|
||||
colors_groups_exchanger.weight_formula,
|
||||
colors_groups_exchanger.curvature_to_vertex_groups,
|
||||
colors_groups_exchanger.weight_formula_wiki,
|
||||
|
||||
dual_mesh.dual_mesh,
|
||||
dual_mesh.dual_mesh_tessellated,
|
||||
|
||||
lattice.lattice_along_surface,
|
||||
|
||||
uv_to_mesh.uv_to_mesh
|
||||
)
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
from bpy.utils import register_class
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
#bpy.utils.register_module(__name__)
|
||||
bpy.types.Object.tissue_tessellate = PointerProperty(
|
||||
type=tessellate_numpy.tissue_tessellate_prop
|
||||
)
|
||||
|
||||
bpy.types.Object.formula_settings = CollectionProperty(
|
||||
type=colors_groups_exchanger.formula_prop
|
||||
)
|
||||
bpy.types.Object.reaction_diffusion_settings = PointerProperty(
|
||||
type=colors_groups_exchanger.reaction_diffusion_prop
|
||||
)
|
||||
# colors_groups_exchanger
|
||||
bpy.app.handlers.frame_change_post.append(colors_groups_exchanger.reaction_diffusion_def)
|
||||
#bpy.app.handlers.frame_change_post.append(tessellate_numpy.anim_tessellate)
|
||||
|
||||
def unregister():
|
||||
tessellate_numpy.unregister()
|
||||
colors_groups_exchanger.unregister()
|
||||
dual_mesh.unregister()
|
||||
lattice.unregister()
|
||||
uv_to_mesh.unregister()
|
||||
from bpy.utils import unregister_class
|
||||
for cls in classes:
|
||||
bpy.utils.unregister_class(cls)
|
||||
#tessellate_numpy.unregister()
|
||||
#colors_groups_exchanger.unregister()
|
||||
#dual_mesh.unregister()
|
||||
#lattice.unregister()
|
||||
#uv_to_mesh.unregister()
|
||||
|
||||
del bpy.types.Object.tissue_tessellate
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,8 +32,8 @@
|
|||
bl_info = {
|
||||
"name": "Dual Mesh",
|
||||
"author": "Alessandro Zomparelli (Co-de-iT)",
|
||||
"version": (0, 3),
|
||||
"blender": (2, 78, 0),
|
||||
"version": (0, 4),
|
||||
"blender": (2, 8, 0),
|
||||
"location": "",
|
||||
"description": "Convert a generic mesh to its dual",
|
||||
"warning": "",
|
||||
|
@ -47,15 +47,105 @@ from bpy.props import (
|
|||
EnumProperty,
|
||||
)
|
||||
import bmesh
|
||||
from .utils import *
|
||||
|
||||
|
||||
class dual_mesh_tessellated(Operator):
|
||||
bl_idname = "object.dual_mesh_tessellated"
|
||||
bl_label = "Dual Mesh"
|
||||
bl_description = ("Generate a polygonal mesh using Tessellate. (Non-destructive)")
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
apply_modifiers : BoolProperty(
|
||||
name="Apply Modifiers",
|
||||
default=True,
|
||||
description="Apply object's modifiers"
|
||||
)
|
||||
|
||||
source_faces : EnumProperty(
|
||||
items=[
|
||||
('QUAD', 'Quad Faces', ''),
|
||||
('TRI', 'Triangles', '')],
|
||||
name="Source Faces",
|
||||
description="Source polygons",
|
||||
default="QUAD",
|
||||
options={'LIBRARY_EDITABLE'}
|
||||
)
|
||||
|
||||
def execute(self, context):
|
||||
auto_layer_collection()
|
||||
ob0 = context.object
|
||||
name1 = "DualMesh_{}_Component".format(self.source_faces)
|
||||
# Generate component
|
||||
if self.source_faces == 'QUAD':
|
||||
verts = [(0.0, 0.0, 0.0), (0.0, 0.5, 0.0),
|
||||
(0.0, 1.0, 0.0), (0.5, 1.0, 0.0),
|
||||
(1.0, 1.0, 0.0), (1.0, 0.5, 0.0),
|
||||
(1.0, 0.0, 0.0), (0.5, 0.0, 0.0),
|
||||
(1/3, 1/3, 0.0), (2/3, 2/3, 0.0)]
|
||||
edges = [(0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7),
|
||||
(7,0), (1,8), (8,7), (3,9), (9,5), (8,9)]
|
||||
faces = [(7,8,1,0), (8,9,3,2,1), (9,5,4,3), (9,8,7,6,5)]
|
||||
else:
|
||||
verts = [(0.0,0.0,0.0), (0.5,0.0,0.0), (1.0,0.0,0.0), (0.0,1.0,0.0), (0.5,1.0,0.0), (1.0,1.0,0.0)]
|
||||
edges = [(0,1), (1,2), (2,5), (5,4), (4,3), (3,0), (1,4)]
|
||||
faces = [(0,1,4,3), (1,2,5,4)]
|
||||
|
||||
# check pre-existing component
|
||||
try:
|
||||
_verts = [0]*len(verts)*3
|
||||
__verts = [c for co in verts for c in co]
|
||||
ob1 = bpy.data.objects[name1]
|
||||
ob1.data.vertices.foreach_get("co",_verts)
|
||||
for a, b in zip(_verts, __verts):
|
||||
if abs(a-b) > 0.0001:
|
||||
raise ValueError
|
||||
except:
|
||||
me = bpy.data.meshes.new("Dual-Mesh") # add a new mesh
|
||||
me.from_pydata(verts, edges, faces)
|
||||
me.update(calc_edges=True, calc_edges_loose=True, calc_loop_triangles=True)
|
||||
if self.source_faces == 'QUAD': n_seams = 8
|
||||
else: n_seams = 6
|
||||
for i in range(n_seams): me.edges[i].use_seam = True
|
||||
ob1 = bpy.data.objects.new(name1, me)
|
||||
bpy.context.collection.objects.link(ob1)
|
||||
# fix visualization issue
|
||||
bpy.context.view_layer.objects.active = ob1
|
||||
ob1.select_set(True)
|
||||
bpy.ops.object.editmode_toggle()
|
||||
bpy.ops.object.editmode_toggle()
|
||||
ob1.select_set(False)
|
||||
# hide component
|
||||
ob1.hide_select = True
|
||||
ob1.hide_render = True
|
||||
ob1.hide_viewport = True
|
||||
ob = convert_object_to_mesh(ob0,False,False)
|
||||
ob.name = 'DualMesh'
|
||||
#ob = bpy.data.objects.new("DualMesh", convert_object_to_mesh(ob0,False,False))
|
||||
#bpy.context.collection.objects.link(ob)
|
||||
#bpy.context.view_layer.objects.active = ob
|
||||
#ob.select_set(True)
|
||||
ob.tissue_tessellate.component = ob1
|
||||
ob.tissue_tessellate.generator = ob0
|
||||
ob.tissue_tessellate.gen_modifiers = self.apply_modifiers
|
||||
ob.tissue_tessellate.merge = True
|
||||
ob.tissue_tessellate.bool_dissolve_seams = True
|
||||
if self.source_faces == 'TRI': ob.tissue_tessellate.fill_mode = 'FAN'
|
||||
print(ob1)
|
||||
print(ob0)
|
||||
print(bpy.context.object)
|
||||
bpy.ops.object.update_tessellate()
|
||||
ob.location = ob0.location
|
||||
ob.matrix_world = ob0.matrix_world
|
||||
return {'FINISHED'}
|
||||
|
||||
class dual_mesh(Operator):
|
||||
bl_idname = "object.dual_mesh"
|
||||
bl_label = "Dual Mesh"
|
||||
bl_description = ("Convert a generic mesh into a polygonal mesh")
|
||||
bl_label = "Convert to Dual Mesh"
|
||||
bl_description = ("Convert a generic mesh into a polygonal mesh. (Destructive)")
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
quad_method: EnumProperty(
|
||||
quad_method : EnumProperty(
|
||||
items=[('BEAUTY', 'Beauty',
|
||||
'Split the quads in nice triangles, slower method'),
|
||||
('FIXED', 'Fixed',
|
||||
|
@ -70,7 +160,7 @@ class dual_mesh(Operator):
|
|||
default="FIXED",
|
||||
options={'LIBRARY_EDITABLE'}
|
||||
)
|
||||
polygon_method: EnumProperty(
|
||||
polygon_method : EnumProperty(
|
||||
items=[
|
||||
('BEAUTY', 'Beauty', 'Arrange the new triangles evenly'),
|
||||
('CLIP', 'Clip',
|
||||
|
@ -80,12 +170,12 @@ class dual_mesh(Operator):
|
|||
default="BEAUTY",
|
||||
options={'LIBRARY_EDITABLE'}
|
||||
)
|
||||
preserve_borders: BoolProperty(
|
||||
preserve_borders : BoolProperty(
|
||||
name="Preserve Borders",
|
||||
default=True,
|
||||
description="Preserve original borders"
|
||||
)
|
||||
apply_modifiers: BoolProperty(
|
||||
apply_modifiers : BoolProperty(
|
||||
name="Apply Modifiers",
|
||||
default=True,
|
||||
description="Apply object's modifiers"
|
||||
|
@ -103,16 +193,6 @@ class dual_mesh(Operator):
|
|||
sel = bpy.context.selected_objects
|
||||
doneMeshes = []
|
||||
|
||||
'''
|
||||
if self.new_object:
|
||||
bpy.ops.object.duplicate_move()
|
||||
for i in range(len(sel)):
|
||||
bpy.context.selected_objects[i].name = sel[i].name + "_dual"
|
||||
if sel[i] == act:
|
||||
bpy.context.scene.objects.active = bpy.context.selected_objects[i]
|
||||
sel = bpy.context.selected_objects
|
||||
'''
|
||||
|
||||
for ob0 in sel:
|
||||
if ob0.type != 'MESH':
|
||||
continue
|
||||
|
@ -153,16 +233,7 @@ class dual_mesh(Operator):
|
|||
)
|
||||
bpy.ops.mesh.extrude_region_move(
|
||||
MESH_OT_extrude_region={"mirror": False},
|
||||
TRANSFORM_OT_translate={"value": (0, 0, 0),
|
||||
"constraint_axis": (False, False, False),
|
||||
"orient_type": 'GLOBAL', "mirror": False,
|
||||
"proportional": 'DISABLED',
|
||||
"proportional_edit_falloff": 'SMOOTH', "proportional_size": 1,
|
||||
"snap": False, "snap_target": 'CLOSEST',
|
||||
"snap_point": (0, 0, 0), "snap_align": False,
|
||||
"snap_normal": (0, 0, 0), "gpencil_strokes": False,
|
||||
"texture_space": False, "remove_on_cancel": False,
|
||||
"release_confirm": False}
|
||||
TRANSFORM_OT_translate={"value": (0, 0, 0)}
|
||||
)
|
||||
|
||||
bpy.ops.mesh.select_mode(
|
||||
|
@ -185,19 +256,21 @@ class dual_mesh(Operator):
|
|||
bpy.ops.object.modifier_apply(
|
||||
apply_as='DATA', modifier='dual_mesh_subsurf'
|
||||
)
|
||||
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
|
||||
verts = ob.data.vertices
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
verts[0].select = True
|
||||
verts[-1].select = True
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
||||
bpy.ops.mesh.select_more(use_face_step=False)
|
||||
|
||||
bpy.ops.mesh.select_similar(
|
||||
type='EDGE', compare='EQUAL', threshold=0.01)
|
||||
bpy.ops.mesh.select_all(action='INVERT')
|
||||
|
||||
bpy.ops.mesh.dissolve_verts()
|
||||
bpy.ops.mesh.select_all(action='DESELECT')
|
||||
|
||||
|
@ -244,7 +317,7 @@ class dual_mesh(Operator):
|
|||
bm = bmesh.from_edit_mesh(ob.data)
|
||||
for v in bm.verts:
|
||||
if len(v.link_edges) == 2 and len(v.link_faces) < 3:
|
||||
v.select_set(True)
|
||||
v.select = True
|
||||
|
||||
# dissolve
|
||||
bpy.ops.mesh.dissolve_verts()
|
||||
|
@ -280,36 +353,3 @@ class dual_mesh(Operator):
|
|||
bpy.ops.object.mode_set(mode=mode)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
"""
|
||||
class dual_mesh_panel(bpy.types.Panel):
|
||||
bl_label = "Dual Mesh"
|
||||
bl_category = "Tools"
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_region_type = "TOOLS"
|
||||
bl_context = "objectmode"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
col = layout.column(align=True)
|
||||
try:
|
||||
if bpy.context.active_object.type == 'MESH':
|
||||
col.operator("object.dual_mesh")
|
||||
except:
|
||||
pass
|
||||
"""
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(dual_mesh)
|
||||
# bpy.utils.register_class(dual_mesh_panel)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(dual_mesh)
|
||||
# bpy.utils.unregister_class(dual_mesh_panel)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
|
@ -31,7 +31,7 @@ bl_info = {
|
|||
"name": "Lattice",
|
||||
"author": "Alessandro Zomparelli (Co-de-iT)",
|
||||
"version": (0, 3),
|
||||
"blender": (2, 78, 0),
|
||||
"blender": (2, 7, 8),
|
||||
"location": "",
|
||||
"description": "Generate a Lattice based on a grid mesh",
|
||||
"warning": "",
|
||||
|
@ -42,12 +42,11 @@ bl_info = {
|
|||
import bpy
|
||||
import bmesh
|
||||
from bpy.types import Operator
|
||||
from bpy.props import (
|
||||
BoolProperty,
|
||||
FloatProperty,
|
||||
)
|
||||
from bpy.props import (BoolProperty, StringProperty, FloatProperty)
|
||||
from mathutils import Vector
|
||||
|
||||
from .utils import *
|
||||
|
||||
|
||||
def not_in(element, grid):
|
||||
output = True
|
||||
|
@ -173,86 +172,93 @@ class lattice_along_surface(Operator):
|
|||
"Lattice's topology")
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
set_parent: BoolProperty(
|
||||
set_parent : BoolProperty(
|
||||
name="Set Parent",
|
||||
default=True,
|
||||
description="Automatically set the Lattice as parent"
|
||||
)
|
||||
flipNormals: BoolProperty(
|
||||
flipNormals : BoolProperty(
|
||||
name="Flip Normals",
|
||||
default=False,
|
||||
description="Flip normals direction"
|
||||
)
|
||||
swapUV: BoolProperty(
|
||||
swapUV : BoolProperty(
|
||||
name="Swap UV",
|
||||
default=False,
|
||||
description="Flip grid's U and V"
|
||||
)
|
||||
flipU: BoolProperty(
|
||||
flipU : BoolProperty(
|
||||
name="Flip U",
|
||||
default=False,
|
||||
description="Flip grid's U")
|
||||
|
||||
flipV: BoolProperty(
|
||||
flipV : BoolProperty(
|
||||
name="Flip V",
|
||||
default=False,
|
||||
description="Flip grid's V"
|
||||
)
|
||||
flipW: BoolProperty(
|
||||
flipW : BoolProperty(
|
||||
name="Flip W",
|
||||
default=False,
|
||||
description="Flip grid's W"
|
||||
)
|
||||
use_groups: BoolProperty(
|
||||
use_groups : BoolProperty(
|
||||
name="Vertex Group",
|
||||
default=False,
|
||||
description="Use active Vertex Group for lattice's thickness"
|
||||
)
|
||||
high_quality_lattice: BoolProperty(
|
||||
high_quality_lattice : BoolProperty(
|
||||
name="High quality",
|
||||
default=True,
|
||||
description="Increase the the subdivisions in normal direction for a "
|
||||
"more correct result"
|
||||
)
|
||||
hide_lattice: BoolProperty(
|
||||
hide_lattice : BoolProperty(
|
||||
name="Hide Lattice",
|
||||
default=True,
|
||||
description="Automatically hide the Lattice object"
|
||||
)
|
||||
scale_x: FloatProperty(
|
||||
scale_x : FloatProperty(
|
||||
name="Scale X",
|
||||
default=1,
|
||||
min=0.001,
|
||||
max=1,
|
||||
description="Object scale"
|
||||
)
|
||||
scale_y: FloatProperty(
|
||||
scale_y : FloatProperty(
|
||||
name="Scale Y", default=1,
|
||||
min=0.001,
|
||||
max=1,
|
||||
description="Object scale"
|
||||
)
|
||||
scale_z: FloatProperty(
|
||||
scale_z : FloatProperty(
|
||||
name="Scale Z",
|
||||
default=1,
|
||||
min=0.001,
|
||||
max=1,
|
||||
description="Object scale"
|
||||
)
|
||||
thickness: FloatProperty(
|
||||
thickness : FloatProperty(
|
||||
name="Thickness",
|
||||
default=1,
|
||||
soft_min=0,
|
||||
soft_max=5,
|
||||
description="Lattice thickness"
|
||||
)
|
||||
displace: FloatProperty(
|
||||
displace : FloatProperty(
|
||||
name="Displace",
|
||||
default=0,
|
||||
soft_min=-1,
|
||||
soft_max=1,
|
||||
description="Lattice displace"
|
||||
)
|
||||
grid_object = ""
|
||||
source_object = ""
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
try: return bpy.context.object.mode == 'OBJECT'
|
||||
except: return False
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -282,12 +288,6 @@ class lattice_along_surface(Operator):
|
|||
slider=True, toggle=False, icon_only=False, event=False,
|
||||
full_event=False, emboss=True, index=-1
|
||||
)
|
||||
"""
|
||||
col.prop(
|
||||
self, "scale_z", text="W", icon='NONE', expand=False,
|
||||
slider=True, toggle=False, icon_only=False, event=False,
|
||||
full_event=False, emboss=True, index=-1)
|
||||
"""
|
||||
col.separator()
|
||||
col.label(text="Flip:")
|
||||
row = col.row()
|
||||
|
@ -303,39 +303,48 @@ class lattice_along_surface(Operator):
|
|||
col.prop(self, "set_parent")
|
||||
|
||||
def execute(self, context):
|
||||
if len(bpy.context.selected_objects) != 2:
|
||||
self.report({'ERROR'}, "Please, select two objects")
|
||||
return {'CANCELLED'}
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
grid_obj = bpy.context.active_object
|
||||
if grid_obj.type not in ('MESH', 'CURVE', 'SURFACE'):
|
||||
self.report({'ERROR'}, "The surface object is not valid. Only Mesh,"
|
||||
"Curve and Surface objects are allowed.")
|
||||
return {'CANCELLED'}
|
||||
obj = None
|
||||
for o in bpy.context.selected_objects:
|
||||
if o.name != grid_obj.name and o.type in \
|
||||
('MESH', 'CURVE', 'SURFACE', 'FONT'):
|
||||
obj = o
|
||||
o.select_set(False)
|
||||
break
|
||||
obj_eval = obj.evaluated_get(depsgraph)
|
||||
try:
|
||||
obj_dim = obj.dimensions
|
||||
obj_me = obj_eval.to_mesh()
|
||||
except:
|
||||
self.report({'ERROR'}, "The object to deform is not valid. Only "
|
||||
"Mesh, Curve, Surface and Font objects are allowed.")
|
||||
return {'CANCELLED'}
|
||||
if self.source_object == self.grid_object == "" or True:
|
||||
if len(bpy.context.selected_objects) != 2:
|
||||
self.report({'ERROR'}, "Please, select two objects")
|
||||
return {'CANCELLED'}
|
||||
grid_obj = bpy.context.object
|
||||
if grid_obj.type not in ('MESH', 'CURVE', 'SURFACE'):
|
||||
self.report({'ERROR'}, "The surface object is not valid. Only Mesh,"
|
||||
"Curve and Surface objects are allowed.")
|
||||
return {'CANCELLED'}
|
||||
obj = None
|
||||
for o in bpy.context.selected_objects:
|
||||
if o.name != grid_obj.name and o.type in \
|
||||
('MESH', 'CURVE', 'SURFACE', 'FONT'):
|
||||
obj = o
|
||||
o.select_set(False)
|
||||
break
|
||||
try:
|
||||
obj_dim = obj.dimensions
|
||||
obj_me = simple_to_mesh(obj)#obj.to_mesh(bpy.context.depsgraph, apply_modifiers=True)
|
||||
except:
|
||||
self.report({'ERROR'}, "The object to deform is not valid. Only "
|
||||
"Mesh, Curve, Surface and Font objects are allowed.")
|
||||
return {'CANCELLED'}
|
||||
self.grid_object = grid_obj.name
|
||||
self.source_object = obj.name
|
||||
else:
|
||||
grid_obj = bpy.data.objects[self.grid_object]
|
||||
obj = bpy.data.objects[self.source_object]
|
||||
obj_me = simple_to_mesh(obj)# obj.to_mesh(bpy.context.depsgraph, apply_modifiers=True)
|
||||
for o in bpy.context.selected_objects: o.select_set(False)
|
||||
grid_obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = grid_obj
|
||||
|
||||
bpy.ops.object.duplicate_move()
|
||||
grid_obj = bpy.context.active_object
|
||||
bpy.ops.object.convert(target='MESH')
|
||||
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
|
||||
grid_mesh = grid_obj.evaluated_get(depsgraph).to_mesh()
|
||||
temp_grid_obj = grid_obj.copy()
|
||||
temp_grid_obj.data = simple_to_mesh(grid_obj)
|
||||
grid_mesh = temp_grid_obj.data
|
||||
for v in grid_mesh.vertices:
|
||||
v.co = grid_obj.matrix_world @ v.co
|
||||
grid_mesh.calc_normals()
|
||||
|
||||
if len(grid_mesh.polygons) > 64 * 64:
|
||||
bpy.ops.object.delete(use_global=False)
|
||||
bpy.data.objects.remove(temp_grid_obj)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
self.report({'ERROR'}, "Maximum resolution allowed for Lattice is 64")
|
||||
|
@ -346,7 +355,8 @@ class lattice_along_surface(Operator):
|
|||
max = Vector((0, 0, 0))
|
||||
first = True
|
||||
for v in obj_me.vertices:
|
||||
vert = obj.matrix_world * v.co
|
||||
v0 = v.co.copy()
|
||||
vert = obj.matrix_world @ v0
|
||||
if vert[0] < min[0] or first:
|
||||
min[0] = vert[0]
|
||||
if vert[1] < min[1] or first:
|
||||
|
@ -361,12 +371,10 @@ class lattice_along_surface(Operator):
|
|||
max[2] = vert[2]
|
||||
first = False
|
||||
|
||||
obj_eval.to_mesh_clear()
|
||||
|
||||
bb = max - min
|
||||
print(bb)
|
||||
lattice_loc = (max + min) / 2
|
||||
bpy.ops.object.add(type='LATTICE', align='WORLD',
|
||||
enter_editmode=False)
|
||||
bpy.ops.object.add(type='LATTICE')
|
||||
lattice = bpy.context.active_object
|
||||
lattice.location = lattice_loc
|
||||
lattice.scale = Vector((bb.x / self.scale_x, bb.y / self.scale_y,
|
||||
|
@ -409,10 +417,10 @@ class lattice_along_surface(Operator):
|
|||
for w in range(nw):
|
||||
if self.use_groups:
|
||||
try:
|
||||
displace = grid_obj.vertex_groups.active.weight(
|
||||
displace = temp_grid_obj.vertex_groups.active.weight(
|
||||
verts_grid[i][j]) * scale_normal * bb.z
|
||||
except:
|
||||
displace = scale_normal * bb.z
|
||||
displace = 0#scale_normal * bb.z
|
||||
else:
|
||||
displace = scale_normal * bb.z
|
||||
target_point = (grid_mesh.vertices[verts_grid[i][j]].co +
|
||||
|
@ -424,15 +432,17 @@ class lattice_along_surface(Operator):
|
|||
i = nu - i - 1
|
||||
if self.flipV:
|
||||
j = nv - j - 1
|
||||
|
||||
lattice.data.points[i + j * nu + w * nu * nv].co_deform.x = \
|
||||
target_point.x / bpy.data.objects[lattice.name].scale.x
|
||||
lattice.data.points[i + j * nu + w * nu * nv].co_deform.y = \
|
||||
target_point.y / bpy.data.objects[lattice.name].scale.y
|
||||
lattice.data.points[i + j * nu + w * nu * nv].co_deform.z = \
|
||||
target_point.z / bpy.data.objects[lattice.name].scale.z
|
||||
|
||||
except:
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
grid_obj.select_set(True)
|
||||
temp_grid_obj.select_set(True)
|
||||
lattice.select_set(True)
|
||||
obj.select_set(False)
|
||||
bpy.ops.object.delete(use_global=False)
|
||||
|
@ -446,15 +456,11 @@ class lattice_along_surface(Operator):
|
|||
self.report({'ERROR'}, "The grid mesh is not correct")
|
||||
return {'CANCELLED'}
|
||||
|
||||
# grid_obj.data = old_grid_data
|
||||
# print(old_grid_matrix)
|
||||
# grid_obj.matrix_world = old_grid_matrix
|
||||
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
grid_obj.select_set(True)
|
||||
lattice.select_set(False)
|
||||
#grid_obj.select_set(True)
|
||||
#lattice.select_set(False)
|
||||
obj.select_set(False)
|
||||
bpy.ops.object.delete(use_global=False)
|
||||
#bpy.ops.object.delete(use_global=False)
|
||||
bpy.context.view_layer.objects.active = lattice
|
||||
lattice.select_set(True)
|
||||
|
||||
|
@ -478,38 +484,7 @@ class lattice_along_surface(Operator):
|
|||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
except:
|
||||
pass
|
||||
bpy.data.meshes.remove(grid_mesh)
|
||||
bpy.data.meshes.remove(obj_me)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
"""
|
||||
class lattice_along_surface_panel(bpy.types.Panel):
|
||||
bl_label = "Modifiers Tools"
|
||||
bl_category = "Tools"
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_region_type = "TOOLS"
|
||||
bl_context = "objectmode"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
col = layout.column(align=True)
|
||||
|
||||
try:
|
||||
col.operator("object.lattice_along_surface", icon="MOD_LATTICE")
|
||||
except:
|
||||
pass
|
||||
"""
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(lattice_along_surface)
|
||||
# bpy.utils.register_class(lattice_along_surface_panel)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(lattice_along_surface)
|
||||
# bpy.utils.unregister_class(lattice_along_surface_panel)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# ##### 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 #####
|
||||
|
||||
from numba import jit
|
||||
import numpy as np
|
||||
|
||||
@jit
|
||||
def numba_reaction_diffusion(n_verts, a, b, diff_a, diff_b, f, k, dt, id0, id1, time_steps):
|
||||
for i in range(time_steps):
|
||||
lap_a = np.zeros(n_verts)
|
||||
lap_b = np.zeros(n_verts)
|
||||
lap_a0 = a[id1] - a[id0] # laplacian increment for first vertex of each edge
|
||||
lap_b0 = b[id1] - b[id0] # laplacian increment for first vertex of each edge
|
||||
|
||||
for i, j, la0, lb0 in zip(id0,id1,lap_a0,lap_b0):
|
||||
lap_a[i] += la0
|
||||
lap_b[i] += lb0
|
||||
lap_a[j] -= la0
|
||||
lap_b[j] -= lb0
|
||||
ab2 = a*b**2
|
||||
#a += eval("(diff_a*lap_a - ab2 + f*(1-a))*dt")
|
||||
#b += eval("(diff_b*lap_b + ab2 - (k+f)*b)*dt")
|
||||
a += (diff_a*lap_a - ab2 + f*(1-a))*dt
|
||||
b += (diff_b*lap_b + ab2 - (k+f)*b)*dt
|
||||
return a, b
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,110 @@
|
|||
import bpy
|
||||
|
||||
#Recursivly transverse layer_collection for a particular name
|
||||
def recurLayerCollection(layerColl, collName):
|
||||
found = None
|
||||
if (layerColl.name == collName):
|
||||
return layerColl
|
||||
for layer in layerColl.children:
|
||||
found = recurLayerCollection(layer, collName)
|
||||
if found:
|
||||
return found
|
||||
|
||||
def auto_layer_collection():
|
||||
# automatically change active layer collection
|
||||
layer = bpy.context.view_layer.active_layer_collection
|
||||
layer_collection = bpy.context.view_layer.layer_collection
|
||||
if layer.hide_viewport or layer.collection.hide_viewport:
|
||||
collections = bpy.context.object.users_collection
|
||||
for c in collections:
|
||||
lc = recurLayerCollection(layer_collection, c.name)
|
||||
if not c.hide_viewport and not lc.hide_viewport:
|
||||
bpy.context.view_layer.active_layer_collection = lc
|
||||
|
||||
def lerp(a, b, t):
|
||||
return a + (b - a) * t
|
||||
|
||||
def _lerp2(v1, v2, v3, v4, v):
|
||||
v12 = v1.lerp(v2,v.x) # + (v2 - v1) * v.x
|
||||
v34 = v3.lerp(v4,v.x) # + (v4 - v3) * v.x
|
||||
return v12.lerp(v34, v.y)# + (v34 - v12) * v.y
|
||||
|
||||
def lerp2(v1, v2, v3, v4, v):
|
||||
v12 = v1 + (v2 - v1) * v.x
|
||||
v34 = v3 + (v4 - v3) * v.x
|
||||
return v12 + (v34 - v12) * v.y
|
||||
|
||||
def lerp3(v1, v2, v3, v4, v):
|
||||
loc = lerp2(v1.co, v2.co, v3.co, v4.co, v)
|
||||
nor = lerp2(v1.normal, v2.normal, v3.normal, v4.normal, v)
|
||||
nor.normalize()
|
||||
return loc + nor * v.z
|
||||
|
||||
def _convert_object_to_mesh(ob, apply_modifiers=True, preserve_status=True):
|
||||
if not apply_modifiers:
|
||||
mod_visibility = [m.show_viewport for m in ob.modifiers]
|
||||
for m in ob.modifiers:
|
||||
m.show_viewport = False
|
||||
if preserve_status:
|
||||
# store status
|
||||
mode = bpy.context.object.mode
|
||||
selected = bpy.context.selected_objects
|
||||
active = bpy.context.object
|
||||
# change status
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
new_ob = ob.copy()
|
||||
new_ob.data = ob.data.copy()
|
||||
bpy.context.collection.objects.link(new_ob)
|
||||
bpy.context.view_layer.objects.active = new_ob
|
||||
new_ob.select_set(True)
|
||||
bpy.ops.object.convert(target='MESH')
|
||||
if preserve_status:
|
||||
# restore status
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
for o in selected: o.select_set(True)
|
||||
bpy.context.view_layer.objects.active = active
|
||||
bpy.ops.object.mode_set(mode=mode)
|
||||
if not apply_modifiers:
|
||||
for m,vis in zip(ob.modifiers,mod_visibility):
|
||||
m.show_viewport = vis
|
||||
return new_ob
|
||||
|
||||
def convert_object_to_mesh(ob, apply_modifiers=True, preserve_status=True):
|
||||
if not ob.name: return None
|
||||
if ob.type != 'MESH':
|
||||
if not apply_modifiers:
|
||||
mod_visibility = [m.show_viewport for m in ob.modifiers]
|
||||
for m in ob.modifiers: m.show_viewport = False
|
||||
#ob.modifiers.update()
|
||||
#dg = bpy.context.evaluated_depsgraph_get()
|
||||
#ob_eval = ob.evaluated_get(dg)
|
||||
#me = bpy.data.meshes.new_from_object(ob_eval, preserve_all_data_layers=True, depsgraph=dg)
|
||||
me = simple_to_mesh(ob)
|
||||
new_ob = bpy.data.objects.new(ob.data.name, me)
|
||||
new_ob.location, new_ob.matrix_world = ob.location, ob.matrix_world
|
||||
if not apply_modifiers:
|
||||
for m,vis in zip(ob.modifiers,mod_visibility): m.show_viewport = vis
|
||||
else:
|
||||
if apply_modifiers:
|
||||
new_ob = ob.copy()
|
||||
new_ob.data = simple_to_mesh(ob)
|
||||
else:
|
||||
new_ob = ob.copy()
|
||||
new_ob.data = ob.data.copy()
|
||||
new_ob.modifiers.clear()
|
||||
bpy.context.collection.objects.link(new_ob)
|
||||
if preserve_status:
|
||||
new_ob.select_set(False)
|
||||
else:
|
||||
for o in bpy.context.view_layer.objects: o.select_set(False)
|
||||
new_ob.select_set(True)
|
||||
bpy.context.view_layer.objects.active = new_ob
|
||||
return new_ob
|
||||
|
||||
def simple_to_mesh(ob):
|
||||
dg = bpy.context.evaluated_depsgraph_get()
|
||||
ob_eval = ob.evaluated_get(dg)
|
||||
me = bpy.data.meshes.new_from_object(ob_eval, preserve_all_data_layers=True, depsgraph=dg)
|
||||
me.calc_normals()
|
||||
return me
|
|
@ -32,7 +32,7 @@ bl_info = {
|
|||
"name": "UV to Mesh",
|
||||
"author": "Alessandro Zomparelli (Co-de-iT)",
|
||||
"version": (0, 1, 1),
|
||||
"blender": (2, 79, 0),
|
||||
"blender": (2, 7, 9),
|
||||
"location": "",
|
||||
"description": "Create a new Mesh based on active UV",
|
||||
"warning": "",
|
||||
|
@ -53,22 +53,22 @@ class uv_to_mesh(Operator):
|
|||
bl_description = ("Create a new Mesh based on active UV")
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
apply_modifiers: BoolProperty(
|
||||
apply_modifiers : BoolProperty(
|
||||
name="Apply Modifiers",
|
||||
default=False,
|
||||
description="Apply object's modifiers"
|
||||
)
|
||||
vertex_groups: BoolProperty(
|
||||
vertex_groups : BoolProperty(
|
||||
name="Keep Vertex Groups",
|
||||
default=False,
|
||||
description="Transfer all the Vertex Groups"
|
||||
)
|
||||
materials: BoolProperty(
|
||||
materials : BoolProperty(
|
||||
name="Keep Materials",
|
||||
default=True,
|
||||
description="Transfer all the Materials"
|
||||
)
|
||||
auto_scale: BoolProperty(
|
||||
auto_scale : BoolProperty(
|
||||
name="Resize",
|
||||
default=True,
|
||||
description="Scale the new object in order to preserve the average surface area"
|
||||
|
@ -76,7 +76,7 @@ class uv_to_mesh(Operator):
|
|||
|
||||
def execute(self, context):
|
||||
bpy.ops.object.mode_set(mode='OBJECT')
|
||||
for o in bpy.data.objects:
|
||||
for o in bpy.data.objects and bpy.context.view_layer.objects:
|
||||
o.select_set(False)
|
||||
bpy.context.object.select_set(True)
|
||||
|
||||
|
@ -85,11 +85,7 @@ class uv_to_mesh(Operator):
|
|||
bpy.ops.object.convert(target='MESH')
|
||||
ob0 = bpy.context.object
|
||||
|
||||
if self.apply_modifiers:
|
||||
depsgraph = context.evaluated_depsgraph_get()
|
||||
me0 = bpy.data.meshes.new_from_object(ob0.evaluated_get(depsgraph))
|
||||
else:
|
||||
me0 = bpy.data.new_from_meshed(ob0)
|
||||
me0 = ob0.to_mesh(bpy.context.depsgraph, apply_modifiers=self.apply_modifiers)
|
||||
area = 0
|
||||
|
||||
verts = []
|
||||
|
@ -122,8 +118,8 @@ class uv_to_mesh(Operator):
|
|||
|
||||
# Link object to scene and make active
|
||||
scn = bpy.context.scene
|
||||
scn.objects.link(ob)
|
||||
scn.objects.active = ob
|
||||
bpy.context.collection.objects.link(ob)
|
||||
bpy.context.view_layer.objects.active = ob
|
||||
ob.select_set(True)
|
||||
|
||||
# Create mesh from given verts, faces.
|
||||
|
@ -144,7 +140,7 @@ class uv_to_mesh(Operator):
|
|||
try:
|
||||
for group in ob0.vertex_groups:
|
||||
index = group.index
|
||||
ob.vertex_groups.new(name=group.name)
|
||||
ob.vertex_groups.new(group.name)
|
||||
for p in me0.polygons:
|
||||
for vert, loop in zip(p.vertices, p.loop_indices):
|
||||
ob.vertex_groups[index].add([loop], group.weight(vert), "ADD")
|
||||
|
@ -183,15 +179,3 @@ class uv_to_mesh(Operator):
|
|||
bpy.context.view_layer.objects.active = ob
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(uv_to_mesh)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(uv_to_mesh)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
|
Loading…
Reference in New Issue