fix rail cret issues

- add transition rail oper
- set sharp edge only when cap is available.
- fix normal flip issue in straight rail.
This commit is contained in:
yyc12345 2024-01-09 17:52:30 +08:00
parent 50b2cf2cf1
commit bfbdf5c99b
2 changed files with 83 additions and 18 deletions

View File

@ -197,6 +197,31 @@ class BBP_OT_add_straight_rail(SharedRailSectionInputProperty, SharedRailCapInpu
layout.label(text = 'Rail Cap') layout.label(text = 'Rail Cap')
self.draw_rail_cap_input(layout) self.draw_rail_cap_input(layout)
class BBP_OT_add_transition_rail(SharedRailCapInputProperty, SharedStraightRailInputProperty, bpy.types.Operator):
"""Add Transition Rail"""
bl_idname = "bbp.add_transition_rail"
bl_label = "Transition Rail"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
_rail_creator_wrapper(
lambda bm: _create_transition_rail(
bm,
c_DefaultRailRadius, c_DefaultRailSpan,
self.general_get_rail_length(),
self.general_get_rail_start_cap(), self.general_get_rail_end_cap()
)
)
return {'FINISHED'}
def draw(self, context):
layout = self.layout
layout.label(text = 'Transition Rail')
self.draw_straight_rail_input(layout)
layout.separator()
layout.label(text = 'Rail Cap')
self.draw_rail_cap_input(layout)
class BBP_OT_add_side_rail(SharedRailCapInputProperty, SharedStraightRailInputProperty, bpy.types.Operator): class BBP_OT_add_side_rail(SharedRailCapInputProperty, SharedStraightRailInputProperty, bpy.types.Operator):
"""Add Side Rail""" """Add Side Rail"""
bl_idname = "bbp.add_side_rail" bl_idname = "bbp.add_side_rail"
@ -357,7 +382,8 @@ def _bmesh_extrude(bm: bmesh.types.BMesh, start_edges: list[bmesh.types.BMEdge],
ret: dict[str, typing.Any] = bmesh.ops.extrude_edge_only( ret: dict[str, typing.Any] = bmesh.ops.extrude_edge_only(
bm, bm,
edges = start_edges, edges = start_edges,
use_normal_flip = False, use_select_history = False use_normal_flip = True, # NOTE: flip normal according to test result.
use_select_history = False
) )
# get end edges # get end edges
@ -404,7 +430,20 @@ def _bmesh_screw(
del ret del ret
return list(filter(lambda x: isinstance(x, bmesh.types.BMEdge), geom_last)) return list(filter(lambda x: isinstance(x, bmesh.types.BMEdge), geom_last))
def _bmesh_smooth_all_edges(bm: bmesh.types.BMesh) -> None:
"""
Resrt all edges to smooth. Call this before calling edge cap function.
"""
# reset all edges to smooth
edge: bmesh.types.BMEdge
for edge in bm.edges:
edge.smooth = True
def _bmesh_cap(bm: bmesh.types.BMesh, edges: list[bmesh.types.BMEdge]) -> None: def _bmesh_cap(bm: bmesh.types.BMesh, edges: list[bmesh.types.BMEdge]) -> None:
"""
Cap given edges. And mark it as sharp edge.
Please reset all edges to smooth one before calling this.
"""
# fill holes # fill holes
bmesh.ops.triangle_fill( bmesh.ops.triangle_fill(
bm, bm,
@ -413,17 +452,8 @@ def _bmesh_cap(bm: bmesh.types.BMesh, edges: list[bmesh.types.BMEdge]) -> None:
# no pass to normal. # no pass to normal.
) )
def _bmesh_mark_sharp(bm: bmesh.types.BMesh, edges: typing.Iterable[list[bmesh.types.BMEdge]]) -> None: # and only set sharp for cap's edges
# Ref: https://blender.stackexchange.com/questions/41351/is-there-a-way-to-select-edges-marked-as-sharp-via-python/41352#41352 for edge in edges:
# reset all edges to smooth
edge: bmesh.types.BMEdge
for edge in bm.edges:
edge.smooth = True
# and only set sharp for specified edges
for subedges in edges:
for edge in subedges:
edge.smooth = False edge.smooth = False
#endregion #endregion
@ -569,14 +599,45 @@ def _create_straight_rail(
bm, start_edges, mathutils.Vector((0, rail_length, 0)) bm, start_edges, mathutils.Vector((0, rail_length, 0))
) )
# smooth geometry
_bmesh_smooth_all_edges(bm)
# cap start and end edges if needed # cap start and end edges if needed
if rail_start_cap: if rail_start_cap:
_bmesh_cap(bm, start_edges) _bmesh_cap(bm, start_edges)
if rail_end_cap: if rail_end_cap:
_bmesh_cap(bm, end_edges) _bmesh_cap(bm, end_edges)
# mark sharp def _create_transition_rail(
_bmesh_mark_sharp(bm, (start_edges, end_edges, )) bm: bmesh.types.BMesh,
rail_radius: float, rail_span: float,
rail_length: float,
rail_start_cap: bool, rail_end_cap: bool) -> None:
"""
Add a transition rail.
The original point is same as `_add_transition_section()`.
The start terminal of this straight will be placed in XZ panel.
The expand direction is +Y.
"""
# create section first
_create_transition_section(bm, rail_radius, rail_span)
# get start edges
start_edges: list[bmesh.types.BMEdge] = bm.edges[:]
# extrude and get end edges
end_edges: list[bmesh.types.BMEdge] = _bmesh_extrude(
bm, start_edges, mathutils.Vector((0, rail_length, 0))
)
# smooth geometry
_bmesh_smooth_all_edges(bm)
# cap start and end edges if needed
if rail_start_cap:
_bmesh_cap(bm, start_edges)
if rail_end_cap:
_bmesh_cap(bm, end_edges)
def _create_screw_rail( def _create_screw_rail(
bm: bmesh.types.BMesh, bm: bmesh.types.BMesh,
@ -608,14 +669,15 @@ def _create_screw_rail(
rail_screw_screw rail_screw_screw
) )
# smooth geometry
_bmesh_smooth_all_edges(bm)
# cap start and end edges if needed # cap start and end edges if needed
if rail_start_cap: if rail_start_cap:
_bmesh_cap(bm, start_edges) _bmesh_cap(bm, start_edges)
if rail_end_cap: if rail_end_cap:
_bmesh_cap(bm, end_edges) _bmesh_cap(bm, end_edges)
_bmesh_mark_sharp(bm, (start_edges, end_edges, ))
#endregion #endregion
def register(): def register():
@ -623,6 +685,7 @@ def register():
bpy.utils.register_class(BBP_OT_add_transition_section) bpy.utils.register_class(BBP_OT_add_transition_section)
bpy.utils.register_class(BBP_OT_add_straight_rail) bpy.utils.register_class(BBP_OT_add_straight_rail)
bpy.utils.register_class(BBP_OT_add_transition_rail)
bpy.utils.register_class(BBP_OT_add_side_rail) bpy.utils.register_class(BBP_OT_add_side_rail)
bpy.utils.register_class(BBP_OT_add_arc_rail) bpy.utils.register_class(BBP_OT_add_arc_rail)
@ -636,6 +699,7 @@ def unregister():
bpy.utils.unregister_class(BBP_OT_add_arc_rail) bpy.utils.unregister_class(BBP_OT_add_arc_rail)
bpy.utils.unregister_class(BBP_OT_add_side_rail) bpy.utils.unregister_class(BBP_OT_add_side_rail)
bpy.utils.unregister_class(BBP_OT_add_transition_rail)
bpy.utils.unregister_class(BBP_OT_add_straight_rail) bpy.utils.unregister_class(BBP_OT_add_straight_rail)
bpy.utils.unregister_class(BBP_OT_add_transition_section) bpy.utils.unregister_class(BBP_OT_add_transition_section)

View File

@ -80,6 +80,7 @@ class BBP_MT_AddRailMenu(bpy.types.Menu):
layout.separator() layout.separator()
layout.label(text = "Straight Rails", icon = 'IPO_CONSTANT') layout.label(text = "Straight Rails", icon = 'IPO_CONSTANT')
layout.operator(OP_ADDS_rail.BBP_OT_add_straight_rail.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_straight_rail.bl_idname)
layout.operator(OP_ADDS_rail.BBP_OT_add_transition_rail.bl_idname)
layout.operator(OP_ADDS_rail.BBP_OT_add_side_rail.bl_idname) layout.operator(OP_ADDS_rail.BBP_OT_add_side_rail.bl_idname)
layout.separator() layout.separator()