import copy import math #ガイドラインスケーリング #選択している頂点だけを弟階層のガイドラインにあわせてスケーリングします #上位パートに変換がかかっていると使用できないように変更(2010.03.03) #動作条件 #選択形状がポリゴンメッシュ #編集モードに入っている #頂点選択モード #頂点が二つ以上選択されている(x、y、z座標の値が異なる) #弟形状に「gscaling」というパートとその中にガイドラインが存在する #ローカル座標モードや、上位パートに変換がかかっていると結果が不正になります #設定項目 #スケーリングの中心 「カーソルのクリック位置(最後にクリックした位置)」「選択頂点の平均座標」 #  「選択頂点を囲むバウンディングボックスの中心」「指定位置」 #指定位置の場合の座標(vec3) #直行軸 「x軸」「y軸」「z軸」・・・ガイドラインの名前の頭につけておく #ガイドラインの分割数・・・・分割数が大きいほど精度が高くなる #「x座標固定」 #「y座標固定」 #「z座標固定」 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: minx=ashape.vertex(aplist[0]).position[0] maxx=ashape.vertex(aplist[0]).position[0] miny=ashape.vertex(aplist[0]).position[1] maxy=ashape.vertex(aplist[0]).position[1] minz=ashape.vertex(aplist[0]).position[2] maxz=ashape.vertex(aplist[0]).position[2] minxp=aplist[0] minyp=aplist[0] minzp=aplist[0] maxxp=aplist[0] maxyp=aplist[0] maxzp=aplist[0] for i in aplist: tpos=ashape.vertex(i).position if tpos[0]maxx: maxxp=i maxx=tpos[0] if tpos[1]>maxy: maxyp=i maxy=tpos[1] if tpos[2]>maxz: maxzp=i maxz=tpos[2] #選択形状がポリゴンメッシュで弟階層にガイドラインが存在しない場合はまず作成して終了 #ある場合も「変形を行う」と「ガイドラインの新規作成」で選択 #軸をたずねる(ガイドラインの頭に軸x、y、zをつける) #ガイドラインはレンダリング対象外 if dousasuru==1: gkesu=0 if ashape.has_bro==True: if ashape.bro.name=='gscaling': dialog=xshade.create_dialog() idx=dialog.append_radio_button('/変形を行う/ガイドラインの新規作成') dialog.set_value(idx,0) kekka7=dialog.ask('ガイドラインスケーリング') if kekka7==False:dousasuru=0 else: tmode=dialog.get_value(idx) if tmode==1: dousasuru=3 gkesu=1 else: dousasuru=3 else: dousasuru=3 if dousasuru==3: #ガイドラインの作成 dialog=xshade.create_dialog() dialog.append_push_button('ガイドラインスケーリング用') idx=dialog.append_radio_button('ガイドライン/x軸と平行/y軸と平行/z軸と平行') dialog.set_value(idx,0) kekka8=dialog.ask('ガイドラインの作成') if kekka8==True: gmode=dialog.get_value(idx) #ガイドラインの新規作成の場合は前のガイドラインを非表示に if gkesu==1: xscene.select_brother(1) xscene.hide_active() xscene.select_sister() if gmode==0: gmin=minx gmax=maxx #z軸方向の厚みを図る atumi=maxz-minz if atumi==0: kizyun=(maxx-minx)/4 # if (maxx-minx)>(maxy-miny): # kizyun=(maxx-minx)/4 # else: # kizyun=(maxy-miny)/4 else: kizyun=atumi/2 stpos=maxz+kizyun*0.1 endpos=stpos+kizyun #パートの作成 xshade.scene().begin_creating() xshade.scene().create_part('gscaling') xshade.scene().end_creating() #線形状の作成 xshade.scene().begin_creating() xshade.scene().create_line('xガイドライン',[[gmin,0,endpos],[gmax,0,endpos]],False) xshade.scene().end_creating() #自由曲面の作成 xshade.scene().begin_creating() xshade.scene().create_surface_part('~基準線') xshade.scene().end_creating() xshade.scene().begin_creating() xshade.scene().create_line('開始ライン',[[gmin,0,stpos],[gmax,0,stpos]],False) xshade.scene().create_line('一倍ライン',[[gmin,0,endpos],[gmax,0,endpos]],False) xshade.scene().end_creating() xscene.select_parent() xshade.scene().active_shape().rendering=0 xscene.select_sister() if gmode==1: gmin=miny gmax=maxy #z軸方向の厚みを図る atumi=maxx-minx if atumi==0: kizyun=(maxy-miny)/4 else: kizyun=atumi/2 stpos=maxx+kizyun*0.1 endpos=stpos+kizyun #パートの作成 xshade.scene().begin_creating() xshade.scene().create_part('gscaling') xshade.scene().end_creating() #線形状の作成 xshade.scene().begin_creating() xshade.scene().create_line('yガイドライン',[[endpos,gmin,0],[endpos,gmax,0]],False) xshade.scene().end_creating() #自由曲面の作成 xshade.scene().begin_creating() xshade.scene().create_surface_part('~基準線') xshade.scene().end_creating() xshade.scene().begin_creating() xshade.scene().create_line('開始ライン',[[stpos,gmin,0],[stpos,gmax,0]],False) xshade.scene().create_line('一倍ライン',[[endpos,gmin,0],[endpos,gmax,0]],False) xshade.scene().end_creating() xscene.select_parent() xshade.scene().active_shape().rendering=0 xscene.select_sister() if gmode==2: gmin=minz gmax=maxz #z軸方向の厚みを図る atumi=maxy-miny if atumi==0: kizyun=(maxz-minz)/4 else: kizyun=atumi/2 stpos=maxy+kizyun*0.1 endpos=stpos+kizyun xshade.scene().begin_creating() xshade.scene().create_part('gscaling') xshade.scene().end_creating() #線形状の作成 xshade.scene().begin_creating() xshade.scene().create_line('zガイドライン',[[0,endpos,gmin],[0,endpos,gmax]],False) xshade.scene().end_creating() #自由曲面の作成 xshade.scene().begin_creating() xshade.scene().create_surface_part('~基準線') xshade.scene().end_creating() xshade.scene().begin_creating() xshade.scene().create_line('開始ライン',[[0,stpos,gmin],[0,stpos,gmax]],False) xshade.scene().create_line('一倍ライン',[[0,endpos,gmin],[0,endpos,gmax]],False) xshade.scene().end_creating() xscene.select_parent() xshade.scene().active_shape().rendering=0 xscene.select_sister() if dousasuru==1: #変形を行う ziku=0#回転軸 0がx軸、1がy軸、2がz軸 #ガイドライン(線形状)のコントロールポイント数を計測と軸の確認 xscene.select_brother() xscene.select_child() bunkatu=xshade.scene().active_shape().total_number_of_control_points-1 if xshade.scene().active_shape().name=='xガイドライン':ziku=0 if xshade.scene().active_shape().name=='yガイドライン':ziku=1 if xshade.scene().active_shape().name=='zガイドライン':ziku=2 xscene.select_parent() xscene.select_sister() #基準の距離 if ziku==0: if maxz==minz:kizyund=(maxx-minx)/4 else:kizyund=(maxz-minz)/2 stpos=maxz+kizyund*0.1 if ziku==1: if maxx==minx:kizyund=(maxy-miny)/4 else:kizyund=(maxx-minx)/2 stpos=maxx+kizyund*0.1 if ziku==2: if maxy==miny:kizyund=(maxz-minz)/4 else:kizyund=(maxy-miny)/2 stpos=maxy+kizyund*0.1 #ここに初期値 renzoku=1 ctype=0 #回転の中心タイプ spos=[0,0,0]#回転の中心が「指定位置」の場合の中心座標 xkotei=0#x座標固定 0で固定しない 1で固定する ykotei=0#y座標固定 0で固定しない 1で固定する zkotei=0#z座標固定 0で固定しない 1で固定する bunkatu=1000 dfctype=ctype dfspos=spos dfxkotei=xkotei dfykotei=ykotei dfzkotei=zkotei dfbunkatu=bunkatu while(renzoku==1): #ダイアログ表示 dialog=xshade.create_dialog_with_uuid('0x51900212') dialog.append_default_button() dialog.begin_group('スケーリングの中心') idx1=dialog.append_radio_button('/カーソルのクリック位置/選択頂点の平均座標/選択頂点を囲むバウンディングボックスの中心/指定位置') dialog.end_group() dialog.begin_group('指定位置の場合') idx2=dialog.append_vec3() dialog.end_group() idx3=dialog.append_int('ガイドラインの分割数(デフォルト:'+str(dfbunkatu)+')') idx4=dialog.append_bool('x座標固定') idx5=dialog.append_bool('y座標固定') idx6=dialog.append_bool('z座標固定') dialog.set_default_value(idx1,dfctype) dialog.set_default_value(idx2,dfspos) dialog.set_default_value(idx3,dfbunkatu) dialog.set_default_value(idx4,dfxkotei) dialog.set_default_value(idx5,dfykotei) dialog.set_default_value(idx6,dfzkotei) kekka=dialog.ask('ガイドラインスケーリング') if kekka==False:renzoku=0 else: ctype=dialog.get_value(idx1) spos=dialog.get_value(idx2) bunkatu=dialog.get_value(idx3) if bunkatu<1:bunkatu=1 xkotei=dialog.get_value(idx4) ykotei=dialog.get_value(idx5) zkotei=dialog.get_value(idx6) #中心点の割り出し if ctype==0: cpos=xscene.cursor_position mat4=ashape.world_to_local_matrix cpos=return_henkan_pos(cpos,mat4) if ctype==1: sumpos=[0,0,0] for i in aplist: tempos=ashape.vertex(i).position sumpos[0]+=tempos[0] sumpos[1]+=tempos[1] sumpos[2]+=tempos[2] cpos=[sumpos[0]/len(aplist),sumpos[1]/len(aplist),sumpos[2]/len(aplist)] if ctype==2: cpos=[(minx+maxx)/2,(miny+maxy)/2,(minz+maxz)/2] if ctype==3:cpos=spos #基準点(開始線の一つ目のコントロールポイントの座標を取得) xscene.select_brother() xscene.select_child() xscene.select_brother() xscene.select_child() ttpos=xshade.scene().active_shape().control_point(0).position kizyunpos=[ttpos[0],ttpos[1],ttpos[2]] xscene.select_parent() xscene.select_sister() #ガイドライン(のコピー)を自由曲面パートに入れて複製つくってポリゴンメッシュに変換して頂点情報を取得 pposlist=[] xscene.copy() xscene.begin_creating() xscene.create_surface_part() xscene.end_creating() xscene.paste() xscene.paste() if ziku==0: xscene.move_object([0,0,0],None,None,[0,0,50]) if ziku==1: xscene.move_object([0,0,0],None,None,[50,0,0]) if ziku==2: xscene.move_object([0,0,0],None,None,[0,50,0]) xscene.select_parent() xscene.active_shape().convert_to_polygon_mesh_with_divisions(1,bunkatu) for i in range(bunkatu+1): tposp=xscene.active_shape().vertex(i).position pposlist.append([tposp[0],tposp[1],tposp[2]]) xscene.clear() xscene.select_parent() xscene.select_sister() #if dousasuru==4: # if dousasuru==4: # if dousasuru==4: #選択を全て解除 # for i in aplist: # ashape.vertex(i).active=False # xscene.inhibit_update() #元の形状をクリップボードにコピー ashape.copy() xscene.enter_modify_mode() #個々の頂点をスケーリング for i in aplist: # ashape.vertex(i).active=True tpos=ashape.vertex(i).position motopos=[tpos[0],tpos[1],tpos[2]] if ziku==0: dist2=abs(pposlist[0][0]-tpos[0]) nearpos=pposlist[0] for gg in pposlist: tdist=abs(gg[0]-tpos[0]) if tdist>dist2:break else: dist2=tdist nearpos=gg #倍率を求める tendist=nearpos[2]-stpos scale2=tendist/kizyund if scale2<0:scale2=0 # print scale2 #頂点の移動 ttpos=[tpos[0]-cpos[0],tpos[1]-cpos[1],tpos[2]-cpos[2]] ttpos=[ttpos[0],scale2*ttpos[1],scale2*ttpos[2]] ttpos=[ttpos[0]+cpos[0],ttpos[1]+cpos[1],ttpos[2]+cpos[2]] #座標固定の場合は if xkotei==1: ttpos[0]=motopos[0] if ykotei==1: ttpos[1]=motopos[1] if zkotei==1: ttpos[2]=motopos[2] ashape.vertex(i).position=ttpos if ziku==1: dist2=abs(pposlist[0][1]-tpos[1]) nearpos=pposlist[0] for gg in pposlist: tdist=abs(gg[1]-tpos[1]) if tdist>dist2:break else: dist2=tdist nearpos=gg #倍率を求める tendist=nearpos[0]-stpos scale2=tendist/kizyund if scale2<0:scale2=0 #頂点の移動 ttpos=[tpos[0]-cpos[0],tpos[1]-cpos[1],tpos[2]-cpos[2]] ttpos=[scale2*ttpos[0],ttpos[1],scale2*ttpos[2]] ttpos=[ttpos[0]+cpos[0],ttpos[1]+cpos[1],ttpos[2]+cpos[2]] #座標固定の場合は if xkotei==1: ttpos[0]=motopos[0] if ykotei==1: ttpos[1]=motopos[1] if zkotei==1: ttpos[2]=motopos[2] ashape.vertex(i).position=ttpos if ziku==2: dist2=abs(pposlist[0][2]-tpos[2]) nearpos=pposlist[0] for gg in pposlist: tdist=abs(gg[2]-tpos[2]) if tdist>dist2:break else: dist2=tdist nearpos=gg #倍率を求める tendist=nearpos[1]-stpos scale2=tendist/kizyund if scale2<0:scale2=0 #頂点の移動 ttpos=[tpos[0]-cpos[0],tpos[1]-cpos[1],tpos[2]-cpos[2]] ttpos=[scale2*ttpos[0],scale2*ttpos[1],ttpos[2]] ttpos=[ttpos[0]+cpos[0],ttpos[1]+cpos[1],ttpos[2]+cpos[2]] #座標固定の場合は if xkotei==1: ttpos[0]=motopos[0] if ykotei==1: ttpos[1]=motopos[1] if zkotei==1: ttpos[2]=motopos[2] ashape.vertex(i).position=ttpos #頂点のマージ # ashape.cleanup_redundant_vertices() #選択箇所の再選択 xshade.scene().enter_modify_mode() for i in aplist: ashape.vertex(i).active=True #元に戻すか聞く dialog=xshade.create_dialog() idx3=dialog.append_push_button('処理を確定しますか?') 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