# ***** BEGIN GPL LICENSE BLOCK ***** # # Copyright (C) 2024 Ilia Kurochkin # # Created by Ilia Kurochkin (brothermechanic) # contact: brothermechanic@yandex.com # # This 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 3 # 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, see . # # ***** END GPL LICENSE BLOCK ***** # # coding: utf-8 ''' DESCRIPTION. Basic mesh processing for asset pipeline. DEPRECATED ''' __version__ = '0.1' import bpy def shell_remesher(lowpoly_obj, mod_name='shell_mod', tree_name='shell_tree'): ''' Conctruct geometry nodes modifier. ''' modifier = lowpoly_obj.modifiers.new(mod_name, type='NODES') tree = bpy.data.node_groups.new(name=tree_name, type='GeometryNodeTree') modifier.node_group = tree group_input = tree.nodes.new(type='NodeGroupInput') collection_info = tree.nodes.new(type='GeometryNodeCollectionInfo') collection_info.location = (300, 0) collection_info.transform_space = 'RELATIVE' tree.interface.new_socket(name='Collection', in_out='INPUT', socket_type='NodeSocketCollection') tree.links.new(group_input.outputs['Collection'], collection_info.inputs['Collection']) realize_instances = tree.nodes.new(type='GeometryNodeRealizeInstances') realize_instances.location = (600, 0) tree.links.new(collection_info.outputs[0], realize_instances.inputs['Geometry']) mesh_to_volume = tree.nodes.new(type='GeometryNodeMeshToVolume') mesh_to_volume.location = (900, 0) mesh_to_volume.resolution_mode = 'VOXEL_SIZE' mesh_to_volume.inputs['Density'].default_value = 10.0 mesh_to_volume.inputs['Voxel Size'].default_value = 0.005 #mesh_to_volume.inputs['Exterior Band Width'].default_value = 0.005 tree.links.new(realize_instances.outputs['Geometry'], mesh_to_volume.inputs['Mesh']) volume_to_mesh = tree.nodes.new(type='GeometryNodeVolumeToMesh') volume_to_mesh.location = (1200, 0) tree.links.new(mesh_to_volume.outputs['Volume'], volume_to_mesh.inputs['Volume']) extrude_mesh = tree.nodes.new(type='GeometryNodeExtrudeMesh') extrude_mesh.location = (1500, 0) extrude_mesh.inputs['Offset Scale'].default_value = 0.001 extrude_mesh.inputs['Individual'].default_value = False tree.links.new(volume_to_mesh.outputs['Mesh'], extrude_mesh.inputs['Mesh']) # 1 pass mesh_to_volume = tree.nodes.new(type='GeometryNodeMeshToVolume') mesh_to_volume.location = (1800, 0) mesh_to_volume.resolution_mode = 'VOXEL_SIZE' mesh_to_volume.inputs['Density'].default_value = 1.0 mesh_to_volume.inputs['Voxel Size'].default_value = 0.003 #mesh_to_volume.inputs['Exterior Band Width'].default_value = 0.003 tree.links.new(extrude_mesh.outputs['Mesh'], mesh_to_volume.inputs['Mesh']) volume_to_mesh = tree.nodes.new(type='GeometryNodeVolumeToMesh') volume_to_mesh.location = (2100, 0) tree.links.new(mesh_to_volume.outputs['Volume'], volume_to_mesh.inputs['Volume']) set_position_01 = tree.nodes.new(type='GeometryNodeSetPosition') set_position_01.location = (2400, -300) tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_01.inputs['Geometry']) # 2 pass mesh_to_volume = tree.nodes.new(type='GeometryNodeMeshToVolume') mesh_to_volume.location = (2700, 0) mesh_to_volume.resolution_mode = 'VOXEL_SIZE' mesh_to_volume.inputs['Density'].default_value = 1.0 mesh_to_volume.inputs['Voxel Size'].default_value = 0.001 #mesh_to_volume.inputs['Exterior Band Width'].default_value = 0.001 tree.links.new(set_position_01.outputs['Geometry'], mesh_to_volume.inputs['Mesh']) volume_to_mesh = tree.nodes.new(type='GeometryNodeVolumeToMesh') volume_to_mesh.location = (3000, 0) tree.links.new(mesh_to_volume.outputs['Volume'], volume_to_mesh.inputs['Volume']) set_position_02 = tree.nodes.new(type='GeometryNodeSetPosition') set_position_02.location = (3300, -300) tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_02.inputs['Geometry']) # 3 pass mesh_to_volume = tree.nodes.new(type='GeometryNodeMeshToVolume') mesh_to_volume.location = (3600, 0) mesh_to_volume.resolution_mode = 'VOXEL_SIZE' mesh_to_volume.inputs['Density'].default_value = 1.0 mesh_to_volume.inputs['Voxel Size'].default_value = 0.0005 #mesh_to_volume.inputs['Exterior Band Width'].default_value = 0.0001 tree.links.new(set_position_02.outputs['Geometry'], mesh_to_volume.inputs['Mesh']) volume_to_mesh = tree.nodes.new(type='GeometryNodeVolumeToMesh') volume_to_mesh.location = (3900, 0) tree.links.new(mesh_to_volume.outputs['Volume'], volume_to_mesh.inputs['Volume']) set_position_03 = tree.nodes.new(type='GeometryNodeSetPosition') set_position_03.location = (4200, -300) tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_03.inputs['Geometry']) group_output = tree.nodes.new(type='NodeGroupOutput') group_output.location = (4500, 0) tree.interface.new_socket(name='Geometry', in_out='OUTPUT', socket_type='NodeSocketGeometry') tree.links.new(set_position_03.outputs['Geometry'], group_output.inputs['Geometry']) geometry_proximity = tree.nodes.new(type='GeometryNodeProximity') geometry_proximity.location = (1200, -1000) tree.links.new(realize_instances.outputs['Geometry'], geometry_proximity.inputs['Target']) tree.links.new(geometry_proximity.outputs['Position'], set_position_01.inputs['Position']) tree.links.new(geometry_proximity.outputs['Position'], set_position_02.inputs['Position']) tree.links.new(geometry_proximity.outputs['Position'], set_position_03.inputs['Position']) return modifier