2

我想知道,从数学上讲,您将如何在 3D 表面上的随机位置生成 x 点,知道组成表面的三角形多边形的数量(它们的尺寸、位置、法线等)?您将分几步进行?

我正在尝试在 Maya 中创建一个“分散器”(使用 Python 和 API),但我什至不知道从概念方面开始。我应该先生成点,然后检查它们是否属于表面吗?我应该直接在表面上创建点(以及如何,在这种情况下)?

编辑:我想尽可能不使用 2D 投影或 UV 来实现这一点。

4

4 回答 4

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]

请注意,脊状或褶皱区域可能看起来具有较高的点密度,这仅仅是因为它们在较小的空间中具有较大的表面积。

于 2016-03-04T19:25:18.813 回答
2

如果约束是所有输出点都在曲面上,则您需要一种一致的方法来解决曲面本身,而不是担心点的 3d > 曲面转换。

hacktastic 的方法是为您的 3d 对象创建一个 UV 贴图,然后在 2 维中随机散布点(丢弃碰巧没有落在有效 UV 外壳内的点)。一旦你的 UV 壳被填满,你可以将你的 UV 点转换为重心坐标 ,以将这些 2-d 点转换回 3-d 点:实际上你说“我是 30% 顶点 A,30 % 顶点 B 和 40% 顶点 C,所以我的位置是 (.3A + .3B + .4C)

除了简单之外,使用 UV 贴图的另一个优点是它可以让您自定义网格不同部分的密度和相对重要性:较大的 UV 面会得到很多散点,而较小的面会更少——甚至如果这与物理尺寸或面部不匹配。

转到 2D 会引入一些伪影,因为您可能无法提出既无拉伸又无接缝的 UV 贴图,因此您会得到散射密度的变化。然而,对于许多应用程序来说,这会很好,因为算法非常简单,而且结果很容易手动调整。

我没有使用过这个,但这看起来像是基于这种通用方法:http ://www.shanemarks.co.za/uncategorized/uv-scatter-script/

如果您需要一种在数学上更严格的方法,则需要一种更高级的网格参数化方法:一种将三角形的 3-d 集合转换为一致空间的方法。该领域有很多有趣的工作,但在不了解应用程序的情况下很难选择特定的路径。

于 2016-03-04T18:17:18.453 回答
2
  1. 从随机三角形中选择 2 个随机边。
  2. 在边上创建 2 个随机点。
  3. 在它们之间创建新的随机点。

我丑陋的梅尔脚本:

//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法比较好

于 2016-03-09T21:47:09.130 回答
1

这是伪代码,可能是一个很好的起点:

  1. 让 N = 您正在使用的 3D 面的顶点数。
  2. 只需生成 N 个随机数,计算它们的总和,然后将每个随机数除以总和。现在你有 N 个随机数,其总和为 = 1.0。
  3. 使用上面的随机数,对您感兴趣的 3D 面的 3D 顶点进行线性组合。这应该会在面上为您提供一个随机的 3D 点。
  4. 重复直到你得到足够的没有。3D 面上的随机点。
于 2016-03-04T16:22:26.510 回答