2016-03-04 131 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方法更好