ラベル OriginalScript の投稿を表示しています。 すべての投稿を表示
ラベル OriginalScript の投稿を表示しています。 すべての投稿を表示

2014年2月10日月曜日

Softimage Original Script : SetHardEdge

2014 0213 追記



SIはポリゴンの周囲をハード化する物が無い。

rcToolsのポリゴンの境界を選択 > ハードエッジ
の手間が面倒だったので、スクリプト化した。


SetHardEdge


選択したエッジ、
選択したポリゴンの境界のエッジを
ハードエッジ化するスクリプト


使用方法

ポリゴンを選択、
または、エッジを選択して実行


Coad

#edgeHard
#
#選択したポリゴンの境界線。
#選択したエッジをハードエッジにするスクリプト
#
# 2014 0209 ハードエッジの調整
#

app = Application; log = app.LogMessage
dbug = False

def dlog(in_str):
 if dbug == True:
  log(in_str)


def markHardEdge(oObj,oEdgeIndecies):
 oIDs = oEdgeIndecies
 dlog(oObj)
 oGeo = oObj.ActivePrimitive.Geometry
 oEdges = oGeo.Segments
 for i in oIDs:
  edge = oEdges[i]
  if edge.IsHard:
   dlog("oEdgeID : " +str(edge.Index) + " : " + "is Hard")
   
 nSub = oGeo.CreateSubComponent("edge",oEdgeIndecies)
  
 app.ApplyOp("MarkHardEdgeVertex", nSub, 3, "siPersistentOperation", "", 0)


#ポリゴンの境界線のエッジを取得
def getPolyUnionEdges(oSel):
 oSub = oSel.SubComponent
 oObj = oSub.Parent3DObject
 oColl = oSub.ComponentCollection
 oGeo = oObj.ActivePrimitive.Geometry
 polys = oGeo.Facets
 nbPoly = polys.Count
 log(nbPoly)
 aPolyIDs = oColl.IndexArray
 bPolyIDs = []
 for i in range(nbPoly):
  flg = False
  for aID in aPolyIDs:
   if i == aID:
    flg = True
    continue
  if flg == False:
   bPolyIDs.append(i)
  
 #dlog(str(aPolyIDs))
 #dlog(str(bPolyIDs))
 
 aEdges = []
 bEdges = []
 
 for i in aPolyIDs:
  edges = polys[i].Edges
  for eID in edges:
   aEdges.append(eID.Index)
  
  
 for i in bPolyIDs:
  edges = polys[i].Edges
  for eID in edges:
   bEdges.append(eID.Index)
  
 aSet = set(aEdges)
 bSet = set(bEdges)
 
 return list(aSet & bSet)
 

#ポリゴンの境界線を調整
def polyEdgeMark(oSel):
 oSub = oSel.SubComponent
 oObj = oSub.Parent3DObject
 oEdges = getPolyUnionEdges(oSel)
 markHardEdge(oObj,oEdges)
 

def main():

 oSels = app.Selection
 for oSel in oSels:
  #seltype
  dlog(oSel.Type)
  if oSel.Type == "polySubComponent":
   polyEdgeMark(oSel)
  
  if oSel.Type == "edgeSubComponent":
   oObj = oSel.SubComponent.Parent3DObject
   oEdges = oSel.SubComponent.ComponentCollection
   markHardEdge(oObj,oEdges.IndexArray)

main()


メモ

ことの起こりは、ハードエッジ化したエッジの、
ハードエッジのプロパティの解除が目的だった

が、SDKを確認しても、
ハードエッジの状態は取得出来るが、
解除に関しては、その記載が無かった。

WEBを調べると、ハードエッジの消去は、
そのエッジを選択、MarkHardEdgeで、
ハードエッジ化をもう一度行い
そのプロパティのチェックを外す。
という物だった orz


ハードエッジ自体は、
その性質上(オペレータスタック)
オペレーター駆動で行っているらしい。

というわけで、
解除する為にはオペレーターコマンドで
作業しないとダメっぽい。

※こんなやつ
Application.ApplyOp("MarkHardEdgeVertex", nSub, 3, "siPersistentOperation", "", 0)


ハードエッジ作業が今後も増えるようだったら、
・ハードエッジの追加
・ハードエッジの削除
・作業途中で出来た、クラスターの削除
・フリーズかを含めたツールがひつようかも。


また、ハードエッジの仕様が気になるところ。
外部ツールは頂点を増やして対応してるのか、
UserNormalで対応してるのかが、謎ね。


既知のバグ

・選択状態が解除される。
・複数のオブジェクトに対応してない(選択状態がはずれる?)


追記 2014 0213

mayaraさんが、ハードエッジを作る、削除するプラグインを
作ってた〜(ymt3Dさんに教えてもらいました

mHard Edge Marker

2014年2月4日火曜日

Softimage : Original Script : VVNormal

3年ぶりにスクリプトを修正。
動くようになったので、メモがてら公開

VVNormal : 効果


選択したコンポーネントを正面に向けるようにカメラを移動します。


Sorce


# VVNormal
#
# v0.1 2014 02 04 とりあえず、UserCameraでもOK
# v0.0 2011 06 04 Cameraには対応するもUserCameraだとNG

SIZE_RETIO = 0.4
BASE_CAMLENGTH = 50

from win32com.client import constants as c
import math
app = Application
log = app.Logmessage
debug = True

#ログの表示を消す
cmdLog = app.Dictionary.GetObject( "preferences.scripting" )
cmdLog.cmdlog.value = False


def dlog(in_value):
 if debug:
  log(in_value)


#ポリゴンのノーマルの平均を算出しノーマライズ
def getPolyAverageNormal(oColl, m3): 
 NA = oColl.NormalArray
 Nx = Ny = Nz = 0
 for i in range(len(NA[0])):
  Nx += NA[0][i]
  Ny += NA[1][i]
  Nz += NA[2][i]
 nV = XSIMath.CreateVector3(Nx,Ny,Nz)
 if nV.Length() <= 0.01:
  nV.Set(0,0,1)
 nV.NormalizeInPlace()
 nV.MulByMatrix3InPlace(m3)
 return nV


#Cameraの注視点を取得
def getCamInterestPos(oColl, m): 
 #CameraのInterestを選択したポリゴンのBBoxの中央に
 pnts = oColl.NeighborVertices(1)
 xp = []
 yp = []
 zp = []
 for pnt in pnts:
  pos = pnt.Position
  pos.MulByMatrix4InPlace(m)
  xp.append(pos.X)
  yp.append(pos.Y)
  zp.append(pos.Z)
 xplen = abs( max(xp)-min(xp) )
 yplen = abs( max(yp)-min(yp) )
 zplen = abs( max(zp)-min(zp) )
 inPos = XSIMath.CreateVector3(xplen * 0.5 + min(xp) ,yplen * 0.5 + min(yp) , zplen * 0.5 + min(zp) )
 return inPos

 
def main():
 dlog("-----main-----")
 userCam = True

 #カメラの取得
 cam = getActiveCamera()
 dlog("CamName : " + str(cam.name))
 cons = cam.Kinematics.Constraints
 log(cons.count)
 for con in cons:
  if con.Type == 'dircns':
   cameraIns = con.Constraining(0)
   userCam = False
   break;
 if app.Selection != None:
  if app.Selection(0).Type != "polySubComponent":
   dlog("PolyMode")
  elif app.Selection(0).Type != "edgeSubComponent":
   dlog("edge")
  elif app.Selection(0).Type != "pntSubComponent":
   dlog("pnt")
  else :
   return
 else:
  return

 oSel = app.Selection(0)
 oSub = oSel.SubComponent
 oObj = oSub.Parent3DObject
 oColl = oSub.ComponentCollection
 m = XSIMath.CreateMatrix4()
 m3 = XSIMath.CreateMatrix3()
 oObj.Kinematics.Global.Transform.GetMatrix4(m)
 oObj.Kinematics.Global.Transform.Rotation.GetMatrix3(m3)
 im = XSIMath.CreateMatrix4()
 im.Invert(m)
 
 #注視点を取得
 inPos = getCamInterestPos(oColl, m)
 
 #Normalを取得
 nV = getPolyAverageNormal(oColl,m3)
 
 oTrans = XSIMath.CreateTransform()
 
 #UserCamでなければ
 if userCam == False:
  cameraIns.Kinematics.Global.Transform = oTrans
  oTrans.SetTranslation(inPos)
 
 #ビューマトリクスから、Xの長さYの長さを算出
 vm = createViewMatrix(nV,inPos)
 m.MulInPlace(vm)
 pnts = oColl.NeighborVertices(1)
 xp = []
 yp = []
 for pnt in pnts:
  pos = pnt.Position
  pos.MulByMatrix4InPlace(m)
  xp.append(pos.X)
  yp.append(pos.Y)
 xLength = abs( max(xp)-min(xp) )
 yLength = abs( max(yp)-min(yp) )

 #カメラの画角より、最適な距離を算出。 inX inY in割合
 camLength = BASE_CAMLENGTH
 if xLength > 0.01 and yLength > 0.01:
  camLength = getCameraLength(cam, xLength, yLength, SIZE_RETIO)
 
 #カメラのポジションに適用
 camPos = XSIMath.CreateVector3()
 nV.ScaleInPlace( camLength )
 camPos.Add(inPos,nV)
 
 if userCam :
  dlog("UserCamera Mode")
  
  #距離の指定
  cam.interestdist.Value = camLength

  oTrans.SetTranslation(camPos)
  oRot = XSIMath.CreateRotation()
  vm.InvertInPlace()
  oTrans.SetMatrix4(vm)
  app.SetValue(cam.FullName + ".kine.global.rotx", oTrans.RotX, "")
  app.SetValue(cam.FullName + ".kine.global.roty", oTrans.RotY, "")
  app.SetValue(cam.FullName + ".kine.global.rotz", oTrans.RotZ, "")
  app.SetValue(cam.FullName + ".kine.global.posx", camPos.X, "")
  app.SetValue(cam.FullName + ".kine.global.posy", camPos.Y, "")
  app.SetValue(cam.FullName + ".kine.global.posz", camPos.Z, "")

 else :
  dlog("CameraMode : Moved")
  oTrans.SetTranslation(camPos)
  cam.Kinematics.Global.Transform = oTrans
  
 dlog("-----finish-----")
 
 return
 
#アクティブなカメラを取得
def getActiveCamera():
 oL = app.DeskTop.ActiveLayOut
 
 #デフォルトビューのチェック
 oV = oL.views("vm")
 abcd = oV.GetAttributeValue("viewportundermouse")
 if oV.Views(abcd).Type == 'Viewer':
  ActiveView = oV.GetAttributeValue("activecamera:" + abcd)
  log(ActiveView)
  if (ActiveView =="User") or (ActiveView =="Top") or (ActiveView =="Front") or (ActiveView =="Right"):
   cam = app.GetValue("Views.View" + abcd + "." + ActiveView + "Camera")
  else:
   cam = app.GetValue(ActiveView)

 #ビューマネージャーにある、オブジェクトビューのチェック 
 num = 0
 for i in range(4):
  if oV.Views(i).Type == 'Object View':
   num += 1
 log("ObjectViewCount : " + str(num))  
 if oV.Views(abcd).Type == 'Object View':
  ActiveView = oV.Views(abcd).GetAttributeValue("Camera")
  ViewName = oV.Views(abcd).FullName
  log(ActiveView)
  log(ViewName)
  if ActiveView == "default":
   cam = app.GetValue("Views.View" + str(num) + ".UserCamera")
  else:
   cam = app.GetValue(ActiveView)
   
 #フローティングのオブジェクトビューの対応 
 for x in oL.Views:
  if x.Type == 'Object View':
   log(x)
   ActiveView = x.GetAttributeValue("Camera")
   if ActiveView == "default":
    cam = app.GetValue("Views.View" + str(num) + ".UserCamera")
   else:
    cam = app.GetValue(ActiveView)
 return cam
 
#画角と長さより焦点からのカメラの距離を算出
def getCameraLength(inCamera, inX, inY, inPercnet):
 cam = inCamera
 x = inX
 y = inY
 aspect = cam.aspect.Value
 fov = cam.fov.Value
 fovtype = cam.fovtype.Value #if 1:Horizontal
 
 fov = XSIMath.DegreesToRadians(fov)
  
 #Xでの算出
 xCos =  ( 0.5 * x ) / math.tan( 0.5 * fov ) 
 #Yでの算出
 yCos = ( 0.5 * y ) / math.tan( 0.5 * fov ) * aspect
 
 if xCos > yCos:
  length = xCos
 else:
  length = yCos
  
 length = length / inPercnet
 return length

#ビューマトリックスの作成 
def createViewMatrix(inNormalVect,inInsPos):
 nv = inNormalVect
 m = XSIMath.CreateMatrix4()
 upv = XSIMath.CreateVector3(0,1,0)
 if nv.Dot(upv) > 0.9:
  m.Set(1,0,0,0,   0,0,-1,0, 0,-1,0,0, inInsPos.X, inInsPos.Y , inInsPos.Z , 1)
  m.InvertInPlace()
  return m
 u = XSIMath.CreateVector3()
 v = XSIMath.CreateVector3()
 w = XSIMath.CreateVector3()

 w.Scale(-1 , nv)
 w.NormalizeInPlace()
 
 u.Cross(upv,w)
 u.NormalizeInPlace()
 
 v.Cross(u,w)
 v.NormalizeInPlace()
 
 m.Set(
 u.X , u.Y , u.Z , 0 ,
 v.X , v.Y , v.Z , 0 ,
 w.X , w.Y , w.Z , 0 ,
 inInsPos.X, inInsPos.Y , inInsPos.Z , 1
 )
 m.InvertInPlace()
 return m
 
main()


備考

Softimageは、自分で制作するカメラと、
シーンにあらかじめ配置してあるビュー用のカメラがあります。

ビュー用のカメラは、注視点ようのNullがなかったので、
場合分けが出来てなかったですが。
改良して使えるようにしてみました。

付け焼き刃的に拡張したので、
中身はUNKです orz

2011年11月8日火曜日

Softimage Script : Extract Plus

オブジェクトをエリアごとに分割する必要があって、
ポリゴンを分けてたんだけど、
標準だといろいろメンドクサイ

通常のExtract

・原点はワールドに移動し
・新しいオブジェクトはScene_Rootの子に

オブジェクト数が少ないうちはいいが
新規のオブジェクトの位置が遠い orz


Extract Plust

・オブジェクトの親を同じにする
・名前を同じにする
・SRTを同じにする