如果您尝试针对任何网格解决此问题,都会遇到麻烦,因为并非所有的任意网格都是封闭的。如果可以假设您的网格是封闭的且格式正确,则可能必须执行3D泛洪填充算法之类的操作来确定是否存在从测试点到可以在对象外部看到的点的路径。 >
[如果您愿意采用一个宽松的方法来为您提供一个近似的答案,并且假定法线都统一指向外部,则此页上有一个用MEL编写的代码示例,您也许可以将其转换为Python 。
我试图找出一种计算世界空间点是否在任意网格内部的方法。
如果不是立方体或球体,我不太清楚如何计算的数学。
任何帮助都会很棒!
可以使用简单的光线追踪技巧来测试您是在形状的内部还是外部。事实证明,2D,3D对象或什至更高尺寸的对象都具有整洁的属性。就是说,如果您朝任意方向发射任意光线,那么您就处于形状内部,并且仅当您达到形状边界和奇数次时。无需知道正常方向或其他任何信息。只知道您有几个路口。这很容易在2D中可视化,并且由于3D只是许多2D切片,同样适用于3D。
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9GNlNkay5wbmcifQ==” alt =“在此处输入图像描述”>“ >>
图1:
从任意方向的某个点发出光线,如果在内部且在外部,则产生奇数次的命中,因此O 1在内部,O 2在不。作为一种特例,需要测试扫视命中的曲线,因为它们使2个命中在同一位置重合(O 3)。<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS80RTdjZi5wbmcifQ==” alt =“在此处输入图像说明”>“ >>
图2:
网格化的曲面具有更好的边界条件,因为只有顶点命中会扫视,但是大多数跟踪引擎会忽略扫视命中,因为完全垂直的命中(O 4)会出现问题,因此它们的行为正确无误这个测试。 Maya跟踪器也不例外。请注意,此方法不需要关闭表面,但它只是在射线方向上闭合间隙,开放的表面可能会报告奇怪的结果,但它仍然有效。但在某些情况下可以接受。
公认的是,光线追踪是没有加速程序的繁重操作,但是一旦加速到位,光线追踪就会变得非常快。 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 。
标记是正确的,没有可以保证的测试适用于开放式网格。同样,任意网格测试将变得缓慢且昂贵,因此请首先尝试便宜的测试(边界球和边界框)。如果网格上有任何开放的边缘,您也可以告诉用户“对不起,没有骰子”-这可以保证“内部”的概念没有解决方案。
如果您想得到一个比边界测试更好的近似答案,但又不像像体素测试那样昂贵,您可以使用qHull或类似方法为网格生成凸包并针对凸网格进行测试。这将无法处理严重的由内向外扭曲的网状凹面,但会捕获比边界测试更优雅的奇形异状的对象。
如果您确实需要速度或具有复杂的对象,则可能需要体素化对象并测试体素数据。对于脚本编写来说,这通常过于数学化(例如,请参见this),并且实现起来并非易事。
所有这些,这是使用内置nParticles对体素的非常hacky
如果有nParticles(Maya 2011 +),则可以尝试用粒子填充对象(nParticles> createNParticles>填充对象
)。然后,您可以针对粒子集中每个粒子的位置进行距离测试。如果到任何粒子的距离小于或等于粒子的半径,则您在“内部”以内1/2粒子半径精度。您会注意到,某些形状无法被n粒子填充-不管怎样,这些形状都是您无法测试“内在面”的形状。如果您尝试针对任何网格解决此问题,都会遇到麻烦,因为并非所有的任意网格都是封闭的。如果可以假设您的网格是封闭的且格式正确,则可能必须执行3D泛洪填充算法之类的操作来确定是否存在从测试点到可以在对象外部看到的点的路径。 >
[如果您愿意采用一个宽松的方法来为您提供一个近似的答案,并且假定法线都统一指向外部,则此页上有一个用MEL编写的代码示例,您也许可以将其转换为Python 。
标记是正确的,没有可以保证的测试适用于开放式网格。同样,任意网格测试将变得缓慢且昂贵,因此请首先尝试便宜的测试(边界球和边界框)。如果网格上有任何开放的边缘,您也可以告诉用户“对不起,没有骰子”-这可以保证“内部”的概念没有解决方案。
如果您想得到一个比边界测试更好的近似答案,但又不像像体素测试那样昂贵,您可以使用qHull或类似方法为网格生成凸包并针对凸网格进行测试。这将无法处理严重的由内向外扭曲的网状凹面,但会捕获比边界测试更优雅的奇形异状的对象。
如果您确实需要速度或具有复杂的对象,则可能需要体素化对象并测试体素数据。对于脚本编写来说,这通常过于数学化(例如,请参见this),并且实现起来并非易事。