0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Mayaのカメラを何とかしたい7 ~レンダリング範囲をトリミング~

0
Posted at

これとは逆に、 特定の部分の解像度を割り出したいなーという場面も。

全体が 960*540 だとして、この赤い部分の解像度はいくつ?

image.png

トリミング用のフレームを設置して、そこから大判と同じ方法で解像度を算出。
そのあと解像度を変更し、フレームがresolutionGateに一致するようにカメラを調整。

ここまでやってみます。

トリミング用のプレートはこんな感じで。
plateCtrl で位置を、plateでスケールを調整する感じです。

image.png

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 addTrimFrame(cameraName,defaultResolution):
    resolutionW = defaultResolution[0]
    resolutionH =  defaultResolution[1]

    sourceResW,sourceResH = getResGateSize(cameraName,resolutionW,resolutionH)
    nearClipPoint = addNearClipPos(cameraName)

    scaleSpace = cmds.createNode("joint",name = cameraName + "_scaleSpace")
    planeCtrl = cmds.createNode("joint",name = cameraName + "_planeCtrl")
    cmds.setAttr(scaleSpace + ".drawStyle",2)
    cmds.setAttr(planeCtrl + ".drawStyle",2)
    
    cmds.parent(planeCtrl,scaleSpace,a=True)
    cmds.parent(scaleSpace,nearClipPoint,r=True)
    
    resGatePlane = cmds.polyPlane(axis = [0,0,1],sx = 1,sy = 1,ch =False,name = cameraName + "_resGateplane")[0]
    cmds.setAttr(resGatePlane + ".template",1)

    cmds.parent(resGatePlane,planeCtrl,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.connectAttr(lengthRatio + ".outFloat",outRezGateW + ".floatA")
    cmds.connectAttr(lengthRatio + ".outFloat",outRezGateH + ".floatA")

    cmds.setAttr(outRezGateW + ".floatB",sourceResW)
    cmds.setAttr(outRezGateH + ".floatB",sourceResH)

    cmds.connectAttr(outRezGateW + ".outFloat",scaleSpace + ".sx")
    cmds.connectAttr(outRezGateH + ".outFloat",scaleSpace + ".sy")
    
    cmds.connectAttr(outRezGateW + ".outFloat",planeCtrl + ".sx")
    cmds.connectAttr(outRezGateH + ".outFloat",planeCtrl + ".sy")
    
    cmds.setAttr(planeCtrl + ".tz",l = True)
    cmds.setAttr(planeCtrl + ".r",l = True)
    cmds.setAttr(planeCtrl + ".s",l = True)
    
    cmds.setAttr(resGatePlane + ".t",l = True)
    cmds.setAttr(resGatePlane + ".r",l = True)
    cmds.setAttr(resGatePlane + ".sz",l = True)

    return resGatePlane,lengthRatio,planeCtrl,scaleSpace

select = cmds.ls(sl =True)
target = select[0]
defaultResolution = [cmds.getAttr("defaultResolution.width"),cmds.getAttr("defaultResolution.height") ]
addTrimFrame(target,defaultResolution)

設置した板の情報を取得して、
resolutionGateとの比率をだして 解像度を算出します。

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, t =True)
        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 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 getTrimResolution(cameraName,parentSpace,planeIndex=[2,3,0,1]):        

    nearClipPlane = cmds.getAttr(cameraName + ".nearClipPlane")
    focalLength = cmds.getAttr(cameraName + ".focalLength")
    ratio = nearClipPlane / focalLength

    pointA = getPosition(planeName +".vtx["+str(planeIndex[0])+"]")#left-top
    pointB = getPosition(planeName +".vtx["+str(planeIndex[1])+"]")#right-top
    pointC = getPosition(planeName +".vtx["+str(planeIndex[2])+"]")#left-bot
    pointD = getPosition(planeName +".vtx["+str(planeIndex[3])+"]")#right-bot

    vectorA = om2.MVector(pointA)
    vectorB = om2.MVector(pointB)
    vectorC = om2.MVector(pointC)
    vectorD = om2.MVector(pointD)

    resolutionW = cmds.getAttr("defaultResolution.width")
    resolutionH = cmds.getAttr("defaultResolution.height") 
    resGateW,resGateH = getResGateSize(cameraName,resolutionW,resolutionH)

    width = (vectorB - vectorA).length()
    height = (vectorC - vectorA).length()

    ratioW = width / (resGateW*ratio)
    ratioH = height / (resGateH*ratio)

    trimedResolution = [resolutionW * ratioW, resolutionH * ratioH]
    
    if trimedResolution[0] % 8 != 0:
        trimedResolution[0] = trimedResolution[0] + (8 - trimedResolution[0] % 8)
    
    if trimedResolution[1] % 8 != 0:
        trimedResolution[1] = trimedResolution[1] + (8 - trimedResolution[1] % 8)

    return trimedResolution

##-----------------------------------------------------------------------------------------------------------
cameraName = "persp1"
parentSpace = "persp1_nearClipPos"
planeName = "persp1_resGateplane"
planeIndex = [2,3,0,1] ##left-top/right-top/left-bot/right-bot

trimedResolution = getTrimResolution(cameraName,parentSpace,planeIndex=[2,3,0,1])
# Result: [176.0, 352.0]

合ってそうなきはしますね

つづけて、カメラの filmOffsetとpostScaleで切り抜きフレームにresolutionGateが合うようにします。


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, t =True)
        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 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 getTrimResolution(cameraName,parentSpace,planeIndex=[2,3,0,1]):        

    nearClipPlane = cmds.getAttr(cameraName + ".nearClipPlane")
    focalLength = cmds.getAttr(cameraName + ".focalLength")
    ratio = nearClipPlane / focalLength

    pointA = getPosition(planeName +".vtx["+str(planeIndex[0])+"]")#left-top
    pointB = getPosition(planeName +".vtx["+str(planeIndex[1])+"]")#right-top
    pointC = getPosition(planeName +".vtx["+str(planeIndex[2])+"]")#left-bot
    pointD = getPosition(planeName +".vtx["+str(planeIndex[3])+"]")#right-bot

    vectorA = om2.MVector(pointA)
    vectorB = om2.MVector(pointB)
    vectorC = om2.MVector(pointC)
    vectorD = om2.MVector(pointD)

    resolutionW = cmds.getAttr("defaultResolution.width")
    resolutionH = cmds.getAttr("defaultResolution.height") 
    resGateW,resGateH = getResGateSize(cameraName,resolutionW,resolutionH)

    width = (vectorB - vectorA).length()
    height = (vectorC - vectorA).length()

    ratioW = width / (resGateW*ratio)
    ratioH = height / (resGateH*ratio)

    trimedResolution = [resolutionW * ratioW, resolutionH * ratioH]
    
    if trimedResolution[0] % 8 != 0:
        trimedResolution[0] = trimedResolution[0] + (8 - trimedResolution[0] % 8)
    
    if trimedResolution[1] % 8 != 0:
        trimedResolution[1] = trimedResolution[1] + (8 - trimedResolution[1] % 8)

    return trimedResolution
    
def adjustFrame(cameraName,planeName,parentSpace,resolutionW,resolutionH,planeIndex):
    nearClipPlane = cmds.getAttr(cameraName + ".nearClipPlane")
    focalLength = cmds.getAttr(cameraName + ".focalLength")
    resGateW,resGateH = getResGateSize(cameraName,resolutionW,resolutionH)
    ratio = nearClipPlane / focalLength
    
    ##filmOffset
    matrixP = om2.MMatrix(cmds.getAttr(parentSpace+".worldInverseMatrix[0]"))
    matrixA = om2.MMatrix(cmds.getAttr(planeName+".worldMatrix[0]"))
    localPositionA = om2.MTransformationMatrix(matrixA*matrixP).translation(om2.MSpace.kWorld)

    offsetX = ((localPositionA[0]/(resGateW*ratio))*resGateW) / 25.4
    offsetY = ((localPositionA[1]/(resGateH*ratio))*resGateH) / 25.4
    
    curOffsetX = cmds.getAttr(cameraName + ".horizontalFilmOffset")
    curOffsetY = cmds.getAttr(cameraName + ".verticalFilmOffset")

    cmds.setAttr(cameraName + ".horizontalFilmOffset",curOffsetX + offsetX)
    cmds.setAttr(cameraName + ".verticalFilmOffset",curOffsetY + offsetY)

    ##postScale
    pointA = getPosition(planeName +".vtx["+str(planeIndex[0])+"]")#left-top
    pointB = getPosition(planeName +".vtx["+str(planeIndex[1])+"]")#right-top
    width = (om2.MVector(pointB) - om2.MVector(pointA)).length()

    ratioW = width / (resGateW*ratio)

    curPostScale = cmds.getAttr(cameraName + ".postScale")
    cmds.setAttr(cameraName + ".postScale",curPostScale*(1.0/ratioW))
    
##---------------------------------------------------------------------------------------------
cameraName = "persp1"
parentSpace = "persp1_nearClipPos"
planeName = "persp1_resGateplane"
planeIndex = [2,3,0,1] ##left-top/right-top/left-bot/right-bot

trimedResolution = getTrimResolution(cameraName,parentSpace,planeIndex=[2,3,0,1])
cmds.setAttr("defaultResolution.width",trimedResolution[0])
cmds.setAttr("defaultResolution.height",trimedResolution[1]) 
cmds.setAttr("defaultResolution.deviceAspectRatio", trimedResolution[0] / trimedResolution[1]) 

adjustFrame(cameraName,planeName,parentSpace,trimedResolution[0],trimedResolution[1],planeIndex)

実行すると
これがー
image.png

こう!
image.png

これがー
image.png

こう!
image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?