アニメーション作業をしている人を見ながら ふと
2次元カメラのアニメーションを確認するために
プレイブラスト書き出して、
AE起動して読み込ませて・・・・・
ん~めんどそう。
maya内である程度完結できんものかなぁ
カメラの機能を確認
この辺のアトリビュートですよねぇ
似たものがありますが、微妙に評価順とか機能とかで結果が違うんですよね。
例えばこの2つ。
一見すると同じように見えるんですが、filmTranslateは2D的な後処理なのに対して
filmOffsetはカメラの構造から調整している感じなのでパースに影響が出るようです。
filmOffset
シーンに対して、解像度ゲート(Resolution Gate)とフィルム ゲート(Film Gate)を垂直または水平にオフセットします。フィルム オフセット(Film Offset)の値を変更すると 2 次元トラックが生成されます(移動距離をインチ単位で指定します)。
filmTranslate
フィルムの移動(Film Translate)は 2D エフェクトで使用されます。この値は、人工的な 2D カメラ パンを表します。このフィールドに値を入力してください。
なので、2Dカメラワークよくある指示に対して
移動 -> filmTranslate
回転 -> filmRollValue
TU,TB -> postScale
で対応してみようかと思います。
構造
2Dカメラの動きをカメラを通して見ながら動かすのはなかなかやりづらそうなので、
2Dカメラワークの結果を見れるカメラ と 2Dカメラワーク全体?を見れるカメラに別けてみます。
あとは2Dカメラの動きを目視するための何か(メッシュかカーブ)を用意したいですね。
それはあまり邪魔になってほしくないので、nearClipPlane上にあると理想的かなと。
なのでこの時に作った機能が使えそうですね。
設置した板をとりあえず filmOffsetにつないで動かしてみるとー
めっちゃ動くので、倍率の調整が必要そうですね。
filmOffsetなので、filmGateを動かしてるかんじですかね。
であれば nearClipPlaneの距離とFocalLengthの比を使えば・・・・
filmOffsetはインチ単位なので、25.4で割らないといかんですね。
ピッタリ来ました。
postScale
この板のscaleX,Yは今ふさがっているので、一旦scaleZからpostScaleへつないでみます。
カメラ2から見るとこんな感じ。
postScaleをいじっても 板とカメラ2のresolutionGateが一致して欲しいですね。
scaleZをいじることで、板のscaleX,Yにもスケールがかかり カメラ2のpostScaleにも数値が入る
という流れで。
ただし postScale は 被写体にスケールがかかって見えるようにするので、相対的にはresolutionGateにはその逆数が入ってる感じですね。
なので
scaleX は resGateSizeH * scaleZ
scaleY は resGateSizeV * scaleZ
postScale は 1.0/scaleZ
となるようにつないでみました
ピッタリ来てますね。
filmRollValue
最後に回転を・・・・
これもとりあえずつないでみます。
これはー このままでよさそうですね。
まとめてスクリプト化
import maya.cmds as cmds
import maya.api.OpenMaya as om2
def getResGateSize(cameraName,resolutionW,resolutionH):
sourceCamDAG = om2.MGlobal.getSelectionListByName(cameraName).getDagPath(0)
sourceCamFn = om2.MFnCamera(sourceCamDAG)
if cmds.getAttr(cameraName + ".filmFit") == 1:
deviceAspectRatio = resolutionH / resolutionW
sourceResH = sourceCamFn.horizontalFilmAperture * deviceAspectRatio
sourceResW = sourceCamFn.horizontalFilmAperture
elif cmds.getAttr(cameraName + ".filmFit") == 2:
deviceAspectRatio = resolutionW / resolutionH
sourceResH = sourceCamFn.verticalFilmAperture
sourceResW = sourceCamFn.verticalFilmAperture * deviceAspectRatio
return sourceResW*25.4,sourceResH*25.4
def addCameraProxyPos(cameraName):
camProxy = cameraName + "_proxy"
if cmds.objExists(camProxy) == False:
cmds.createNode("transform",name = camProxy)
cmds.parentConstraint(cameraName,camProxy)
return camProxy
def addNearClipPos(cameraName):
camProxy = addCameraProxyPos(cameraName)
nearClipPoint = cameraName + "_nearClipPos"
if cmds.objExists(nearClipPoint) == False:
nearClipPoint = cmds.createNode("transform",name = nearClipPoint)
cmds.parent(nearClipPoint,camProxy,r = True)
rev = cmds.createNode("floatMath")
cmds.setAttr(rev + ".operation",2)
cmds.setAttr(rev + ".floatB",-1)
cmds.connectAttr(cameraName + ".nearClipPlane",rev+".floatA" )
cmds.connectAttr(rev + ".outFloat",nearClipPoint+".tz" )
return nearClipPoint
def connectClipCamera(destCamera,resGatePlane,lengthRatio):
cmds.connectAttr(resGatePlane + ".rz" , destCamera + ".filmRollValue")
invPostScale = cmds.createNode("floatMath")
cmds.setAttr(invPostScale+ ".floatA", 1.0)
cmds.connectAttr(resGatePlane + ".sz", invPostScale + ".floatB")
cmds.setAttr(invPostScale + ".operation",3)
cmds.connectAttr(invPostScale + ".outFloat",destCamera + ".postScale")
transYConv = cmds.createNode("floatMath")
cmds.setAttr(transYConv + ".operation",3)
cmds.connectAttr(resGatePlane + ".ty",transYConv + ".floatA")
cmds.connectAttr(lengthRatio + ".outFloat",transYConv + ".floatB")
transYConvUnit = cmds.createNode("floatMath")
cmds.setAttr(transYConvUnit + ".operation",3)
cmds.setAttr(transYConvUnit + ".floatB",25.4)
cmds.connectAttr(transYConv + ".outFloat",transYConvUnit + ".floatA")
cmds.connectAttr(transYConvUnit + ".outFloat",destCamera + ".verticalFilmOffset")
transXConv = cmds.createNode("floatMath")
cmds.setAttr(transXConv + ".operation",3)
cmds.connectAttr(resGatePlane + ".tx",transXConv + ".floatA")
cmds.connectAttr(lengthRatio + ".outFloat",transXConv + ".floatB")
transXConvUnit = cmds.createNode("floatMath")
cmds.setAttr(transXConvUnit + ".operation",3)
cmds.setAttr(transXConvUnit + ".floatB",25.4)
cmds.connectAttr(transXConv + ".outFloat",transXConvUnit + ".floatA")
cmds.connectAttr(transXConvUnit + ".outFloat",destCamera + ".horizontalFilmOffset")
cmds.setAttr(resGatePlane + ".tz",l = True)
cmds.setAttr(resGatePlane + ".rx",l = True)
cmds.setAttr(resGatePlane + ".ry",l = True)
cmds.setAttr(resGatePlane + ".sx",l = True)
cmds.setAttr(resGatePlane + ".sy",l = True)
cmds.setAttr(resGatePlane + ".template",1)
def addClipFrame(cameraName,defaultResolution):
resolutionW = defaultResolution[0]
resolutionH = defaultResolution[1]
sourceResW,sourceResH = getResGateSize(cameraName,resolutionW,resolutionH)
nearClipPoint = addNearClipPos(cameraName)
resGatePlane = cmds.polyPlane(axis = [0,0,1],sx = 1,sy = 1,ch =False,name = cameraName + "_resGateplane")[0]
cmds.parent(resGatePlane,nearClipPoint,r=True)
lengthRatio = cmds.createNode("floatMath")
cmds.connectAttr(cameraName + ".nearClipPlane",lengthRatio + ".floatA")
cmds.connectAttr(cameraName + ".focalLength",lengthRatio + ".floatB")
cmds.setAttr(lengthRatio + ".operation",3)
outRezGateW = cmds.createNode("floatMath")
outRezGateH = cmds.createNode("floatMath")
cmds.setAttr(outRezGateW + ".operation",2)
cmds.setAttr(outRezGateH + ".operation",2)
cmds.setAttr(outRezGateW + ".floatB",sourceResW)
cmds.setAttr(outRezGateH + ".floatB",sourceResH)
cmds.connectAttr(lengthRatio + ".outFloat",outRezGateW + ".floatA")
cmds.connectAttr(lengthRatio + ".outFloat",outRezGateH + ".floatA")
outScaleX = cmds.createNode("floatMath")
outScaleY = cmds.createNode("floatMath")
cmds.setAttr(outScaleX + ".operation",2)
cmds.setAttr(outScaleY + ".operation",2)
cmds.connectAttr(outRezGateW + ".outFloat",outScaleX + ".floatA")
cmds.connectAttr(outRezGateH + ".outFloat",outScaleY + ".floatA")
cmds.connectAttr(resGatePlane + ".sz",outScaleX + ".floatB")
cmds.connectAttr(resGatePlane + ".sz",outScaleY + ".floatB")
cmds.connectAttr(outScaleX + ".outFloat",resGatePlane + ".sx")
cmds.connectAttr(outScaleY + ".outFloat",resGatePlane + ".sy")
return resGatePlane,lengthRatio
def create2DCamera(sourceCamera,replace = True):
if cmds.listRelatives(sourceCamera,type = "camera") == None:
return
cameraName = sourceCamera.split(":")[-1]
destCamera = cameraName + "_2D"
parent = cmds.createNode("transform", name = destCamera + "_parent")
if cmds.objExists(destCamera):
if replace:
cmds.delete(destCamera)
cmds.delete(parent)
else:
return destCamera
if cmds.objExists(destCamera) == False:
nodes = cmds.duplicate(sourceCamera)
cmds.refresh()
cmds.rename(nodes[0], destCamera)
cmds.parentConstraint(sourceCamera,parent,mo =False)
cmds.parent(destCamera,parent,a=True)
# cmds.setAttr(parent + ".sx",-1.0)
connectAttrs = ["focalLength","nearClipPlane","farClipPlane"]
for attr in connectAttrs:
cmds.connectAttr(sourceCamera + "." + attr,destCamera + "." + attr)
return destCamera
select = cmds.ls(sl =True)
target = select[0]
destCamera = create2DCamera(target)
defaultResolution = [960,540]
resGatePlane,lengthRatio = addClipFrame(target,defaultResolution)
connectClipCamera(destCamera,resGatePlane,lengthRatio)
前回のスクリプトを改修してみました。
もう少し詰めるとなると、もとのカメラのpostscaleやらflimeoffsetやらにも対応できるといいかもですねぇ











