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?

MayaAdvent Calendar 2023

Day 22

mayaのブーリアンで虚無が生まれるので雑な奴を自作

Last updated at Posted at 2023-12-21

maya2024からブーリアンが改修されたようなのですが、
まだ2022をメインでやってるもので

ブーリアンが難しい

コツというか、未だその辺をつかめていないので
ブーリアン実行!ってやると大体虚無が生まれるんですよね。

時間がない時だと、えーあーもういいやブーリアンあきらめよう!
ってなってしまいがち。

今回もそうなってしまいましたが、処理する数が多かったので
メッシュがスフィアの中に収まるようにスフィアの外側にはみ出た部分を何とかする

というパワー な処理を作ってなんとかしました。

設計

ターゲットはこんな感じ
image.png

スフィア(切り取りオブジェクト)から

外にはみ出てるメッシュを削除したい。

または

外にはみ出てるメッシュを内側に押し込めたい

パッと思いついたのはshrinkWrapですが、
はみ出てる部分を判別できない事にはなぁ・・・・

vtxが切り取りオブジェクトの外にいるかうちにいるか
を判別出来ればあとは煮るなり焼くなりにのみやかz

凄く雑に考えると

  • vtxの位置から全軸の方向にレイを飛ばす
  • レイが1か所でも切り取りオブジェクトにヒットしない場合は外
  • レイが全て切り取りオブジェクトにヒットした場合は内

でいいかなぁ。
まぁ切り取りオブジェクトが複雑な形状だと法線とかもみないと駄目かなと思いますが、今回はシンプルな形状なので。

雑に実装

import maya.cmds as cmds
import maya.api.OpenMaya as om

def getDagNode(target):    
    try:
        sellist = om.MGlobal.getSelectionListByName(target)
        return sellist.getDagPath(0)
    except:
        return None
        
def stringToVector(axis):
    if axis == "x":
        return om.MVector.kXaxisVector 
    elif axis == "y":
        return om.MVector.kYaxisVector 
    elif axis == "z":
        return om.MVector.kZaxisVector 

    elif axis == "-x":
        return om.MVector.kXnegAxisVector
    elif axis == "-y":
        return om.MVector.kYnegAxisVector
    elif axis == "-z":
        return om.MVector.kZnegAxisVector

def checkVtxInside(vtx,mesh):
    meshDagPath = getDagNode(mesh)
    shapeFn = om.MFnMesh(meshDagPath)
    position = cmds.xform(vtx , q =True , ws = True, t =True)
    raySource = om.MFloatPoint(*position)
    space =  om.MSpace.kWorld
                
    id_list = []
    point_list = []
    isInside = True
    for axis in ["x","y","z","-x","-y","-z"]:
        #vtxの位置から全軸方向へrayをとばす
        axisVector = stringToVector(axis)    
        maxParam = 9999
        testBothDirections = False
        accelParams=om.MMeshIsectAccelParams()
        result = shapeFn.closestIntersection(
                                                raySource,
                                                om.MFloatVector(axisVector),
                                                space,
                                                maxParam,
                                                testBothDirections, idsSorted=False, accelParams=accelParams, tolerance=0.0001)    
        
        if result == None:
            isInside = False
            break

    return isInside

def getOutsideVtx(checkTarget,clipGuide):
    meshDagPath = getDagNode(checkTarget)
    shapeFn = om.MFnMesh(meshDagPath) 
    
    outsideVtx = []
    for i in range(0,shapeFn.numVertices):
        #ターゲットのvtxを順番に処理
        isInside = checkVtxInside(checkTarget +".vtx["+str(i)+"]",clipGuide)

        if isInside == False:
            outsideVtx.append(checkTarget +".vtx["+str(i)+"]")

    return outsideVtx

checkTarget = "pCube1"
clipGuide = "pSphere1"
outsideVtx = getOutsideVtx(checkTarget,clipGuide)
cmds.select(outsideVtx,r =True)

ぱっと見は・・・・・大丈夫そうかな?
image.png

あとはこのvtxを元にポリゴンを削除するなり、shrinkWrapでスフィアにくっつけるなりすれば
虚無は回避できそうですわね

shrikWrapするとこんな感じ
image.png

実際の運用時には

  • 外のvtxをfaceに変換
  • 変換したfaceを削除
  • 削除後にも外側に残ってるvtxを再取得
  • そのvtxを切り取りオブジェクトの最近接点にスナップ

までを処理させて対応しました。

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?