[Blender] Алгоритм ретопологии полного цикла. #82

Closed
opened 2023-06-14 11:53:05 +03:00 by brothermechanic · 10 comments
brothermechanic commented 2023-06-14 11:53:05 +03:00 (Migrated from gitlab.com)

highpoly > lowpoly

highpoly > lowpoly
brothermechanic commented 2023-06-14 11:53:09 +03:00 (Migrated from gitlab.com)

assigned to @brothermechanic

assigned to @brothermechanic
brothermechanic commented 2023-06-14 11:53:32 +03:00 (Migrated from gitlab.com)
import bpy
from collections import  defaultdict

import sys
scr = '/media/disk/robossembler/project/collab/74-blender_obj_joiner/cg/blender/utils/'
sys.path.append(scr)
from apply_transforms import apply_transforms


def copy_objects(from_col, to_col, linked, dupe_lut):
    for o in from_col.objects:
        dupe = o.copy()
        if not linked and o.data:
            dupe.data = dupe.data.copy()
        to_col.objects.link(dupe)
        dupe_lut[o] = dupe


def copy(parent, collection, suffix = '', linked=False):
    dupe_lut = defaultdict(lambda : None)
    def _copy(parent, collection, linked=False):
        cc = bpy.data.collections.new(collection.name + suffix)
        copy_objects(collection, cc, linked, dupe_lut)

        for c in collection.children:
            _copy(cc, c, linked)

        parent.children.link(cc)

    _copy(parent, collection, linked)
    print(dupe_lut)
    for o, dupe in tuple(dupe_lut.items()):
        parent = dupe_lut[o.parent]
        if parent:
            dupe.parent = parent


highpoly_col = bpy.data.collections.new('Highpoly')
bpy.context.scene.collection.children.link(highpoly_col)

col_parts = bpy.data.collections['Import Parts']
parts = [col for col in col_parts.children if col.name.endswith('_in')]

for part in parts:
    copy(highpoly_col, part, '_hp')

parts = bpy.data.collections['Highpoly'].children
for part in parts:
    bpy.ops.object.select_all(action='DESELECT')
    for obj in part.objects:
        if obj.type == 'MESH':
            obj.select_set(True)
            bpy.context.view_layer.objects.active = obj
        bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
    bpy.ops.object.join()
    mesh = bpy.context.object
    mesh.name = part.name
    part.objects.unlink(mesh)
    highpoly_col.objects.link(mesh)
    apply_transforms(mesh, location=True, rotation=True, scale=True)
    for obj in part.objects:
        if obj.type != 'MESH':
            bpy.data.objects.remove(obj, do_unlink=True)
    bpy.data.collections.remove(part)
```python import bpy from collections import defaultdict import sys scr = '/media/disk/robossembler/project/collab/74-blender_obj_joiner/cg/blender/utils/' sys.path.append(scr) from apply_transforms import apply_transforms def copy_objects(from_col, to_col, linked, dupe_lut): for o in from_col.objects: dupe = o.copy() if not linked and o.data: dupe.data = dupe.data.copy() to_col.objects.link(dupe) dupe_lut[o] = dupe def copy(parent, collection, suffix = '', linked=False): dupe_lut = defaultdict(lambda : None) def _copy(parent, collection, linked=False): cc = bpy.data.collections.new(collection.name + suffix) copy_objects(collection, cc, linked, dupe_lut) for c in collection.children: _copy(cc, c, linked) parent.children.link(cc) _copy(parent, collection, linked) print(dupe_lut) for o, dupe in tuple(dupe_lut.items()): parent = dupe_lut[o.parent] if parent: dupe.parent = parent highpoly_col = bpy.data.collections.new('Highpoly') bpy.context.scene.collection.children.link(highpoly_col) col_parts = bpy.data.collections['Import Parts'] parts = [col for col in col_parts.children if col.name.endswith('_in')] for part in parts: copy(highpoly_col, part, '_hp') parts = bpy.data.collections['Highpoly'].children for part in parts: bpy.ops.object.select_all(action='DESELECT') for obj in part.objects: if obj.type == 'MESH': obj.select_set(True) bpy.context.view_layer.objects.active = obj bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM') bpy.ops.object.join() mesh = bpy.context.object mesh.name = part.name part.objects.unlink(mesh) highpoly_col.objects.link(mesh) apply_transforms(mesh, location=True, rotation=True, scale=True) for obj in part.objects: if obj.type != 'MESH': bpy.data.objects.remove(obj, do_unlink=True) bpy.data.collections.remove(part) ```
brothermechanic commented 2023-06-14 13:37:42 +03:00 (Migrated from gitlab.com)
import bpy

o_from = bpy.data.objects['remesh']

lowpoly_col = bpy.data.collections.new('Lowpoly')
bpy.context.scene.collection.children.link(lowpoly_col)

hps = bpy.data.collections['Highpoly'].objects


def copy_modifiers(o_from, o_to):
    for m in o_from.modifiers:
        nm = o_to.modifiers.new(type=m.type, name=m.name)
        for prop in dir(m):
            try:
                setattr(nm, prop, getattr(m, prop))
            except:
                pass
        if m.type == 'NODES':
            #print("Input #2", m["Input_2"])
            for input in m.node_group.inputs[1:]:
                #print(m[input.identifier])
                o_to.modifiers[m.name][input.identifier] = m[input.identifier]


for obj in hps:
    bpy.ops.object.select_all(action='DESELECT')
    bpy.ops.mesh.primitive_plane_add(
        size=0.1, location=(0.0, 0.0, 0.0), scale=(1, 1, 1))
    mesh = bpy.context.object
    mesh.name = obj.name.split('_hp')[0] + '_lp'
    bpy.context.scene.collection.objects.unlink(mesh)
    lowpoly_col.objects.link(mesh)
    copy_modifiers(o_from, mesh)
    mesh.modifiers['GeometryNodes']['Input_2'] = obj
```python import bpy o_from = bpy.data.objects['remesh'] lowpoly_col = bpy.data.collections.new('Lowpoly') bpy.context.scene.collection.children.link(lowpoly_col) hps = bpy.data.collections['Highpoly'].objects def copy_modifiers(o_from, o_to): for m in o_from.modifiers: nm = o_to.modifiers.new(type=m.type, name=m.name) for prop in dir(m): try: setattr(nm, prop, getattr(m, prop)) except: pass if m.type == 'NODES': #print("Input #2", m["Input_2"]) for input in m.node_group.inputs[1:]: #print(m[input.identifier]) o_to.modifiers[m.name][input.identifier] = m[input.identifier] for obj in hps: bpy.ops.object.select_all(action='DESELECT') bpy.ops.mesh.primitive_plane_add( size=0.1, location=(0.0, 0.0, 0.0), scale=(1, 1, 1)) mesh = bpy.context.object mesh.name = obj.name.split('_hp')[0] + '_lp' bpy.context.scene.collection.objects.unlink(mesh) lowpoly_col.objects.link(mesh) copy_modifiers(o_from, mesh) mesh.modifiers['GeometryNodes']['Input_2'] = obj ```
brothermechanic commented 2023-06-15 22:13:35 +03:00 (Migrated from gitlab.com)
import bpy

# tree = bpy.data.node_groups[tree_name]

lowpoly_col = bpy.data.collections['Collection']

lowpoly_name = 'test_lp'
lowpoly_mesh = bpy.data.meshes.new(lowpoly_name)
lowpoly_obj = bpy.data.objects.new(lowpoly_name, lowpoly_mesh)
lowpoly_col.objects.link(lowpoly_obj)

lowpoly_obj.select_set(True)
bpy.context.view_layer.objects.active = lowpoly_obj

tree_name = 'robossembler'

remesh_nodes = lowpoly_obj.modifiers.new('remesh_nodes',type='NODES')

tree = bpy.data.node_groups.new(name=tree_name, type='GeometryNodeTree')

remesh_nodes.node_group = tree

group_input = tree.nodes.new(type="NodeGroupInput")

object_info = tree.nodes.new(type="GeometryNodeObjectInfo")
object_info.location = (300, 0)

tree.inputs.new('NodeSocketObject', 'Object')
tree.links.new(group_input.outputs['Object'], object_info.inputs['Object'])

mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume")
mesh_to_volume.location = (600, 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(object_info.outputs['Geometry'], mesh_to_volume.inputs['Mesh'])

volume_to_mesh = tree.nodes.new(type="GeometryNodeVolumeToMesh")
volume_to_mesh.location = (900, 0)

tree.links.new(mesh_to_volume.outputs['Volume'], volume_to_mesh.inputs['Volume'])

extrude_mesh = tree.nodes.new(type="GeometryNodeExtrudeMesh")
extrude_mesh.location = (1200, 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'])


mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume")
mesh_to_volume.location = (1500, 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 = (1800, 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 = (2100, -300)

tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_01.inputs['Geometry'])


mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume")
mesh_to_volume.location = (2400, 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 = (2700, 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 = (3000, -300)

tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_02.inputs['Geometry'])


mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume")
mesh_to_volume.location = (3300, 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 = (3600, 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 = (3900, -300)

tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_03.inputs['Geometry'])


group_output = tree.nodes.new(type="NodeGroupOutput")
group_output.location = (4200, 0)

tree.outputs.new('NodeSocketGeometry', 'Geometry')
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(object_info.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'])


remesh_voxel = lowpoly_obj.modifiers.new('remesh_voxel',type='REMESH')
remesh_voxel.mode = 'VOXEL'
remesh_voxel.voxel_size = 0.001

remesh_sharp = lowpoly_obj.modifiers.new('remesh_sharp',type='REMESH')
remesh_sharp.mode = 'SHARP'
remesh_sharp.octree_depth = 7

decimate = lowpoly_obj.modifiers.new('decimate',type='DECIMATE')
decimate.decimate_type = 'COLLAPSE'
decimate.ratio = 0.1

```python import bpy # tree = bpy.data.node_groups[tree_name] lowpoly_col = bpy.data.collections['Collection'] lowpoly_name = 'test_lp' lowpoly_mesh = bpy.data.meshes.new(lowpoly_name) lowpoly_obj = bpy.data.objects.new(lowpoly_name, lowpoly_mesh) lowpoly_col.objects.link(lowpoly_obj) lowpoly_obj.select_set(True) bpy.context.view_layer.objects.active = lowpoly_obj tree_name = 'robossembler' remesh_nodes = lowpoly_obj.modifiers.new('remesh_nodes',type='NODES') tree = bpy.data.node_groups.new(name=tree_name, type='GeometryNodeTree') remesh_nodes.node_group = tree group_input = tree.nodes.new(type="NodeGroupInput") object_info = tree.nodes.new(type="GeometryNodeObjectInfo") object_info.location = (300, 0) tree.inputs.new('NodeSocketObject', 'Object') tree.links.new(group_input.outputs['Object'], object_info.inputs['Object']) mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume") mesh_to_volume.location = (600, 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(object_info.outputs['Geometry'], mesh_to_volume.inputs['Mesh']) volume_to_mesh = tree.nodes.new(type="GeometryNodeVolumeToMesh") volume_to_mesh.location = (900, 0) tree.links.new(mesh_to_volume.outputs['Volume'], volume_to_mesh.inputs['Volume']) extrude_mesh = tree.nodes.new(type="GeometryNodeExtrudeMesh") extrude_mesh.location = (1200, 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']) mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume") mesh_to_volume.location = (1500, 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 = (1800, 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 = (2100, -300) tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_01.inputs['Geometry']) mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume") mesh_to_volume.location = (2400, 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 = (2700, 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 = (3000, -300) tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_02.inputs['Geometry']) mesh_to_volume = tree.nodes.new(type="GeometryNodeMeshToVolume") mesh_to_volume.location = (3300, 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 = (3600, 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 = (3900, -300) tree.links.new(volume_to_mesh.outputs['Mesh'], set_position_03.inputs['Geometry']) group_output = tree.nodes.new(type="NodeGroupOutput") group_output.location = (4200, 0) tree.outputs.new('NodeSocketGeometry', 'Geometry') 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(object_info.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']) remesh_voxel = lowpoly_obj.modifiers.new('remesh_voxel',type='REMESH') remesh_voxel.mode = 'VOXEL' remesh_voxel.voxel_size = 0.001 remesh_sharp = lowpoly_obj.modifiers.new('remesh_sharp',type='REMESH') remesh_sharp.mode = 'SHARP' remesh_sharp.octree_depth = 7 decimate = lowpoly_obj.modifiers.new('decimate',type='DECIMATE') decimate.decimate_type = 'COLLAPSE' decimate.ratio = 0.1 ```
brothermechanic commented 2023-06-16 20:02:42 +03:00 (Migrated from gitlab.com)

changed title from [Bledner] {-Техпроцесс компьютерной графики-} to [Bledner] {+Алгоритм ретопологии.+}

changed title from **[Bledner] {-Техпроцесс компьютерной графики-}** to **[Bledner] {+Алгоритм ретопологии.+}**
movefasta commented 2023-06-18 19:00:10 +03:00 (Migrated from gitlab.com)

changed title from [Ble{-d-}ner] Алгоритм ретопологии. to [Blen{+d+}er] Алгоритм ретопологии.

changed title from **[Ble{-d-}ner] Алгоритм ретопологии.** to **[Blen{+d+}er] Алгоритм ретопологии.**
brothermechanic commented 2023-06-19 12:03:32 +03:00 (Migrated from gitlab.com)

marked this issue as related to #83

marked this issue as related to #83
brothermechanic commented 2023-06-19 12:04:38 +03:00 (Migrated from gitlab.com)

changed title from [Blender] Алгоритм ретопологии. to [Blender] Алгоритм ретопологии{+ полного цикла+}.

changed title from **[Blender] Алгоритм ретопологии.** to **[Blender] Алгоритм ретопологии{+ полного цикла+}.**
brothermechanic commented 2023-06-19 12:04:38 +03:00 (Migrated from gitlab.com)

changed the description

changed the description
brothermechanic (Migrated from gitlab.com) closed this issue 2023-06-19 22:54:57 +03:00
brothermechanic commented 2023-06-19 23:02:51 +03:00 (Migrated from gitlab.com)

mentioned in merge request !36

mentioned in merge request !36
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
robossembler/framework#82
No description provided.