Skip to content

Commit

Permalink
ポリペン追加
Browse files Browse the repository at this point in the history
  • Loading branch information
sakana3 committed Feb 22, 2020
1 parent b2f3b37 commit dfbf937
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 81 deletions.
66 changes: 32 additions & 34 deletions Addons/PolyQuilt/subtools/subtool_edge_extrude.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,53 +50,51 @@ def __init__(self,op, target : ElementItem, is_loop : bool = False ) :
self.ignoreEdges.extend(face.edges)
self.ignoreEdges = set(self.ignoreEdges )

self.newEdge = [ self.bmo.local_to_world_pos( self.currentEdge.element.verts[0].co ) , self.bmo.local_to_world_pos( self.currentEdge.element.verts[1].co ) ]
self.newEdge = [ self.bmo.local_to_world_pos( v.co ) for v in self.currentEdge.element.verts ]

# calc perpendicular
view_matrix = bpy.context.region_data.view_matrix
view_vector = bpy.context.region_data.view_rotation.to_matrix() @ mathutils.Vector((0.0, 0.0, -1.0))
vp0 = view_matrix @ self.newEdge[0]
vp1 = view_matrix @ self.newEdge[1]
vs0 = mathutils.Vector(( vp0.x , vp0.y , 0.0))
vs1 = mathutils.Vector(( vp1.x , vp1.y , 0.0))
n = (vs1 - vs0).normalized()
vp = [ view_matrix @ v for v in self.newEdge ]
vs = [ mathutils.Vector(( v.x , v.y , 0.0)) for v in vp ]
n = (vs[1] - vs[0]).normalized()
self.perpendicular = view_vector.cross( n.xyz ).normalized()

@staticmethod
def Check( root ,target ) :
return target.element.is_boundary or target.element.is_manifold == False

def CalcFin( self , context , v0 , v1 , move ) :
region = context.region
rv3d = context.region_data
view_matrix = rv3d.view_matrix
view_vector = rv3d.view_rotation.to_matrix() @ mathutils.Vector((0.0, 0.0, -1.0))
region = context.region
rv3d = context.region_data
view_matrix = rv3d.view_matrix
view_vector = rv3d.view_rotation.to_matrix() @ mathutils.Vector((0.0, 0.0, -1.0))

n = ( view_matrix.to_3x3() @ move ).xy.normalized()
r0 = math.atan2( n.y , n.x )
r1 = math.atan2( self.perpendicular.y , self.perpendicular.x )
n = ( view_matrix.to_3x3() @ move ).xy.normalized()
r0 = math.atan2( n.y , n.x )
r1 = math.atan2( self.perpendicular.y , self.perpendicular.x )

q0 = mathutils.Quaternion( view_vector , r0 )
q1 = mathutils.Quaternion( view_vector , r1 )
q0 = mathutils.Quaternion( view_vector , r0 )
q1 = mathutils.Quaternion( view_vector , r1 )

q = q0.rotation_difference(q1)
q = q0.rotation_difference(q1)

f0 = self.bmo.local_to_world_pos(v0.co) - self.startPos
f1 = self.bmo.local_to_world_pos(v1.co) - self.startPos
f0 = self.bmo.local_to_world_pos(v0.co) - self.startPos
f1 = self.bmo.local_to_world_pos(v1.co) - self.startPos

if self.operator.extrude_mode != 'PARALLEL' :
if self.operator.extrude_mode == 'BEND' :
f0 = q.to_matrix() @ f0
f1 = q.to_matrix() @ f1
else :
f0 = q.to_matrix() @ q.to_matrix() @ f0
f1 = q.to_matrix() @ q.to_matrix() @ f1
if self.operator.extrude_mode != 'PARALLEL' :
if self.operator.extrude_mode == 'BEND' :
f0 = q.to_matrix() @ f0
f1 = q.to_matrix() @ f1
else :
f0 = q.to_matrix() @ q.to_matrix() @ f0
f1 = q.to_matrix() @ q.to_matrix() @ f1

p0 = self.targetPos + f0
p1 = self.targetPos + f1
p0 = QSnap.view_adjust(p0)
p1 = QSnap.view_adjust(p1)
return [p0,p1]
p0 = self.targetPos + f0
p1 = self.targetPos + f1
p0 = QSnap.view_adjust(p0)
p1 = QSnap.view_adjust(p1)
return [p0,p1]

def OnUpdate( self , context , event ) :
if event.type == 'MOUSEMOVE':
Expand Down Expand Up @@ -238,11 +236,11 @@ def AdsorptionEdge( self , p0 , p1 , edge ) :
se0 = pqutil.location_3d_to_region_2d(self.bmo.local_to_world_pos(edge.verts[0].co))
se1 = pqutil.location_3d_to_region_2d(self.bmo.local_to_world_pos(edge.verts[1].co))
if (st0-se0).length + (st1-se1).length > (st0-se1).length + (st1-se0).length :
t0 = self.snapTarget.element.verts[1]
t1 = self.snapTarget.element.verts[0]
t0 = edge.verts[1]
t1 = edge.verts[0]
else :
t0 = self.snapTarget.element.verts[0]
t1 = self.snapTarget.element.verts[1]
t0 = edge.verts[0]
t1 = edge.verts[1]

return t0,t1

Expand Down
182 changes: 135 additions & 47 deletions Addons/PolyQuilt/subtools/subtool_polypen.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,31 @@ def __init__(self , op , target : ElementItem ) :
self.startMousePos = copy.copy(target.coord)

self.startEdge = target.element
self.startData = self.CalcStart( target.verts )
self.startData = [ self.CalcStart( target.verts ) ]
self.endData = None

@staticmethod
def Check( root ,target ) :
return target.isEdge and target.can_extrude() and False
return target.isEdge and target.can_extrude()

def OnUpdate( self , context , event ) :
if event.type == 'MOUSEMOVE':
self.endData = self.CalcEnd( self.mouse_pos )
if self.startData != None and self.endData != None :
# print(( self.startData.Center - self.endData.Center ).length)
if ( self.startData.Center - self.endData.Center ).length > self.startData.Witdh :
self.MakePoly()
dist = self.preferences.distance_to_highlight
hitEdge = self.bmo.PickElement( self.mouse_pos , dist , edgering=True , backface_culling = True , elements=['EDGE'], ignore=[self.startEdge] )
if hitEdge.isEdge :
self.endData = self.AdsorptionEdge( self.startData[-1].WorldPos[0] , self.startData[-1].WorldPos[1] , hitEdge.element )
else :
while( True ) :
sd = self.startData[-1]
v = ( self.mouse_pos - sd.Center )
pos = sd.Center + v.normalized() * min( sd.Witdh , v.length )
self.endData = self.CalcEnd( pos )
self.ReCalcFin()
if self.startData != None and self.endData != None :
if v.length >= sd.Witdh :
self.MakePoly()
continue
break

elif event.type == 'RIGHTMOUSE' :
if event.value == 'PRESS' :
Expand All @@ -60,64 +71,122 @@ def OnUpdate( self , context , event ) :
pass
elif event.type == 'LEFTMOUSE' :
if event.value == 'RELEASE' :
if self.endData != None :
self.MakePoly()
return 'FINISHED'
return 'RUNNING_MODAL'

def OnDraw( self , context ) :
pass

def OnDraw3D( self , context ) :
if self.startData != None and self.endData != None :
verts = [ self.startData.WorldPos[0] , self.startData.WorldPos[1] , self.endData.WorldPos[0] , self.endData.WorldPos[1] ]
draw_util.draw_Poly3D( context , verts , color = self.color_create(0.5) )
startData = self.startData[-1]
if startData != None and self.endData != None :
alpha = (startData.Center - self.mouse_pos).length / startData.Witdh

verts = [ startData.WorldPos[0] , startData.WorldPos[1] , self.endData.WorldPos[1] , self.endData.WorldPos[0] ]
draw_util.draw_Poly3D( context , verts , color = self.color_create(alpha / 2) )
verts.append( verts[-1] )
draw_util.draw_lines3D( context , verts , color = self.color_create() , width = 2 )

def CalcStart( self , verts ) :
startVerts = verts[:]
startWPs = [ self.bmo.obj.matrix_world @ v.co for v in startVerts ]
startPlane = [ pqutil.Plane.from_screen( bpy.context , v ) for v in startWPs ]
startPos = [ pqutil.location_3d_to_region_2d(v) for v in startWPs ]
startCenetr = ( startPos[0] + startPos[1] ) / 2
width = ( startPos[0] - startPos[1] ).length

Ret = namedtuple('Ret', ('Verts','WorldPos', 'Plane' , 'ViewPos' , 'Center' , 'Witdh'))
ret = Ret(Verts=startVerts,WorldPos=startWPs,Plane=startPlane, ViewPos = startPos , Center = startCenetr , Witdh = width )
draw_util.draw_lines3D( context , verts , color = self.color_create(alpha ) , width = 2 )

def CalcStart( self , verts , center = None ) :
wpos = [ self.bmo.obj.matrix_world @ v.co for v in verts ]
planes = [ pqutil.Plane.from_screen( bpy.context , v ) for v in wpos ]
vpos = [ pqutil.location_3d_to_region_2d(v) for v in wpos ]
if center == None :
center = ( vpos[0] + vpos[1] ) / 2
vec = ( vpos[0] - vpos[1] )
width = vec.length
nrm = vec.normalized()

perpendicular = mathutils.Vector( (0,0,1) ).cross( mathutils.Vector( (nrm.x,nrm.y,0) ) ).normalized()

Ret = namedtuple('Ret', ('Verts','WorldPos', 'Plane' , 'ViewPos' , 'Center' , 'Witdh', 'Perpendicular' ))
ret = Ret(Verts=verts[:],WorldPos=wpos,Plane=planes, ViewPos = vpos , Center = center , Witdh = width , Perpendicular = perpendicular )
return ret

def CalcEnd( self , mouse_pos ) :
if (self.startData.Center - mouse_pos).length <= sys.float_info.epsilon :
return None
Ret = namedtuple('Ret', ('WorldPos', 'ViewPos' , 'Center', 'Verts' ))

start = self.startData[-1]
context = bpy.context
start = self.startData
p0 = mouse_pos + start.ViewPos[0] - start.Center
p1 = mouse_pos + start.ViewPos[1] - start.Center
lengh = (p0-mouse_pos).length
vec = mathutils.Matrix.Rotation(math.radians(90.0), 2, 'Z') @ (mouse_pos - start.Center).normalized()
nrm = (start.ViewPos[0]-mouse_pos).normalized()

if vec.dot(nrm) < 0 :
p0 = mouse_pos + vec * lengh
p1 = mouse_pos - vec * lengh

vec = (mouse_pos - start.Center )
nrm = ( mouse_pos - start.Center ).normalized()

if vec.length <= sys.float_info.epsilon :
return None
mouse_pos = start.Center + nrm * max( start.Witdh , vec.length )

r0 = math.atan2( nrm.x , nrm.y )
if nrm.dot(start.Perpendicular) > 0 :
r1 = math.atan2( start.Perpendicular.x , start.Perpendicular.y )
else :
p0 = mouse_pos - vec * lengh
p1 = mouse_pos + vec * lengh
r1 = math.atan2( -start.Perpendicular.x , -start.Perpendicular.y )

q0 = mathutils.Quaternion( mathutils.Vector( (0,0,1) ) , r0 )
q1 = mathutils.Quaternion( mathutils.Vector( (0,0,1) ) , r1 )

r0 = pqutil.Ray.from_screen( bpy.context , p0 )
r1 = pqutil.Ray.from_screen( bpy.context , p1 )
v0 = start.Plane[0].intersect_ray( r0 )
v1 = start.Plane[1].intersect_ray( r1 )
q = q0.rotation_difference(q1)

Ret = namedtuple('Ret', ('WorldPos', 'ViewPos' , 'Center' ))
ret = Ret(WorldPos = [v0,v1] , ViewPos = [p0,p1] , Center = mouse_pos )
f = [ v - start.Center for v in start.ViewPos ]
ft = [ q.to_matrix() @ v.to_3d() for v in f ]
pt = [ mouse_pos + v.xy for v in ft ]
rt = [ pqutil.Ray.from_screen( context , v ) for v in pt ]
vt = [ p.intersect_ray( r ) for r,p in zip(rt , start.Plane) ]
vt = [ QSnap.view_adjust( p ) for p in vt ]

ret = Ret(WorldPos = vt , ViewPos = pt , Center = mouse_pos , Verts = [None,None] )
return ret

def ReCalcFin( self ) :
if len( self.startData ) < 2 :
return
context = bpy.context
finP = self.startData[-2]
fin1 = self.startData[-1]

n = ( finP.Center - self.endData.Center ).normalized()
r0 = math.atan2( n.x , n.y )
if n.dot(finP.Perpendicular) > 0 :
r1 = math.atan2( finP.Perpendicular.x , finP.Perpendicular.y )
else :
r1 = math.atan2( -finP.Perpendicular.x , -finP.Perpendicular.y )

q0 = mathutils.Quaternion( mathutils.Vector( (0,0,1) ) , r0 )
q1 = mathutils.Quaternion( mathutils.Vector( (0,0,1) ) , r1 )

q = q0.rotation_difference(q1)

f = [ v - finP.Center for v in finP.ViewPos ]
ft = [ q.to_matrix() @ v.to_3d() for v in f ]
pt = [ fin1.Center + v.xy for v in ft ]
rt = [ pqutil.Ray.from_screen( context , v ) for v in pt ]
vt = [ p.intersect_ray( r ) for r,p in zip(rt , finP.Plane) ]
vt = [ QSnap.view_adjust( p ) for p in vt ]

for v , p in zip( fin1.Verts , vt ) :
if self.bmo.is_mirror_mode :
mirror = self.bmo.find_mirror(v)

self.bmo.set_positon( v , p , is_world = True )

if self.bmo.is_mirror_mode and mirror != None :
self.bmo.set_positon( mirror , self.bmo.mirror_world_pos( p ) , is_world = True )
self.bmo.UpdateMesh()

self.startData[-1] = self.CalcStart( fin1.Verts , fin1.Center )

def MakePoly( self ) :
verts = [ self.startData.Verts[0] , self.startData.Verts[1] ]
startData = self.startData[-1]
verts = [ startData.Verts[0] , startData.Verts[1] ]
nv = []
for p in self.endData.WorldPos :
v = self.bmo.AddVertexWorld( p )

for p , vt in zip( self.endData.WorldPos[::-1] , self.endData.Verts[::-1] ) :
if vt != None :
v = vt
else :
v = self.bmo.AddVertexWorld( p )
verts.append( v )
nv.append( v )

Expand All @@ -130,5 +199,24 @@ def MakePoly( self ) :
for e in face.edges :
if set( e.verts ) == set( nv ) :
self.startEdge = e
self.startData = self.CalcStart( nv )
self.endData = None
self.startData.append( self.CalcStart( nv[::-1] ) )
self.endData = None


def AdsorptionEdge( self , p0 , p1 , edge ) :
Ret = namedtuple('Ret', ('WorldPos', 'ViewPos' , 'Center' , 'Verts' ))

st0 = pqutil.location_3d_to_region_2d(p0)
st1 = pqutil.location_3d_to_region_2d(p1)
se0 = pqutil.location_3d_to_region_2d(self.bmo.local_to_world_pos(edge.verts[0].co))
se1 = pqutil.location_3d_to_region_2d(self.bmo.local_to_world_pos(edge.verts[1].co))
if (st0-se0).length + (st1-se1).length > (st0-se1).length + (st1-se0).length :
wp = [ edge.verts[1] , edge.verts[0] ]
else :
wp = [ edge.verts[0] , edge.verts[1] ]

vp = [ pqutil.location_3d_to_region_2d(v.co) for v in wp ]

ret = Ret(WorldPos = [ v.co for v in wp] , ViewPos = vp , Center = (vp[0]+vp[1]) / 2 , Verts = wp )

return ret

0 comments on commit dfbf937

Please sign in to comment.