Add occlusion management in geometry mode Fixes #2

master
pullusb 2024-02-06 17:21:46 +01:00
parent b8180ea84f
commit 5ca9c9707e
4 changed files with 38 additions and 37 deletions

View File

@ -1,7 +1,7 @@
bl_info = {
"name": "gp interpolate",
"author": "Christophe Seux, Samuel Bernou",
"version": (0, 5, 0),
"version": (0, 6, 0),
"blender": (3, 6, 0),
"location": "Sidebar > Gpencil Tab > Interpolate",
"description": "Interpolate Grease pencil strokes over 3D",

View File

@ -24,7 +24,7 @@ from mathutils.geometry import (barycentric_transform,
## TODO: add bake animation to empty for later GP layer parenting
## TODO: Occlusion management
## TODO: Convert operator to Modal to Stop animation
class GP_OT_interpolate_stroke(bpy.types.Operator):
bl_idname = "gp.interpolate_stroke"
@ -258,6 +258,7 @@ class GP_OT_interpolate_stroke(bpy.types.Operator):
matrix_inv = np.array(gp.matrix_world.inverted(), dtype='float64')#.inverted()
new_strokes = gp.data.layers.active.active_frame.strokes[-len(strokes_data):]
# for new_stroke, stroke_data in zip(new_strokes, strokes_data):
for new_stroke, stroke_data in zip(reversed(new_strokes), reversed(strokes_data)):
world_co_3d = []
for stroke, point_co, object_hit, hit_location, tri_a, tri_indices in stroke_data:
@ -291,47 +292,43 @@ class GP_OT_interpolate_stroke(bpy.types.Operator):
new_stroke.points.update()
## TODO: Occlusion management
## Tag occlusion on points for removal (need to create all substrokes from existing strokes)
# if settings.method == 'GEOMETRY':
# ## WIP
# occlusion_list = [False]*len(world_co_3d)
# for i, nco in enumerate(world_co_3d):
# vec_direction = nco - origin
# ## Maybe distance need to be reduced by tiny segment...
# n_hit, _hit_location, _normal, _n_face_index, n_object_hit, _matrix = scn.ray_cast(dg, origin, vec_direction, distance=vec_direction.length)
# # if n_hit and n_object_hit != object_hit: # note: Arm could still hit from torso...
# if n_hit:
# # if there is a hit, it's occluded
# # Occluded !
# occlusion_list[i] = True
## Occlusion management
if settings.method == 'GEOMETRY' and settings.remove_occluded:
viz_list = [True]*len(world_co_3d)
for i, nco in enumerate(world_co_3d):
vec_direction = nco - origin
## Reduced distance slightly to avoid occlusion on same source...
dist = vec_direction.length - 0.001
n_hit, _hit_location, _normal, _n_face_index, n_object_hit, _matrix = scn.ray_cast(dg, origin, vec_direction, distance=dist)
# if there is a hit, it's occluded
if n_hit:
viz_list[i] = False
# if all(occlusion_list):
# # all occluded, Just remove stroke (! Safer to reverse both list in zip iteration !)
# gp.data.layers.active.active_frame.strokes.remove(new_stroke)
if all(viz_list):
# All visible, do nothing (just keep previous stroke)
continue
# if any(occlusion_list):
# # Create substroke according to indices in original stroke
# for sublist in index_list_from_bools(occlusion_list):
# ## Clear if only one isolated point ?
# # if len(sublist) == 1:
# # continue
# ns = gp.data.layers.active.active_frame.strokes.new()
# for elem in ('hardness', 'material_index', 'line_width'):
# setattr(ns, elem, getattr(new_strokes, elem))
if any(viz_list):
# Create sub-strokes according to indices in original stroke
for sublist in index_list_from_bools(viz_list):
## Clear if only one isolated point ?
if len(sublist) == 1:
continue
# ns.points.add(len(sublist))
# for i, point_index in enumerate(sublist):
# for elem in ('uv_factor', 'uv_fill', 'uv_rotation', 'pressure', 'co', 'strength', 'vertex_color'):
# setattr(ns.points[i], elem, getattr(new_strokes.points[point_index], elem))
ns = gp.data.layers.active.active_frame.strokes.new()
for elem in ('hardness', 'material_index', 'line_width'):
setattr(ns, elem, getattr(new_stroke, elem))
# ## Delete original stroke
# gp.data.layers.active.active_frame.strokes.remove(new_stroke)
ns.points.add(len(sublist))
for i, point_index in enumerate(sublist):
for elem in ('uv_factor', 'uv_fill', 'uv_rotation', 'pressure', 'co', 'strength', 'vertex_color'):
setattr(ns.points[i], elem, getattr(new_stroke.points[point_index], elem))
## Delete original stroke
gp.data.layers.active.active_frame.strokes.remove(new_stroke)
wm.progress_end() # Pgs
if debug:
print(f"Paste'n'place time {time()-start - scan_time}s")
else:

View File

@ -29,6 +29,10 @@ class GP_PG_interpolate_settings(PropertyGroup):
default=False,
description='Apply the interpolation on the all keys forward or backward')
remove_occluded : BoolProperty(name='Remove Occluded Points',
default=False,
description='Remove point when occluded by geometry (works best in animation mode)')
search_range : FloatProperty(
name="Search Range",
description="Search range size when points are out of mesh\

2
ui.py
View File

@ -38,10 +38,10 @@ class GP_PT_interpolate(bpy.types.Panel):
col.prop_search(settings, 'target_bone', settings.target_rig.pose, 'bones', text='Bone')
col.prop(settings, 'use_bone_rotation', text='Use Bone Rotation')
elif settings.method == 'GEOMETRY':
col.prop(settings, 'target_collection', text='Collection')
col.prop(settings, 'search_range')
col.prop(settings, 'remove_occluded')
elif settings.method == 'OBJECT':
col.prop(settings, 'target_object', text='Object')