動くようになったので、メモがてら公開
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
0 件のコメント:
コメントを投稿