繁体   English   中英

点的查询在网格内 Maya python api

[英]Querying of a point is within a mesh maya python api

我试图找出一种计算世界空间点是否在任意网格内的方法。

如果它不是立方体或球体,我不太确定如何计算它的数学方法。

任何帮助都会很棒!

人们可以使用一种简单的光线追踪技巧来测试您是在形状的内部还是外部。 事实证明,2D、3D 对象或什至可能更高维的对象具有整洁的属性。 也就是说,如果您在任何方向上发射任意光线,当且仅当您击中形状的边界且次数为奇数时,您才处于形状内部。 无需知道正常方向或任何东西。 只要知道你有多少个交叉点。 这很容易在 2D 中进行可视化,并且由于 3D 只是许多 2D 切片,因此同样适用于 3D。

在此处输入图片说明

图 1:从任意方向的一个点射出一条射线,如果在里面,即使在外面,也会产生奇数次命中,所以 O 1在里面,O 2不在。 作为一种特殊情况,需要针对曲线测试斜视命中,因为它们使 2 个命中重合在一个位置 (O 3 )。

在此处输入图片说明

图 2:网格曲面具有更好的边界条件,因为只有顶点命中是掠过然而,大多数跟踪引擎忽略掠过,因为完全垂直的命中 (O 4 ) 会出现问题,因此它们的行为适合此测试的目的。 玛雅示踪剂也不例外。

请注意,此方法不需要关闭曲面,它仍然有效,它只是关闭了光线方向上的间隙,而打开的曲面可能会报告奇怪的结果。 但在某些情况下是可以接受的。

诚然,光线追踪在没有加速例程的情况下是非常繁重的操作,但是一旦加速到位,它就会变得非常快。 Maya API 为此提供了一种方法。 请注意,首先构建加速器,然后每次后续调用都便宜得多。 这是一个快速编写的没有加速的脚手架,请参阅MFnMesh 的文档以获取有关如何加速的更多信息:

import maya.cmds as cmd
import maya.OpenMaya as om 

def test_if_inside_mesh(point=(0.0, 0.0, 0.0), dir=(0.0, 0.0, 1.0)):
    sel = om.MSelectionList()
    dag = om.MDagPath()

    #replace torus with arbitrary shape name
    sel.add("pTorusShape1")
    sel.getDagPath(0,dag)

    mesh = om.MFnMesh(dag)

    point = om.MFloatPoint(*point)
    dir = om.MFloatVector(*dir)
    farray = om.MFloatPointArray()

    mesh.allIntersections(
            point, dir,
            None, None,
            False, om.MSpace.kWorld,
            10000, False,
            None, # replace none with a mesh look up accelerator if needed
            False,
            farray,
            None, None,
            None, None,
            None
        ) 
    return farray.length()%2 == 1   

#test
cmd.polyTorus()
print test_if_inside_mesh()
print test_if_inside_mesh((1,0,0))

在您的具体情况下,这可能是矫枉过正。 我假设你在做某种拒绝抽样。 也可以用棱镜构建物体并使用类似重心的坐标随机化。 这具有从不浪费结果的优点。 但是跟踪代码通常更容易使用。

如果您尝试为任何网格解决此问题,您将遇到麻烦,因为并非每个任意网格都是关闭的。 如果可以假设您的网格是闭合且结构良好的,那么您可能需要执行类似 3D 洪水填充算法的操作,以确定是否有一条路径可以从您正在测试的点看到对象外部的点。

如果您愿意采用更宽松的方法来给出近似答案,并假设法线都统一向外指向,则此页面上有一个用 MEL 编写的代码示例,您可以将其转换为 Python。

http://forums.cgsociety.org/archive/index.php/t-747732.html

马克是正确的,没有保证测试适用于开放网格。 此外,任意网格测试将缓慢且昂贵,因此请先尝试廉价测试(边界球体和/或边界框)。 如果您的网格上有任何开放的边缘,您也可以告诉用户“对不起,没有骰子”——这保证了“内部”的概念没有解决方案

如果您想要一个比边界测试更好但又不像体素测试那么昂贵的近似答案,您可以使用qHull或类似的东西为您的网格生成凸包并针对凸网格进行测试。 这不会处理由内向外扭曲的网格的严重凹陷,但会比边界测试更优雅地捕捉形状奇特的物体。

如果您确实需要速度或拥有复杂的对象,您可能希望对对象进行体素化并测试体素数据。 这对于脚本编写来说通常过于数学化(例如,请参阅)并且实现起来并非易事。

综上所述,这里有一个使用内置 nParticle 的体素近似值:

如果您有 nParticles(maya 2011 +),您可以尝试用粒子填充您的对象( nParticles > createNParticles > Fill Object )。 然后,您可以根据粒子集中每个粒子的位置对您的点进行距离测试。 如果到任何粒子的距离小于或等于粒子的半径,则您处于 1/2 粒子半径精度内的“内部”。 您会注意到某些形状不能由 nparticles 填充 - 这些形状无论如何都无法测试“内部性”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM