【问题标题】:Programmatically generate simple UV Mapping for models以编程方式为模型生成简单的 UV 映射
【发布时间】:2016-04-29 17:22:55
【问题描述】:

来自this 问题我正在尝试使用 Three.js 为某些模型以编程方式生成 UV 映射,我需要这个,因为我的模型也是以编程方式生成的,我需要对它们应用简单的纹理。我已经阅读了here 并成功地为一些简单的 3D 文本生成了 UV 映射,但是当将相同的映射应用于更复杂的模型时它就不起作用了。

我尝试应用的纹理是这样的:

黑色背景在 PNG 图像中只是透明的。我需要将其应用于我的模型,它只是一种闪光效果,所以我不关心模型中的确切位置,有什么方法可以为这种情况以编程方式创建一个简单的 UV 贴图吗?

我正在使用来自链接问题的代码,该代码对平面模型非常有用,但不适用于非平面模型:

assignUVs = function( geometry ){

    geometry.computeBoundingBox();

    var max     = geometry.boundingBox.max;
    var min     = geometry.boundingBox.min;

    var offset  = new THREE.Vector2(0 - min.x, 0 - min.y);
    var range   = new THREE.Vector2(max.x - min.x, max.y - min.y);

    geometry.faceVertexUvs[0] = [];
    var faces = geometry.faces;

    for (i = 0; i < geometry.faces.length ; i++) {

      var v1 = geometry.vertices[faces[i].a];
      var v2 = geometry.vertices[faces[i].b];
      var v3 = geometry.vertices[faces[i].c];

      geometry.faceVertexUvs[0].push([
        new THREE.Vector2( ( v1.x + offset.x ) / range.x , ( v1.y + offset.y ) / range.y ),
        new THREE.Vector2( ( v2.x + offset.x ) / range.x , ( v2.y + offset.y ) / range.y ),
        new THREE.Vector2( ( v3.x + offset.x ) / range.x , ( v3.y + offset.y ) / range.y )
      ]);

    }

    geometry.uvsNeedUpdate = true;
}

【问题讨论】:

  • 如果只是一个闪光效果,是不是只创建一个着色器会更好?类似THIS

标签: three.js uv-mapping


【解决方案1】:

您需要更具体。在这里,我将以编程方式应用 UV 映射

for (i = 0; i < geometry.faces.length ; i++) {
   geometry.faceVertexUvs[0].push([
     new THREE.Vector2( 0, 0 ),
     new THREE.Vector2( 0, 0 ),
     new THREE.Vector2( 0, 0 ),
   ]);
}

开心吗?

有无数种应用 UV 坐标的方法。这个怎么样

for (i = 0; i < geometry.faces.length ; i++) {
   geometry.faceVertexUvs[0].push([
     new THREE.Vector2( Math.random(), Math.random() ),
     new THREE.Vector2( Math.random(), Math.random() ),
     new THREE.Vector2( Math.random(), Math.random() ),
   ]);
}

没有正确答案。只是你想做什么取决于你。这有点像问我如何在纸上使用铅笔。

很抱歉这么刻薄,只是指出问题在某种意义上是荒谬的。

不管怎样,应用纹理有一些常用的方法。

  • 球面映射

    假设您的模型是半透明的,里面有一个由薄膜制成的球体,球体内部是点光源,因此它从球体向各个方向投射(就像电影放映机一样)。因此,您可以通过数学计算出适合该情况的正确 UV

    要在球体上获得一个点,请将您的点乘以球体世界矩阵的倒数,然后对结果进行归一化。在那之后,仍然存在纹理本身如何映射到虚构球体的问题,而这又有无数种方法。

    我猜最简单的方法是mercator projection,这是世界上大多数二维地图的工作方式。他们的问题是在北极和南极浪费了大量空间。假设x,y,z是上一段提到的归一化坐标那么

    U = Math.atan2(z, x) / Math.PI * 0.5 - 0.5;
    V = 0.5 - Math.asin(y) / Math.PI;
    
  • 投影映射

    这就像一部电影。您有一个从一个点投影的 2d 图像。想象一下,您将电影放映机(或投影电视)指向椅子。计算这些点

    计算这些点与根据几乎所有 WebGL 应用程序所做的 3D 数据计算 2D 图像完全一样。通常他们的顶点着色器中有一条这样的线

    gl_Position = matrix * position;
    

    在哪里matrix = worldViewProjection。然后你可以做

    clipSpace = gl_Position.xy / gl_Position.w
    

    您现在拥有从 -1 到 +1 的 x,y 值。然后你转换它们 UV 坐标为 0 到 1

    uv = clipSpace * 0.5 + 0.5;
    

    当然,通常你会在 JavaScript 的初始化时计算 UV 坐标,但概念是一样的。

  • 平面映射

    这与投影映射几乎相同,只是假设投影仪不是一个点,而是与您要投影的大小相同。换句话说,使用投影映射,当您将模型移近投影仪时,被投影的图片会变小,但使用平面则不会。

    按照投影映射示例,这里唯一的区别是使用正交投影而不是透视投影。

  • 立方体映射?

    这实际上是来自 6 个方向的平面映射。由你决定 决定哪个 UV 坐标得到 6 个平面中的哪个。我猜 大多数时候你会取三角形的法线来看看哪个 平面它的大部分面,然后从该平面进行平面映射。

    实际上,我可能把我的条款搞混了。你也可以做 真正的立方体贴图,你有一个立方体纹理,但这需要 U,V,W 而不仅仅是 U,V。为此,它与球体相同 示例,除非您直接使用归一化坐标作为 U,V,W。

  • 圆柱映射

    这类似于球体映射,只是假设有一个小圆柱体投射到您的模型上。与球体不同,圆柱体具有方向,但基本上您可以将模型的点移动到圆柱体的方向,然后假设 x,y,z 现在相对于圆柱体(换句话说,您将它们乘以矩阵的逆矩阵表示圆柱体的方向),然后。

    U = Math.atan2(x, z) / Math.PI * 0.5 + 0.5
    V = y
    

另外 2 个解决方案

  1. 也许你想要环境映射?

    Here's 1 exampleHere's another

  2. 也许您应该考虑使用内置 UV editors 和 UV 投影仪的建模包,例如 Maya 或 Blender。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-28
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2010-12-27
    • 1970-01-01
    相关资源
    最近更新 更多