前回に引き続きカメラネタをこすっていこうかと。
2Dカメラワークを確認しやすくなったんですが、例えばこんな風にカメラワークを決めた場合
最終的なレンダリング解像度はいくつになるでしょうか?
レギュラーサイズを 960x540 だとすると、
青線の一番小さい時が 960x540になる必要があります。
必要最低限のレンダリング範囲を求めるなら 赤線の解像度が欲しいですね

まー力技ではありますが、
フレーミング用の板の4点の 開始・終了時座標をとって、バウンディングボックスサイズを算出し
現在のresolutionGateサイズとの比をだします。
その比を基に解像度を求められないかなぁ~
nearClipPlane 上での座標を求める
matrixやらなんやらをコネコネして、nearClipPlane上での座標を求めてみます。
とりあえず左上のvtxの座標を・・・
import maya.cmds as cmds
import maya.api.OpenMaya as om2
parentSpace = "persp1_nearClipPos"
matrixP = om2.MMatrix(cmds.getAttr(parentSpace+".worldInverseMatrix[0]"))
pointA = cmds.xform("persp1_resGateplane.vtx[2]",ws =True,t=True,q=True)
vectorA = om2.MVector(pointA)
matrixA = om2.MTransformationMatrix(om2.MMatrix.kIdentity).setTranslation(vectorA,om2.MSpace.kWorld).asMatrix()
localPositionA = om2.MTransformationMatrix(matrixA*matrixP).translation(om2.MSpace.kWorld)
print(localPositionA)
# (-0.0458055, 0.0237331, -1.77636e-15)
locatorを実際に配置してみると、合ってそうですね。
まぁこれをやっていけば良いのですがー
1つ問題が。
この板はアニメーションをします。
アニメーションするので、各フレーム毎の座標を確認する必要があります。
cmds.getAttr() だとフレーム指定で値をとれますが、vtxの位置はcmds.getAttr()では取れません。
cmds.xform()でvtxの座標をとれますが、 cmds.xform()だとフレーム指定でき・・・なかったよなぁ
となると、プレイブラストの様に1fずつ送って確認するしかないかなぁ と
ただ、重いシーンだとそれやりたくないんですよねぇ 重いから。
で、ボケーっと空を見上げてたら流れ星が見えまして、
あ。もーしょんとれいる
と。(嘘です)
なのでvtx毎にmotionTrailを設置して、そこから全フレーム分の位置情報を引っ張り出してやろうと思います。
import maya.cmds as cmds
import maya.api.OpenMaya as om2
def getPosition(target):
nodeType = cmds.nodeType(target)
if nodeType == "joint" or nodeType == "transform" or nodeType == "ikHandle" or nodeType == "place3dTexture":
return cmds.xform(target , q =True , ws = True, rotatePivot =True)
elif nodeType == "mesh" or nodeType == "nurbsCurve" or nodeType == "nurbsSurface" or nodeType == "lattice":
return cmds.xform(target , q =True , ws = True, t =True)
def getTrailPoints(planeName,startFrame,endFrame,index):
trailPointNodes = []
trailNodes = []
trailPoints = []
for i in range(0,len(index)):
position = getPosition(planeName +".vtx["+str(index[i])+"]")
trailPointNode = cmds.createNode("transform",name = planeName + str(i))
cmds.setAttr(trailPointNode + ".t",**position)
cmds.parent(trailPointNode,planeName,a =True)
cmds.setAttr(trailPointNode + ".r",0,0,0)
trailPointNodes.append(trailPointNode)
nodes = cmds.snapshot(trailPointNode, motionTrail =True ,increment = 1, startTime =startFrame ,endTime = endFrame)
trailNodes.append(nodes[-1])
points = cmds.getAttr(nodes[-1] + ".points")
trailPoints.append(points)
cmds.delete(trailNodes)
cmds.delete(trailPointNodes)
return trailPoints
一旦 deleteの部分をコメントアウトして実行してみます。
parentSpace = "persp1_nearClipPos"
matrixP = om2.MMatrix(cmds.getAttr(parentSpace+".worldInverseMatrix[0]"))
planeName = "persp1_resGateplane"
startFrame = 1
endFrame = 50
index = [2]
trailPoints = getTrailPoints(planeName,startFrame,endFrame,index)
設置されて、数値も取れました。
この数値をもとにバウンディングボックスを定義して、そこから解像度を割り出します。
一番小さい板のサイズもついでに引っ張り出しておきます。
import maya.cmds as cmds
import maya.api.OpenMaya as om2
import math
def getPosition(target):
nodeType = cmds.nodeType(target)
if nodeType == "joint" or nodeType == "transform" or nodeType == "ikHandle" or nodeType == "place3dTexture":
return cmds.xform(target , q =True , ws = True, rotatePivot =True)
elif nodeType == "mesh" or nodeType == "nurbsCurve" or nodeType == "nurbsSurface" or nodeType == "lattice":
return cmds.xform(target , q =True , ws = True, t =True)
def getTrailPoints(planeName,startFrame,endFrame,index):
trailPointNodes = []
trailNodes = []
trailPoints = []
index = [0,2,6,8]
for i in range(0,len(index)):
position = getPosition(planeName +".vtx["+str(index[i])+"]")
trailPointNode = cmds.createNode("transform",name = planeName + str(i))
cmds.setAttr(trailPointNode + ".t",*position)
cmds.parent(trailPointNode,planeName,a =True)
cmds.setAttr(trailPointNode + ".r",0,0,0)
trailPointNodes.append(trailPointNode)
nodes = cmds.snapshot(trailPointNode, motionTrail =True ,increment = 1, startTime =startFrame ,endTime = endFrame)
trailNodes.append(nodes[-1])
points = cmds.getAttr(nodes[-1] + ".points")
trailPoints.append(points)
cmds.delete(trailNodes)
cmds.delete(trailPointNodes)
return trailPoints
def getBBox(trailPoints,parentSpace):
maxX = None
minX = None
maxY = None
minY = None
minWidth = None
matrixP = om2.MMatrix(cmds.getAttr(parentSpace+".worldInverseMatrix[0]"))
for i in range(0,len(trailPoints[0])):
pointA = trailPoints[0][i][:3]#left-top
pointB = trailPoints[1][i][:3]#right-top
pointC = trailPoints[2][i][:3]#left-bot
pointD = trailPoints[3][i][:3]#right-bot
vectorA = om2.MVector(pointA)
vectorB = om2.MVector(pointB)
vectorC = om2.MVector(pointC)
vectorD = om2.MVector(pointD)
width = (vectorB - vectorA).length()
if minWidth == None:
minWidth = width
elif minWidth > width:
minWidth = width
matrixA = om2.MTransformationMatrix(om2.MMatrix.kIdentity).setTranslation(vectorA,om2.MSpace.kWorld).asMatrix()
matrixB = om2.MTransformationMatrix(om2.MMatrix.kIdentity).setTranslation(vectorB,om2.MSpace.kWorld).asMatrix()
matrixC = om2.MTransformationMatrix(om2.MMatrix.kIdentity).setTranslation(vectorC,om2.MSpace.kWorld).asMatrix()
matrixD = om2.MTransformationMatrix(om2.MMatrix.kIdentity).setTranslation(vectorD,om2.MSpace.kWorld).asMatrix()
localPositionA = om2.MTransformationMatrix(matrixA*matrixP).translation(om2.MSpace.kWorld)
localPositionB = om2.MTransformationMatrix(matrixB*matrixP).translation(om2.MSpace.kWorld)
localPositionC = om2.MTransformationMatrix(matrixC*matrixP).translation(om2.MSpace.kWorld)
localPositionD = om2.MTransformationMatrix(matrixD*matrixP).translation(om2.MSpace.kWorld)
for position in [localPositionA,localPositionB,localPositionC,localPositionD]:
if maxX == None:
maxX = position[0]
elif maxX < position[0]:
maxX = position[0]
if minX == None:
minX = position[0]
elif minX > position[0]:
minX = position[0]
if maxY == None:
maxY = position[1]
elif maxY < position[1]:
maxY = position[1]
if minY == None:
minY = position[1]
elif minY > position[1]:
minY = position[1]
return maxX,minX,maxY,minY,minWidth
##-----------------------------------------------------------------------------------------------------------
def getRasolution(parentSpace,defaultResolution,frameRange,planeIndex=[2,3,0,1]):
trailPoints = getTrailPoints(planeName,frameRange[0],frameRange[1],planeIndex)
maxX,minX,maxY,minY,minWidth = getBBox(trailPoints,parentSpace)
bboxW = maxX - minX
bboxH = maxY - minY
ratio = float(defaultResolution[0]) / minWidth
wholeResolution = [math.ceil(bboxW * ratio), math.ceil(bboxH * ratio)]
if wholeResolution[0] % 8 != 0:
wholeResolution[0] = wholeResolution[0] + (8 - wholeResolution[0] % 8)
if wholeResolution[1] % 8 != 0:
wholeResolution[1] = wholeResolution[1] + (8 - wholeResolution[1] % 8)
return wholeResolution
parentSpace = "persp1_nearClipPos"
planeName = "persp1_resGateplane"
planeIndex = [2,3,0,1] ##left-top/right-top/left-bot/right-bot
defaultResolution = [960,540]
frameRange = [
cmds.playbackOptions(q =True, animationStartTime=True),
cmds.playbackOptions(q =True, animationEndTime=True)
]
wholeResolution = getRasolution(parentSpace,defaultResolution,frameRange,planeIndex=[2,3,0,1])
print(wholeResolution)
# Result: [6656, 3232]
さて、合ってるかどうか・・・・
お、合ってそうですね。
地味にこの確認のための調整が面倒なので、ここもパシッと一発でできたら楽になりそうですね




