在three.js中将高度图应用到SphereGeometry

4

[编辑:请参见此jsfiddle以获取实时示例和相关代码]

我正在使用three.js尝试渲染出一些具有突出特征的天体。

不幸的是,threejs没有提供如何应用球形高度图的示例,但他们有一个示例,在其中将高度图应用于平面。

我采用了该示例,并将其修改为使用SphereGeometry();而不是PlaneGeometry();

显然,球体的几何形状与平面的几何形状有很大的区别,当渲染结果时,球体显示为平坦的纹理。

平面高度图代码:

var plane = new THREE.PlaneGeometry( 2000, 2000, quality - 1, quality - 1 );
plane.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
for ( var i = 0, l = plane.vertices.length; i < l; i ++ ) {
    var x = i % quality, y = ~~ ( i / quality );
    plane.vertices[ i ].y = data[ ( x * step ) + ( y * step ) * 1024 ] * 2 - 128;
}

现在我猜解决方案相对简单:在for循环中不再映射到平面的2D坐标,而是要找到3D空间中球体的表面坐标。不幸的是,我不是很擅长3D数学,所以我现在卡住了。
高度图应用于球体的示例和所有代码都放在this jsfiddle中。更新的jsfiddle展示了一个修改过的球体,但数据是随机的而不是高度图数据。
我知道你可以扭曲球体的3D点来生成这些表面细节,但我想使用高度图来做到这一点。这个JSFiddle是我做到的最远的地方-它会随机改变点,使球体看起来像岩石,但显然不太自然。
编辑:下面是我希望实现的逻辑,将高度图数据映射到球体上。
为了将数据映射到球面上,我们需要将简单的球形坐标系(经度φ、纬度θ、半径r)的坐标映射到笛卡尔坐标系(x、y、z)。就像在普通的高度映射中,(x, y) 处的数据值被映射到 z,我们将 (φ, θ) 处的值映射到 r。这个转换可以表示为:
x = r × cos φ × sin θ

y = r × sin φ × sin θ

z = r × cos θ

r = Rdefault + Rscale × d(φ, θ) 

参数Rdefault和Rscale可以用于控制球体的大小和其上的高度图。

你可以使用反引号将代码括起来,从而创建内联代码段。这样,您就不需要单独的行来命名一个函数。 - Adi Inbar
你能展示一下你的实时例子,然后提出一个具体的问题吗? - WestLangley
2个回答

1
使用Vector3移动每个顶点:
  var vector = new THREE.Vector3()
  vector.set(geometry.vertices[i].x, geometry.vertices[i].y, geometry.vertices[i].z);
  vector.setLength(h);
  geometry.vertices[i].x = vector.x;
  geometry.vertices[i].y = vector.y;
  geometry.vertices[i].z = vector.z;

示例:http://jsfiddle.net/damienlabat/b3or4up3/


0

如果您想将2D地图应用到3D球体表面上,您需要使用球体的UV。幸运的是,THREE.SphereGeometry默认带有UV。

然而,UV是按面存储的,因此您需要遍历faces数组。

对于几何体中的每个面:

  • 读取每个相关顶点在FaceVertexUvs数组中对应的UV值。
  • 使用该UV位置读取高度图值。
  • 沿着顶点法线将顶点移动该值。 faces数组给出了顶点索引,您可以使用它来索引vertices数组以获取/设置顶点位置。

完成所有操作后,将verticesNeedUpdate设置为true以更新顶点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接