如何纹理球体的不规则平面?

Posted

技术标签:

【中文标题】如何纹理球体的不规则平面?【英文标题】:How to texture the irregular Planes of a Sphere? 【发布时间】:2012-08-11 08:21:10 【问题描述】:

我想为 THREE.js 球体的每个面赋予它自己的纹理。所以我让 SphereGeometry 计算顶点并使用面的顶点将每个面转换为 PlaneGeometry。

THREE.SpherePlaneGeometry = function ( v1, v2, v3, v4 ) 

  THREE.Geometry.call( this );

  var normal = new THREE.Vector3( 0, 1, 0 );

  this.vertices.push( v1.clone() );
  this.vertices.push( v2.clone() );
  this.vertices.push( v3.clone() );
  this.vertices.push( v4.clone() );

  var face = new THREE.Face4( 0, 1, 2, 3 );

  face.normal.copy( normal );
  face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );

  this.faces.push( face );

  var uvs = [
    new THREE.UV( 1.0, 0.0 ),
    new THREE.UV( 0.0, 0.0 ),
    new THREE.UV( 0.0, 1.0 ),
    new THREE.UV( 1.0, 1.0 ),
  ];
  this.faceVertexUvs[ 0 ].push( uvs );

;

确保所有这些都在稍后使用返回的几何图形运行:

geometry.computeCentroids();
geometry.computeFaceNormals();
geometry.verticesNeedUpdate = true;
geometry.uvsNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.tangentsNeedUpdate = true;
geometry.elementsNeedUpdate = true;
geometry.dynamic = true;

通过应用这个纹理:

我得到了这个结果:

可以做些什么来消除红点和绿点之间的失真?对于极点,一个顶点被使用了两次,但它可能会更好,知道吗?

【问题讨论】:

看起来这是一个类似的问题:***.com/questions/6046929/…,更一般的是:如何纹理投影的四边形?但是,有没有使用 THREE.js 的解决方案? 正如 noiv 所说,似乎顶部四边形的三角测量错误,我建议为每个四边形制作一个中间点并制作 4 个三角形,然后尝试使用纹理......甚至可以使用 u ,v 的 phi 和 delta 覆盖整个球体并使用某种重复因子... @EliSherer,overtesselation 可以解决这个问题,但多边形数量应该保持不变。另一种称为投影插值的方法被排除在外,因为它将问题移动到四边形的边缘:reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1 【参考方案1】:

这是一个棘手的问题。我们的纹理映射仍然是仿射的。

在某些时候,我们需要尝试使用透视正确的纹理映射。我在某处读过一些关于插入 w... 但我不确定这是否能解决您的问题。

为了简化问题...查看纹理映射图像中的仿射映射四边形。想象一下,您将左上角的顶点移动到右上角。通过这样做,您基本上将左三角形变成了一条从左下角到右上角的简单线。这基本上意味着你不会看到它。因为直角三角形的顶点没有移动,所以三角形仍然存在,可见,每个顶点都分配了 UV。

所以我能想到的唯一解决方案是:

    为这些多边形添加一层细分。 针对这些可能的情况使用特殊的预校正纹理(使用画布或 Photoshop)。

【讨论】:

我不确定是否是同一个问题。也许它会产生相同的解决方案,或者我需要两者的解决方案。但是我在投影时没有扭曲的矩形,它是一个梯形。我发现这个描述很有用:xyzw.us/~cass/qcoord。但是,我不知道从哪里开始执行此收据:“这很好,因为不是将上顶点的纹理坐标指定为 (0, 1) 和 (1, 1) 的 (s,t) 坐标,我们可以将它们指定为 (0, width, 0, width) 和 (width, width, 0, width) 的 (s,t,r,q) 坐标!”听起来真的很简单。【参考方案2】:

这里有几个问题。

首先,您不需要将几何体的每个面都转换为平面几何体——除非出于某种原因您想要这样做。您可以在下面的 Fiddles 中了解如何处理此问题。

其次,你的问题是你的紫外线设置。

这是一个 Fiddle (http://jsfiddle.net/PBjEE/),显示了与您类似的问题。我使用了更简单的几何形状,但和你的一样,四边形面是梯形。在小提琴中,我按照你的方法将每个面的 UV 设置为纹理的角,(0,1)、(0,0)、(1,0) 和 (1,1)。结果是一个扭曲的圆圈。

这是另一个 Fiddle (http://jsfiddle.net/PBjEE/1/),通过更改 UV 坐标来消除失真。

UV 坐标必须定义一个与人脸比例相同的梯形。

【讨论】:

啊。现在我明白他用梯形指的是什么。我的眼睛完全忽略了这种失真,而是专注于顶部的三角形:P 圆圈很好,但纹理被裁剪:jsfiddle.net/noiv/3Spe3。不能这样做,例如谷歌地图瓷砖。 mts1.google.com/vt/lyrs=m@183042665&x=129&y=95&z=8 公平地说,您的问题是“可以做些什么来消除失真?”这是解决该问题的方法。看来您现在正在添加新要求。或许你可以发个新帖子? 保持纹理完整并不是一个隐藏的要求。但我会准备一个更好的小提琴并重新发布。顺便说一句:你的小提琴已经揭示了下一个问题:如何设置灯光?

以上是关于如何纹理球体的不规则平面?的主要内容,如果未能解决你的问题,请参考以下文章

构建GIS地图常用知识

如何裁剪任意形状的纹理?

如何使用点图元将纹理映射到由参数方程渲染的球体

SceneKit 节点的交集

C++ openGl 纹理将图像映射到球体上

如何在 PyQt5 QOpenGLWidget 中对球体进行纹理处理