import copy import math #うずまきツール #選択している頂点だけを指定の位置を中心に回転します #中心から離れるほど回転量が落ちます #動作条件 #選択形状がポリゴンメッシュ #編集モードに入っている #頂点選択モード #頂点が二つ以上選択されている(x、y、z座標の値が異なる) #上位パートに変換がかかっていない事 #shade1301に対応 #設定項目 #回転の中心 「選択頂点を囲むバウンディングボックスの中心」「弟階層の円か球の中心」 #回転軸 「x軸」「y軸」「z軸」 #角度(-360〜360) #始点 「中心から回転」「最外周から回転」(今のところ「中心から回転のみ」) #減衰タイプ 0が直線 1が二乗 2が1/二乗(今のところ0のみ) def return_henkan_pos(pos,mat): #posをmatで変換した座標(タプル)を返す tempx=pos[0] tempy=pos[1] tempz=pos[2] x1=mat[0][0]*tempx+mat[1][0]*tempy+mat[2][0]*tempz+mat[3][0]*1 y1=mat[0][1]*tempx+mat[1][1]*tempy+mat[2][1]*tempz+mat[3][1]*1 z1=mat[0][2]*tempx+mat[1][2]*tempy+mat[2][2]*tempz+mat[3][2]*1 return [x1,y1,z1] def return_kaiten(pos,cpos,kakudo2,ziku): #posをcposを中心にziku(0x軸、1y軸、2z軸)まわりにkakudoだけ回転させて返す kakudo=(2*math.pi*kakudo2)/360 tempos5=[pos[0]-cpos[0],pos[1]-cpos[1],pos[2]-cpos[2]] newpos=[tempos5[0],tempos5[1],tempos5[2]] if ziku==0: newpos[1]=tempos5[1]*math.cos(kakudo)-tempos5[2]*math.sin(kakudo) newpos[2]=tempos5[1]*math.sin(kakudo)+tempos5[2]*math.cos(kakudo) if ziku==1: newpos[2]=tempos5[2]*math.cos(kakudo)-tempos5[0]*math.sin(kakudo) newpos[0]=tempos5[2]*math.sin(kakudo)+tempos5[0]*math.cos(kakudo) if ziku==2: newpos[0]=tempos5[0]*math.cos(kakudo)-tempos5[1]*math.sin(kakudo) newpos[1]=tempos5[0]*math.sin(kakudo)+tempos5[1]*math.cos(kakudo) newpos=[newpos[0]+cpos[0],newpos[1]+cpos[1],newpos[2]+cpos[2]] return newpos dousasuru=0 xscene=xshade.scene() ashape=xshade.scene().active_shape() if ashape.type==7 and xscene.is_modify_mode==True: if xscene.selection_mode==2: aplist=[]#選択頂点リスト for i in range(ashape.total_number_of_control_points): if ashape.vertex(i).active==True: aplist.append(i) if len(aplist)>1:dousasuru=1 if dousasuru>0: #上位パートに変換がかかっているなら動作しない if xshade.scene().active_shape().local_to_world_matrix!=((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0)): dousasuru=0 dialog=xshade.create_dialog() dialog.append_push_button('上位パートに変換がかかっているため') dialog.append_push_button('スクリプトが実行できません') dialog.ask('エラー') if dousasuru==1: #ここに初期値 renzoku=1 ctype=0 #回転の中心タイプ ziku=0#回転軸 0がx軸、1がy軸、2がz軸 angle=90 #角度 startp=0 #始点 0が中心から回転  1が最外周から回転 type=0 #減衰 0の場合は直線 1の場合は二乗 2の場合は1/二乗 # dfctype=ctype # dfspos=spos # dfziku=ziku # dfmuki=muki # dfvtype=vtype # dfrval=rval # dfkaiten=kaiten # dfnezip=nezip # dfissyo=issyo while(renzoku==1): #ダイアログ表示 dialog=xshade.create_dialog() # dialog.append_default_button() dialog.begin_group('回転の中心') idx1=dialog.append_radio_button('/選択頂点を囲むバウンディングボックスの中心/弟階層にある円か球の中心') dialog.end_group() dialog.begin_group('回転軸(直行軸)') idx3=dialog.append_radio_button('/x軸と並行/y軸と並行/z軸と並行') dialog.end_group() idx2=dialog.append_float('角度') # dialog.begin_group('始点') # idx7=dialog.append_radio_button('/中心からねじる/最外周からねじる') # dialog.end_group() # dialog.begin_group('減衰タイプ') # idx8=dialog.append_radio_button('/直線/二乗/二乗分の一') # dialog.end_group() dialog.set_value(idx1,ctype) dialog.set_value(idx2,angle) dialog.set_value(idx3,ziku) # dialog.set_value(idx7,startp) # dialog.set_value(idx8,type) # dialog.set_value(idx1,ctype) # dialog.set_value(idx2,spos) # dialog.set_value(idx3,ziku) # dialog.set_value(idx4,muki) # dialog.set_value(idx5,vtype) # dialog.set_value(idx6,rval) # dialog.set_value(idx7,kaiten) # dialog.set_value(idx8,nezip) # dialog.set_value(idx9,issyo) xshade.idle(120) kekka=dialog.ask('うずまきツール') if kekka==False:renzoku=0 else: ctype=dialog.get_value(idx1) angle=dialog.get_value(idx2) if angle<-360:angle=-360 if angle>360:angle=360 ziku=dialog.get_value(idx3) # startp=dialog.get_value(idx7) # type=dialog.get_value(idx8) #元の形状をクリップボードにコピー ashape.copy() xscene.enter_modify_mode() #弟階層に円か球があるか? if ctype==1: if ashape.has_bro==True: if ashape.bro.type==5 or ashape.bro.type==6: cpos=ashape.bro.center else:ctype=0 else:ctype=0 #バウンディングボックス計算 if ctype==0: tp1=ashape.vertex(aplist[0]).position minx=tp1[0] maxx=tp1[0] miny=tp1[1] maxy=tp1[1] minz=tp1[2] maxz=tp1[2] for i in aplist: tp2=ashape.vertex(i).position if tp2[0]maxx:maxx=tp2[0] if tp2[1]maxy:maxy=tp2[1] if tp2[2]maxz:maxz=tp2[2] cpos=[(minx+maxx)/2,(miny+maxy)/2,(minz+maxz)/2] #中心から一番外にある選択頂点との距離を求める maxr=0 for i in aplist: tp3=ashape.vertex(i).position if ziku==0: r2r=(cpos[1]-tp3[1])**2+(cpos[2]-tp3[2])**2 if ziku==1: r2r=(cpos[0]-tp3[0])**2+(cpos[2]-tp3[2])**2 if ziku==2: r2r=(cpos[0]-tp3[0])**2+(cpos[1]-tp3[1])**2 if r2r>(maxr**2):maxr=pow(r2r,0.5) #それぞれの頂点を回転 # print maxr for i in aplist: tp4=ashape.vertex(i).position # r2r=(cpos[0]-tp4[0])**2+(cpos[1]-tp4[1])**2+(cpos[2]-tp4[2])**2 if ziku==0: r2r=(cpos[1]-tp4[1])**2+(cpos[2]-tp4[2])**2 if ziku==1: r2r=(cpos[0]-tp4[0])**2+(cpos[2]-tp4[2])**2 if ziku==2: r2r=(cpos[0]-tp4[0])**2+(cpos[1]-tp4[1])**2 tempr=pow(r2r,0.5) # print tempr if maxr!=0: wari=tempr/maxr else:wari=0 if startp==0:wari=1-wari if type==0: newangle=angle*wari if type==1: newangle=angle*(wari**2) if type==2: if wari==0: newangle=angle else: newangle=angle*((1/wari)**2) newpos=return_kaiten(tp4,cpos,newangle,ziku) ashape.vertex(i).position=newpos #再選択状態に # for i in aplist: # ashape.vertex(i).active=True # xscene.allow_update() #元に戻すか聞く dialog=xshade.create_dialog() idx3=dialog.append_push_button('処理を確定しますか?') xshade.scene().enter_modify_mode() xshade.idle(120) kekka=dialog.ask('うずまきツール') if kekka==True:renzoku=0 if kekka==False: idou1=0 if xshade.scene().active_shape().has_sis==True: idou1=1 xshade.scene().paste() xshade.scene().select_sister(1) xshade.scene().clear() if idou1==1: xshade.scene().select_brother() xshade.scene().enter_modify_mode() ashape=xshade.scene().active_shape() for i in aplist: ashape.vertex(i).active=True