2013-08-08 1 views
2

Я пытаюсь выяснить способ вычисления, если точка мирового пространства находится внутри произвольной сетки.Запрос точки находится в пределах mesh maya python api

Я не совсем уверен в математике, как вычислить его, если это не куб или сфера.

Любая помощь будет замечательной!

ответ

10

Можно использовать простой трассировочный трюк для проверки, если вы находитесь внутри или снаружи формы. Оказывается, что двумерные, трехмерные объекты или, возможно, даже более крупные размерные объекты имеют аккуратное свойство. То есть, если вы снимаете произвольный луч в любом направлении, находящемся внутри фигуры, если и только если вы нажмете границы своей фигуры и нечетное число раз. Не нужно знать нормальное направление или что-то еще. Просто знайте, сколько пересечений у вас есть. Это легко визуализировать в 2D, и поскольку 3D - это просто много 2D-фрагментов, то это относится и к 3D.

enter image description here

фигура 1: Стрельба луч из точки в произвольном направлении производит нечетное число ударов, если внутри и даже если снаружи, так O_1 внутри и O_2 нет. В качестве особого случая оглядывающие хиты должны быть проверены на кривые, потому что они делают два удара совпадающими в одном месте (O_3).

enter image description here

фигура 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)) 

В вашем конкретном случае это может быть излишним. Я предполагаю, что вы делаете какую-то отбраковку. Также возможно построить тело из призм и рандомизировать с помощью барицентрических подобных координат. Это имеет то преимущество, что никогда не тратишь впустую результаты. Но трассировочный код намного проще использовать.

+0

Удивительный. Большое спасибо! – chribis

1

Если вы пытаетесь решить эту проблему для любой сетки, у вас возникнут проблемы, потому что не каждая произвольная сетка закрыта. Если ваша сетка может считаться замкнутой и хорошо сформированной, вам может понадобиться сделать что-то вроде 3D-заливки, чтобы определить, есть ли путь к точке, которая может видеть вне объекта с точки, которую вы тестируете.

Если вы готовы принять более свободный подход, который дает приблизительный ответ и предполагает, что нормали все равно направлены наружу, на этой странице, написанной в MEL, есть пример кода, который вы могли бы преобразовать на Python.

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

+0

Я копаю технику. В этом случае я не должен был говорить «произвольная» сетка. Это относится к замкнутой сетке и, в частности, к тому моменту, когда я имею дело с неоднородным кубом. Ограничительная рамка в ситуации не работает, потому что это не совсем правильный угловой куб. Спасибо за ответ! – chribis

+0

Форма, которую я хотел назвать, это «Hexahedron». http://etc.usf.edu/clipart/42200/42204/hexahedron_42204_lg.gif – chribis

0

Марк является правильным, нет гарантировано теста, который работает на открытые сетки. Кроме того, произвольные тесты сетки будут медленными и дорогостоящими, поэтому сначала попробуйте дешевые тесты (ограничивающая сфера и ограничивающая рамка). Вы также можете просто сказать пользователю «извините, не кубик», если у вас есть какие-либо открытые края на вашей сетке, что гарантирует отсутствие решения для понятия «внутри»

Если вы хотите приблизительный ответ, который лучше, чем тест границ, но не такой дорогой, как что-то вроде теста воксела, вы можете использовать qHull или что-то подобное для создания выпуклого корпуса для вашей сетки и теста против выпуклой сетки. Это не будет обрабатывать серьезные вогнутости сетки, которые выкручиваются наизнанку, но будут захватывать объекты с нечеткой формой с большей грацией, чем тест границ.

Если вам действительно нужна скорость или сложные объекты, вы, вероятно, захотите выполнить вокселизацию объекта и проверить данные вокселя. Это типично слишком тяжело для сценариев (см., Например, this), и его нетривиально реализовать.

Все, что сказал, вот очень Hacky приближения вокселей с использованием встроенного nParticles:

Если у вас есть nParticles (MAYA 2011 +), вы можете попробовать наполняя объект (nParticles> createNParticles> Fill Объект) с частицами. Затем вы можете дистанцировать проверку своей точки от положения каждой частицы в наборе частиц. Если расстояние до любой частицы меньше или равно радиусу частиц, вы «внутри» с точностью до 1/2 радиуса частиц. Вы заметите, что некоторые фигуры не могут быть заполнены nparticles - это те формы, которые вы не можете тестировать во всей полноте.