将heightmap应用于three.js中的SphereGeometry

时间:2013-08-21 16:53:24

标签: javascript html5-canvas three.js webgl procedural-generation

[编辑:见this jsfiddle for a live example plus accompanying code]

使用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可用于控制球体的大小和球体上的高度图。

2 个答案:

答案 0 :(得分:1)

使用vector3移动每个顶点:

SELECT "tasks".* FROM "tasks" INNER JOIN "user_lists" ON "tasks"."user_list_id" = "user_lists"."id" WHERE "user_lists"."user_id" = ?  [["user_id", 1]]

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

答案 1 :(得分:0)

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

虽然UV是按面存储的,但您需要遍历faces数组。

对于几何中的每个面:

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

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