2016-03-04 4 views
2

Мне было интересно, как бы вы, математически говоря, генерировать x точек в случайных положениях на трехмерной поверхности, зная количество треугольных многоугольников, составляющих поверхность (их размеры, положения, нормали, и т.д.)? Сколько шагов вы предпримете?Генерировать случайные точки на любой трехмерной поверхности

Я пытаюсь создать «рассеиватель» в Maya (с Python и API), но я даже не знаю, с чего начать с точки зрения концепции. Должен ли я сначала создать точки, а затем проверить, принадлежат ли они к поверхности? Должен ли я создавать точки непосредственно на поверхности (и как, в этом случае)?

Редактировать: Я хочу достичь этого, не используя 2D-проекцию или УФ-лучи, насколько это возможно.

+0

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

ответ

2

Вы должны вычислить площадь каждого треугольника и использовать их в качестве весов для определения места назначения каждой случайной точки.Это, вероятно, проще всего сделать это в качестве пакетной операции:

def sample_areas(triangles, samples): 
    # compute and sum triangle areas 
    totalA = 0.0 
    areas = [] 
    for t in triangles: 
    a = t.area() 
    areas.append(a) 
    totalA += a 

    # compute and sort random numbers from [0,1) 
    rands = sorted([random.random() for x in range(samples)]) 

    # sample based on area 
    area_limit = 0.0 
    rand_index = 0 
    rand_value = rands[rand_index] 
    for i in range(len(areas)): 
    area_limit += areas[i] 
    while rand_value * totalA < area_limit: 
     # sample randomly over current triangle 
    triangles[i].add_random_sample() 

     # advance to next sorted random number 
     rand_index += 1; 
     if rand_index >= samples: 
     return 
     rand_value = rands[rand_index] 

Обратите внимание, что остроконечные или морщинистые участки могут появляться, имеют более высокую плотность точек, просто потому, что они имеют большую площадь поверхности в меньшем пространстве.

+0

Спасибо за ваш ответ. Я пытаюсь переписать псевдоним в коде python, но у меня есть проблемы с переводом части цикла, не могли бы вы дать мне больше детали или комментарии, чтобы объяснить, как это работает? Еще раз спасибо – UKDP

+1

Я переписал псевдокод в python. Непроверенный, так что стоит того, за что ты заплатил за это ... – comingstorm

1

Здесь пока псевдо код, который может быть хорошей отправной точкой:

  1. Пусть N = нет вершин 3D лица, что вы работаете.
  2. Просто сгенерируйте N случайных чисел, вычислите их сумму, разделите каждый на сумму. Теперь у вас есть N случайных чисел, сумма которых равна 1.0.
  3. Используя приведенные выше случайные числа, возьмите linear combination трехмерных вершин интересующего вас трехмерного лица. Это должно дать вам случайную трехмерную точку на лице.
  4. Повторите, пока не получите достаточное количество. случайных точек на трехмерной грани.
2

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

Хакстастический способ сделать это будет создание UV-карты для вашего 3D-объекта, а затем случайным образом разброс точек в 2-х измерениях (выбрасывание точек, которые не попадали в действительную UV-оболочку). После того, как ваши UV-оболочки будут заполнены так, как вам хотелось бы, вы можете конвертировать ваши УФ-очки в barycentric coordinates, чтобы преобразовать эти 2-D точки обратно в 3-D точки: эффективно вы говорите: «Я 30% верхушки A, 30% вершина B и 40% вершины C, поэтому моя позиция (.3A + .3B + .4C)

Помимо простоты, еще одним преимуществом использования UV-карты является то, что она позволит вам настроить плотность и относительную важность из разных частей сетки: большая УФ-поверхность будет получать много разбросанных точек, а меньшая - меньше, даже если это не соответствует физическому размеру или граням.

Переход к 2D представит некоторые артефактов, потому что вы, вероятно, не сможете придумать УФ-карту, которая будет без растягивания и без шва, поэтому вы получите варианты из-за этого. Однако для многих приложений это будет хорошо, так как алгоритм очень прост и результаты легко настраиваются.

Я не использовал этот один, но это выглядит как оно основано на этом общем подходе: http://www.shanemarks.co.za/uncategorized/uv-scatter-script/

Если вам нужна более математически строгий метод, вы должны были бы любитель метод mesh parameterization: способ превратить ваш 3-й набор треугольников в согласованное пространство. В этой области много интересной работы, но было бы трудно выбрать конкретный путь, не зная приложения.

+0

Эй, спасибо за ваш ответ! Дело в том, что я должен был добавить это в свой пост. Я хочу избежать модификации UV, потому что в сетке уже могут быть UV, и я не хочу их модифицировать. – UKDP

+1

Вы можете добавить пользовательский UV-канал, а затем удалить его, когда закончите. – theodox

2
  1. Выберите 2 случайных края из случайного треугольника.
  2. Создайте 2 случайных точки по краям.
  3. Создайте новую случайную точку между ними.

Мой некрасиво Mel сценарий: метод

//Select poly and target object 
{ 
$sel = `ls -sl -fl`; select $sel[0]; 
polyTriangulate -ch 0; 
$poly_s = `polyListComponentConversion -toFace`;$poly_s = `ls -fl $poly_s`;//poly flat list 
int $numPoly[] = `polyEvaluate -fc`;//max random from number of poly 
int $Rand = rand($numPoly[0]);//random number 
$vtx_s =`polyListComponentConversion -tv $poly_s[$Rand]`;$vtx_s=`ls- fl $vtx_s`;//3 vertex from random poly flat list 
undo; //for polyTriangulate 

vector $A = `pointPosition $vtx_s[0]`; 
vector $B = `pointPosition $vtx_s[1]`; 
vector $C = `pointPosition $vtx_s[2]`; 
vector $AB = $B-$A; $AB = $AB/mag($AB); //direction vector and normalize 
vector $AC = $A-$C; $AC = $AC/mag($AC); //direction vector and normalize 
$R_AB = mag($B-$A) - rand(mag($B-$A)); vector $AB = $A + ($R_AB * $AB);//new position 
$R_AC = mag($A-$C) - rand(mag($A-$C)); vector $AC = $C + ($R_AC * $AC);//new position 
vector $ABC = $AB-$AC; $ABC = $ABC/mag($ABC); //direction vector and normalize 
$R_ABC = mag($AB-$AC) - rand(mag($AB-$AC)); //random 
vector $ABC = $AC + ($R_ABC * $ABC); 
float $newP2[] = {$ABC.x,$ABC.y,$ABC.z};//back to float 

move $newP2[0] $newP2[1] $newP2[2] $sel[1]; 
select -add $sel[1]; 
} 

PS UV лучше

 Смежные вопросы

  • Нет связанных вопросов^_^