2

私は最近、Minecraft 内の実際の高さマップに基づいて地球を生成したいので、バイキュービック補間をいじっています。補間を使用する理由は、世界をより詳細にしたいからです。いろいろ調べて、試行錯誤した結果、こちらにお願いすることにしました。:)

メモリが限られているため、起動時にイメージをスケーリングできず、ロードしたままにしておく必要があります。その場で補間を行う必要があります。

ここで見られるように、Cubic Interpolation が機能しているよう です 。テスト目的で、小さな画像を使用して 4 倍にスケーリングしています。これがコードの動作です:入力 -> 出力

これは私の現在のコードです:

 public static double cubicInterpolate(double[] points, double x, double scale)
{
    x /= scale;

    double inBetweenPoint = x;
    int xInHeightmap = (int) x;
    inBetweenPoint -= xInHeightmap;

    double beforePoint1 = safe(points, xInHeightmap - 1);
    double point1 = safe(points, xInHeightmap);
    double point2 = safe(points, xInHeightmap + 1);
    double afterPoint2 = safe(points, xInHeightmap + 2);

    double p = (afterPoint2 - point2) - (beforePoint1 - point1);
    double q = (beforePoint1 - point1) - p;
    double r = point2 - beforePoint1;
    double s = point1;

    return (p * Math.pow(inBetweenPoint, 3)) + (q * Math.pow(inBetweenPoint, 2)) + (r * inBetweenPoint) + s;
}

public static double bicubicInterpolate(double[][] points, double x, double y, double scale)
{
    x /= scale;

    double inBetweenPoint = x;
    int xInHeightmap = (int) x;
    inBetweenPoint -= xInHeightmap;

    double beforePoint1 = cubicInterpolate(safe(points, xInHeightmap - 1), y, scale);
    double point1 = cubicInterpolate(safe(points, xInHeightmap), y, scale);
    double point2 = cubicInterpolate(safe(points, xInHeightmap + 1), y, scale);
    double afterPoint2 = cubicInterpolate(safe(points, xInHeightmap + 2), y, scale);

    return cubicInterpolate(new double[]{beforePoint1, point1, point2, afterPoint2}, inBetweenPoint + 1, scale);
}

public static double[] safe(double[][] p, int i)
{
    return p[Math.max(0, Math.min(i, p.length - 1))];
}

public static double safe(double[] p, int i)
{
    return p[Math.max(0, Math.min(i, p.length - 1))];
}

ご協力ありがとうございました :)

4

2 に答える 2

3

私の理解では、あなたの実装は与えられたものxy座標をまったく異なる方法で扱い、それは望ましい結果につながりません。基本的に次のことを行う必要があります。

まず、補間の基礎となるグリッド内の 4 つのポイント (座標ペア) と、グリッドから補間までの両方向の距離を特定する必要があります。これは次のように行うことができます。

int xfloor = (int)x;
int yfloor = (int)y;
int xdelta = x - (double)xfloor;
int ydelta = y - (double)yfloor;

目的の座標ペアは、(軸の向きに応じて)

P1 = (xfloor,     yfloor    ) // left upper corner
P2 = (xfloor,     yfloor + 1) // left lower corner
P3 = (xfloor + 1 ,yfloor + 1) // right lower corner
P4 = (xfloor + 1, yfloor    ) // left upper corner

そして最後に、最初に平行軸に沿って補間し、次に中間で補間します。これは、中間値を使用して次のように実行できます。

val1 = cubic(value(P1), value(P2), deltay) // interpolate cubically on the left edge
val2 = cubic(value(P4), value(P3), deltay) // interpolate cubically on the right edge
val = cubic (val1, val2, deltax) // interpolate cubically between the intermediates

ここでは、補間方法についても説明します

于 2015-12-01T12:28:16.933 に答える