ここでは、まだ明示的に言及されていない手続き型生成への別のアプローチがあります。スプラインスキニングです。Hermiteスプラインのバージョンを使用できます(これは、位置と接線を補間する曲線を提供します)曲線を定義します。新しいセグメントを生成するときは、位置(大まかに前のセグメントの方向に、bcristが言うように)と方向(ほぼ同じ方向)を選択します方向-たとえば、前の方向の明確に定義された円錐内)、新しい位置+方向および以前の位置+方向を使用して、洞窟の新しい「背骨」を構築します。このバックボーンを取得したら、円筒形の構成でスキンを適用できます。たとえば、曲線に沿った10点の位置と接線を決定し、それらの位置/接線を使用して直交する「フレーム」を見つけ、これらのフレームを使用して円筒セグメントを構築します。これに関する小さな注意点は、洞窟も曲がることができないということです それ以外の場合は、自己交差の問題が発生する可能性があります。
編集:これはアルゴリズムの大まかな疑似コードの内訳です:
Parameters:
L = (average) segment length,
V = segment length variation,
R = cylinder radius,
T = segment angular variation
S = number of 'rings' per segment
Setup:
Choose an initial point P_0 and direction D_0 (for concreteness' sake, these can be
the origin and the X axis). Set P_prev and D_prev to these values.
Initialize u_prev to be the Y axis and v_prev to be the Y and Z axes.
(Note that (D_prev, u_prev, v_prev) form a mutually-orthogonal 'coordinate frame')
Generate a segment (do this as many times as you want):
{
Choose a (temporary) direction D within a cone of size T around the previous direction D_prev
Choose a segment length L_cur = at random from within the range [L-V, L+V].
Set the current terminal point P_cur to P_prev+D*L_cur - this is the position
we'll interpolate to
Set the current terminal direction D_cur to a direction chosen at random from
within a cone of size T around the previous direction. (There are good ways
of doing this - if you look back through gamedev.SE you should find some)
'Build' the Hermite spline H that goes from (P_prev, D_prev) to (P_cur, D_cur)
Now, skin that spline:
for ( i = 1; i <= S; i++ ) {
find the position P of the hermite spline H at t=i/S
find the direction D of the spline at t (this will be just the derivative)
'transport' the orthogonal frame to the new spot: for instance,
v_new = D x u_prev
u_new = v_new x D
(note that this keeps u_new, v_new close to their old values, and orthogonal
to each other and to D)
Use the previous and current frames and positions to build a cylindrical 'ring':
For theta from 0 to 2pi {
find the points (P+(u_new, v_new, D) * (cos theta, sin theta, 0))
and connect them to their counterparts from the previous ring
(note that that multiplication is a matrix-vector multiply)
}
update u_prev and v_prev to u_new and v_new
}
update the other prev variables to their 'new' values
}
これは明らかに非常に大まかな疑似コードです。不明な部分がある場合は、私に知らせて説明してみましょう。しかし、巨大なコードダンプだけでは、すべての詳細をカバーするのは難しいでしょう...