简体   繁体   English

点的查询在网格内 Maya python api

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

I'm trying to figure out a way of calculating if a world space point is inside of an arbitrary mesh.我试图找出一种计算世界空间点是否在任意网格内的方法。

I'm not quite sure of the math on how to calculate it if it's not a cube or sphere.如果它不是立方体或球体,我不太确定如何计算它的数学方法。

Any help would be great!任何帮助都会很棒!

One can use a simple ray tracing trick to test if you are inside or outside of a shape.人们可以使用一种简单的光线追踪技巧来测试您是在形状的内部还是外部。 It turns out that 2D, 3D objects or possibly even higher dimension objects have a neat property.事实证明,2D、3D 对象或什至可能更高维的对象具有整洁的属性。 That is if you shoot an arbitrary ray in any direction you are inside the shape if, and only if you hit the boundaries of your shape and odd number of times.也就是说,如果您在任何方向上发射任意光线,当且仅当您击中形状的边界且次数为奇数时,您才处于形状内部。 No need to know the normal direction or anything.无需知道正常方向或任何东西。 Just know how many intersections you have.只要知道你有多少个交叉点。 This is easy to visualize in 2D, and since 3D is just many 2D slices same applies to 3D too.这很容易在 2D 中进行可视化,并且由于 3D 只是许多 2D 切片,因此同样适用于 3D。

在此处输入图片说明

figure 1: Shooting a ray from a point in an arbitrary direction produces an odd number of hits if inside and an even if outside, So O 1 is inside and O 2 is not.图 1:从任意方向的一个点射出一条射线,如果在里面,即使在外面,也会产生奇数次命中,所以 O 1在里面,O 2不在。 As a special case glancing hits need to be tested for curves because they make 2 hits coincide in one place (O 3 ).作为一种特殊情况,需要针对曲线测试斜视命中,因为它们使 2 个命中重合在一个位置 (O 3 )。

在此处输入图片说明

figure 2: Meshed surfaces have a better boundary condition as only vertex hits are glancing However most tracing engines ignore glancing hits as totally perpendicular hits (O 4 ) would be problematic so they behave right for purposes of this test.图 2:网格曲面具有更好的边界条件,因为只有顶点命中是掠过然而,大多数跟踪引擎忽略掠过,因为完全垂直的命中 (O 4 ) 会出现问题,因此它们的行为适合此测试的目的。 Maya tracer is no exception.玛雅示踪剂也不例外。

Please note this method does not need the surface to be closed, it works none the less it just closes the gap in direction of the ray and open surfaces can report weird results.请注意,此方法不需要关闭曲面,它仍然有效,它只是关闭了光线方向上的间隙,而打开的曲面可能会报告奇怪的结果。 But can be acceptable in some cases.但在某些情况下是可以接受的。

Admittedly ray tracing is pretty heavy operation without acceleration routines, however it becomes quite fast once acceleration is in place.诚然,光线追踪在没有加速例程的情况下是非常繁重的操作,但是一旦加速到位,它就会变得非常快。 Maya API provides a method for this. Maya API 为此提供了一种方法。 Note the accelerator is built first then each subsequent call is much cheaper.请注意,首先构建加速器,然后每次后续调用都便宜得多。 Here is a quickly written scaffold without acceleration see docs for MFnMesh for more info on how to accelerate:这是一个快速编写的没有加速的脚手架,请参阅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))

In your specific case this may be overkill.在您的具体情况下,这可能是矫枉过正。 I assume your doing some kind of rejection sampling.我假设你在做某种拒绝抽样。 It is also possible to build the body out of prisms and randomize with barycentric like coordinates.也可以用棱镜构建物体并使用类似重心的坐标随机化。 This has the advantage of never wasting results.这具有从不浪费结果的优点。 But the tracing code is much easier to generally use.但是跟踪代码通常更容易使用。

If you're attempting to solve this problem for any mesh, you'll have trouble, because not every arbitrary mesh is closed.如果您尝试为任何网格解决此问题,您将遇到麻烦,因为并非每个任意网格都是关闭的。 If your mesh can be assumed closed and well-formed, then you might have to do something like a 3D flood-fill algorithm to determine whether there's a path to a point that can see outside the object from the point you're testing.如果可以假设您的网格是闭合且结构良好的,那么您可能需要执行类似 3D 洪水填充算法的操作,以确定是否有一条路径可以从您正在测试的点看到对象外部的点。

If you're willing to take a looser approach that gives you an approximate answer, and assumes that normals are all uniformly pointed outward, there's a code example on this page, written in MEL, that you might be able to convert to Python.如果您愿意采用更宽松的方法来给出近似答案,并假设法线都统一向外指向,则此页面上有一个用 MEL 编写的代码示例,您可以将其转换为 Python。

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

Mark is correct, there's no guaranteed test that works for open meshes.马克是正确的,没有保证测试适用于开放网格。 Also, arbitrary mesh tests are going to be slow and expensive, so try the cheap tests (bounding sphere and or bounding box) first.此外,任意网格测试将缓慢且昂贵,因此请先尝试廉价测试(边界球体和/或边界框)。 You can also just tell the user 'sorry, no dice' if you have any open edges on your mesh -- that guarantees there is no solution for the concept of 'inside'如果您的网格上有任何开放的边缘,您也可以告诉用户“对不起,没有骰子”——这保证了“内部”的概念没有解决方案

If you want an approximate answer that's better than a bounds test but not as expensive as something like a voxel test, you can use qHull or something similar to generate a convex hull for your mesh and test against the convex mesh.如果您想要一个比边界测试更好但又不像体素测试那么昂贵的近似答案,您可以使用qHull或类似的东西为您的网格生成凸包并针对凸网格进行测试。 That will not handle serious concavities of meshes that twist inside out, but will catch oddly shaped objects with more grace than a bounds test.这不会处理由内向外扭曲的网格的严重凹陷,但会比边界测试更优雅地捕捉形状奇特的物体。

If you really need speed or have complex objects, you probably want to voxelize the object and test the voxel data.如果您确实需要速度或拥有复杂的对象,您可能希望对对象进行体素化并测试体素数据。 This is typically too math-heavy for scripting (see this , for example) and it's not trivial to implement.这对于脚本编写来说通常过于数学化(例如,请参阅)并且实现起来并非易事。

All that said, here's a very hacky approximation of voxels using the built-in nParticles:综上所述,这里有一个使用内置 nParticle 的体素近似值:

If you have nParticles (maya 2011 + ) you can try filling your object ( nParticles > createNParticles > Fill Object ) with particles.如果您有 nParticles(maya 2011 +),您可以尝试用粒子填充您的对象( nParticles > createNParticles > Fill Object )。 You can then distance test your point against the positition of each particle in the particle set.然后,您可以根据粒子集中每个粒子的位置对您的点进行距离测试。 If the distance to any particle is less than or equal to the particles' radius, you're 'inside' to within 1/2 particle radius accuracy.如果到任何粒子的距离小于或等于粒子的半径,则您处于 1/2 粒子半径精度内的“内部”。 You'll note that some shapes can't be filled by nparticles - those are the kind of shapes you can't test 'insidedness' for anyway.您会注意到某些形状不能由 nparticles 填充 - 这些形状无论如何都无法测试“内部性”。

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

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