在three.js中将heightmap应用于SphereGeometry



[EDIT:请参阅此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循环中映射到平面的二维坐标。不幸的是,我并不是一个真正的三维数学专家,所以我在这一点上几乎陷入了困境。

应用于球体的heightmap示例和所有代码都放在这个jsfiddle中。更新后的jsfiddle显示了一个更改后的球体,但使用了随机数据而不是高度图数据。

我知道你可以扭曲球体的三维点来生成这些表面细节,但我想使用高度贴图。这个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可用于控制球体的大小及其上的高度图。

使用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/

如果要将2D贴图应用到3D球体曲面上,则需要使用球体的UV。幸运的是,默认情况下UV附带THREE.SphereGeometry

不过,UV是按面存储的,因此需要遍历faces阵列。

对于几何图形中的每个面:

  • 读取FaceVertexUvs阵列中每个关联顶点的相应UV值
  • 使用该UV位置读取高度贴图值
  • 将顶点沿顶点法线移动该值。faces数组提供顶点索引,您可以使用该索引到vertices数组中以获取/设置顶点位置

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

相关内容

  • 没有找到相关文章

最新更新