2016-03-04 129 views
2

我想知道,在數學上,如何在3D表面上的隨機位置生成x個點,知道組成曲面的三角形多邊形的數量(它們的尺寸,位置,法線,等等。)?你會在多少步驟中進行?在任意三維表面上生成隨機點

我想在Maya中創建一個「scatterer」(使用Python和API),但我甚至不知道從概念開始從哪裏開始。我應該先生成點,然後檢查它們是否屬於表面?我應該直接在表面創建點(以及在這種情況下如何)?

編輯:我想在不使用2D投影或UV的情況下儘可能達到此目的。

+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 =沒有,你正在使用的三維人臉的頂點。
  2. 只需生成N個隨機數,計算它們的總和,然後每個數除以總和。現在你有N個隨機數,其總和= 1.0。
  3. 使用上面的隨機數字,獲取您感興趣的3D人臉的3D頂點的linear combination。這應該會給您一個臉上的隨機3D點。
  4. 重複,直到你得到足夠的沒有。 3D面上的隨機點。
2

如果約束條件是所有輸出點都在表面上,那麼您需要一種一致的方法來處理曲面本身,而不用擔心點的3d>曲面轉換。這樣做的hacktastic方法是爲你的3D對象創建一個UV貼圖,然後在2維中隨機地散點(扔掉掉在有效的UV殼內的地方)。一旦你的UV殼充滿了你想要的,你可以將你的UV點轉換爲barycentric coordinates將這些2-d點轉換回3-d點:實際上你說「我30%的頂點A,30%頂點B和頂點C的40%,所以我的位置是(.3A + .3B + .4C)

除了簡單之外,使用的另一個優點是UV貼圖可以讓您自定義密度和相對重要性網格的不同部分:較大的UV面會得到大量的散點,而較小的面則會更少 - 即使這與實際大小或面不匹配。因爲你可能無法拿出無拉伸和無縫的UV貼圖,所以你會得到變化因爲你的分散密度。但是對於許多應用來說,這很好,因爲算法非常簡單,並且結果易於手動調整。

我沒有使用過這一個,但這看起來像是基於這種一般方法:http://www.shanemarks.co.za/uncategorized/uv-scatter-script/

如果你需要一個更嚴格的數學方法,你需要的mesh parameterization票友方法:一種方法,把你的三維三角形收集成一個一致的空間。在該領域有許多有趣的工作,但如果不知道應用程序,就很難選擇特定的路徑。

+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方法更好