[编辑:请参见此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可以用于控制球体的大小和其上的高度图。