단조 비 감소 노이즈 기능이 있습니까?


10

시간이 지남에 따라 A 지점에서 B 지점으로 이동하는 객체에 애니메이션을 적용하여 일정 시간에 B에 도달하지만 언제든지 위치가 연속적으로 무작위로 교란되지만 결코 뒤지지 않습니다. 객체는 직선을 따라 이동하므로 하나의 치수 만 필요합니다.

수학적으로 이것은 연속 f (x), x ∈ [0,1]을 찾고 있음을 의미합니다.

  • f (0) = 0
  • f (1) = 1
  • x <y → f (x) ≤ f (y)
  • "가장"지점에서 f (x + d)-f (x)는 d와 명백한 관계가 없습니다. (함수는 균일하게 증가하거나 예측할 수 없습니다. 미분의 정도가 일정하지 않다고 말하는 것과 같습니다.)

이상적으로는 실제로 일부 기능을 사용하여 일부 시드 상태를 제공하는 방법을 원합니다. 현재 사용하려면 최소 4 비트의 시드 (16 가지 기능)가 필요하지만 더 이상 자유롭게 제공 할 수는 없기 때문에.

누적 오류와 관련된 다양한 문제를 피하려면 내부 상태가 필요 없는 기능을 선호합니다 . 즉, 프로그래밍 "기능"이 아닌 실제 기능이되기를 원합니다.


3
세 번째 및 네 번째 요구 사항은로 추정 할 수 있으므로 f'(x)>0모든 노이즈 함수의 절대 값의 정규화 된 통합은 모든 요구 사항을 충족시킵니다. 불행히도 나는 그것을 계산하는 쉬운 방법을 모르지만 다른 누군가가 할 수 있습니다. :)
SkimFlux

함수의 직각 경사 작업의 수직을 교란 시키는가?
kaoD

"누적 오류와 관련된 다양한 문제를 피하기 위해"라고 말하면 정밀도에 대해 걱정하는 것 같습니다. 많은 의견을 바탕으로 지나치게 많은 평가의 성능 비용이 우려되는 것 같습니다. 우리는 어떤 성능 및 메모리 제약 조건을 정확하게 설명해야합니다-어쨌든 축적 오류가없는 상태로 함수를 구성 할 수 있기 때문에 요구 사항은 도움이되지 않습니다 (무엇을 의미합니까?). 또한 네 번째 요점이 잘못되었습니다. 사소한 예 : e ^ x의 파생물이 일정하지 않으므로 그렇게 말하는 것과 동등하지 않습니다.
Superbest

답변:


4

이 게시물의 경우, y = f (t) 여기서 t는 변경하는 매개 변수 (시간 / 진행)이고 y는 목표까지의 거리입니다. 가로축이 시간 / 진행이고 세로가 거리 인 2D 플롯에서 점으로 설명하겠습니다.

첫 번째 점이 (0, 1)이고 네 번째 (마지막) 점이 (1, 0) 인 입방 베 지어 곡선을 만들 수 있다고 생각합니다. 이 1x1 사각형 내에 두 개의 중간 점을 임의로 배치 할 수 있습니다 (x = rand, y = rand). 나는 이것을 분석적으로 확인할 수는 없지만 애플릿으로 놀아서 (예, 계속 웃어 라) 베 지어 곡선은 그런 제약으로 결코 줄어들지 않는 것 같습니다.

이것은 포인트 p1에서 포인트 p2까지 비 감소 경로를 제공하는 기본 함수 b (p1, p2)가됩니다.

이제 ab (p (1) = (0, 1), p (n) = (1, 0))을 생성 하고이 곡선을 따라 p (i)의 수를 1과 같이 선택할 수 있습니다

기본적으로 하나의 "일반"경로를 생성 한 후이를 세그먼트로 나누고 각 세그먼트를 재생성합니다.

수학 함수가 필요하기 때문에 : 위의 절차가 하나의 함수 y = f (t, s)로 패키지되어 시드 함수의 t 거리를 제공한다고 가정합니다. 필요할 것이예요:

  • 메인 베 지어 스플라인의 중간 지점 2 개를 배치하기위한 4 개의 난수 ((0, 1)에서 (1, 0)까지)
  • n 개의 세그먼트가있는 경우 각 세그먼트의 경계에 대한 n-1 숫자 (첫 번째 세그먼트는 항상 (0, 1)에서 시작합니다. 즉 t = 0이고 마지막은 (1,0)에서 끝납니다. 즉 t = 1)
  • 세그먼트 수를 랜덤 화하려는 경우 1 개
  • 당신의 t가 도달하는 세그먼트의 스플라인의 중간 지점을 배치하기위한 4 개의 숫자

따라서 각 시드는 다음 중 하나를 제공해야합니다.

  • 0과 1 사이의 7 + n 실수 (세그먼트 수를 제어하려는 경우)
  • 실수 7 개 및 1보다 큰 정수 1 (임의의 세그먼트 수)

시드로 숫자 배열을 제공하여 이들 중 하나를 수행 할 수 있다고 생각합니다. 또는 하나의 숫자 s를 시드로 제공 한 다음 rand (s), rand (s + 1), rand (s + 2) 등으로 내장 난수 생성기를 호출하거나 그런 다음 rand.NextNumber를 계속 호출하십시오.

전체 함수 f (t, s)가 많은 세그먼트로 구성되어 있지만 각 t에 대해 하나의 세그먼트 만 평가한다는 점에 유의하십시오. 당신은 것입니다 당신이 없는지를 두 개의 세그먼트가 겹치는 있도록으로 정렬해야하기 때문에, 반복이 방법으로 세그먼트의 경계를 계산해야합니다. 아마도이 여분의 작업을 최적화하고 제거하고 각 호출마다 하나의 세그먼트의 끝점 만 찾을 수는 있지만 지금 당장은 분명하지 않습니다.

또한 베 지어 곡선은 필요하지 않으며 적절하게 동작하는 스플라인이 수행합니다.

샘플 Matlab 구현을 만들었습니다.

베 지어 기능 (벡터화) :

function p = bezier(t, points)
% p = bezier(t, points) takes 4 2-dimensional points defined by 2-by-4 matrix
% points and gives the value of the Bezier curve between these points at t.
% 
% t can be a number or 1-by-n vector. p will be an n-by-2 matrix.
    coeffs = [
        (1-t').^3, ...
        3*(1-t').^2.*t', ...
        3*(1-t').*t'.^2, ...
        t'.^3
    ];

    p = coeffs * points;
end

위에서 설명한 복합 베 지어 기능 (각 호출마다 얼마나 많은 평가가 필요한지 명확하게 알 수 있도록 벡터화되지 않은 상태로 남음) :

function p = bezier_compound(t, ends, s)
% p = bezier(t, points) takes 2 2-dimensional endpoints defined by a 2-by-2
% matrix ends and gives the value of a "compound" Bezier curve between
% these points at t.
% 
% t can be a number or 1-by-n vector. s must be a 1-by-7+m vector of random
% numbers from 0 to 1. p will be an n-by-2 matrix. 
    %% Generate a list of segment boundaries
    seg_bounds = [0, sort(s(9:end)), 1];

    %% Find which segment t falls on
    seg = find(seg_bounds(1:end-1)<=t, 1, 'last');

    %% Find the points that segment boundaries evaluate to
    points(1, :) = ends(1, :);
    points(2, :) = [s(1), s(2)];
    points(3, :) = [s(3), s(4)];
    points(4, :) = ends(2, :);

    p1 = bezier(seg_bounds(seg), points);
    p4 = bezier(seg_bounds(seg+1), points);

    %% Random middle points
    p2 = [s(5), s(6)] .* (p4-p1) + p1;
    p3 = [s(7), s(8)] .* (p4-p1) + p1;

    %% Gather together these points
    p_seg = [p1; p2; p3; p4];

    %% Find what part of this segment t falls on
    t_seg = (t-seg_bounds(seg))/(seg_bounds(seg+1)-seg_bounds(seg));

    %% Evaluate
    p = bezier(t_seg, p_seg);    
end

임의의 시드에 대한 함수를 표시하는 스크립트 (이것은 임의의 함수가 호출되는 유일한 장소이며 다른 모든 코드에 대한 임의의 변수는이 하나의 임의의 배열에서 전파됨)에 유의하십시오.

clear
clc

% How many samples of the function to plot (higher = higher resolution)
points = 1000;

ends = [
    0, 0;
    1, 1;
    ];

% a row vector of 12 random points
r = rand(1, 12);

p = zeros(points, 2);

for i=0:points-1
    t = i/points;
    p(i+1, :) = bezier_compound(t, ends, r);
end

% We take a 1-p to invert along y-axis here because it was easier to
% implement a function for slowly moving away from a point towards another.
scatter(p(:, 1), 1-p(:, 2), '.');
xlabel('Time');
ylabel('Distance to target');

다음은 샘플 출력입니다.

여기에 이미지 설명을 입력하십시오

대부분의 기준을 충족하는 것 같습니다. 하나:

  • "코너"가 있습니다. 베 지어 곡선을보다 적절하게 사용하면이 기능을 사용할 수 있습니다.
  • "분명히"스플라인처럼 보이지만 종자를 알지 못하면 사소한 시간이 지나면 어떻게 될지 추측 할 수 없습니다.
  • 구석쪽으로 너무 많이 벗어나는 경우는 거의 없습니다 (시드 생성기의 분포로 재생하여 고정 할 수 있음).
  • 3 차 베 지어 기능은 이러한 구속 조건이 주어지면 모퉁이 근처 영역에 도달 할 수 없습니다.

1

펄린 노이즈의 도트 제품과 같이 변환 된 코사인을 혼합하는 대신 f (x) = x 또는 2x와 같이 f (0) = 0에서 시작하는 여러 단조 함수를 혼합 할 수 있다고 생각합니다. 또는 x ^ 2 등입니다. 실제로 도메인이 0 => 1로 제한되어 있기 때문에 cos (90 * x + 270)와 같이 해당 도메인 내의 계산서에 맞는 삼각 함수를 혼합 할 수도 있습니다. 1에서 끝나도록 방법을 정규화하려면 f (0) = 0에서 시작하여 f (1)로 시작하는 이러한 단조로운 방법의 가중치 합계를 간단히 나눌 수 있습니다. 이와 같은 것은 반전하기가 상당히 쉬워야합니다 (스테이트리스 실제 함수 대 프로그래밍 함수에 관한 비트에서 원하는 것을 모았습니다).

도움이 되었기를 바랍니다.


1

이 조잡한 그림을 분석 할 여기에 이미지 설명을 입력하십시오 수 있습니다 균일 한 랜드 기능을 사용하여 애니메이션을 즉석에서 수행하는 기능으로 끝날 수 있습니다. 나는 이것이 정확한 수학 공식이 아니라는 것을 알고 있지만 실제로는 임의 함수에 대한 수학 공식이 없으며, 함수가 있더라도 이것을 달성하기 위해 많은 코딩을하고있을 것입니다. 평활도 조건을 지정하지 않은 경우 속도 프로파일은 $ C ^ 0 $ 연속입니다 (로봇을 다루지 않기 때문에 불연속 가속 프로파일에 대해 걱정할 필요가 없습니다).


"실제로 임의 함수에 대한 수학 공식은 없습니다"임의 함수가 아니라 노이즈 함수를 원합니다. 노이즈 기능은 존재하는 것으로 잘 문서화되어 있습니다. 이와 같은 부분 정의는 또한 비 효율성 (오래 시간 척도를 가질 때 문제가되는 O (조각이 됨)로 평가), 불순한 기능 (O (1)으로 평가되지만 이전 위치를 유지해야 함) 또는 가능한 기능을 제한하십시오 (예 : 모든 변곡점이 고정 간격으로).

흠, 죄송합니다. 노이즈 함수는 난수 생성기 절차를 사용하며 모양을 만들기 위해 별도의 가이드 / 키 포인트 세트에 의존한다고 생각했습니다 (Perlin Noise가 언급 된 것을 보았습니다. 통합하기가 매우 어렵 기 때문에 분석 솔루션이 없습니다). 노이즈 기능을 분석적으로 통합 할 수 있습니까? 이들 중 하나가 후보가 될 수 있는지 궁금 링크
teodron

예를 들어, Perlin 노이즈는 255 8 비트 숫자의 시드 상태를 취하지 만 그로부터 3 차원으로 무한 거리에서 랜덤 노이즈를 생성합니다. 그것들을 "가이드 포인트"로 묘사하는 것은 실제로 정확하지 않습니다. 수학적으로 그들은 당신이 계속 제공하고 싶지 않은 또 다른 256 개의 매개 변수와 같습니다. 당신이 말했듯이 그것은 본질적으로 통합 할 수는 없지만 순수한 기능입니다. 귀하가 링크 한 페이지는 Perlin 노이즈에 대한 나쁜 설명입니다 (실제로 Perlin 노이즈는 아닙니다). 어떤 종류의 소음 기능이 가능한지 여부 는 문제입니다. 그렇지 않습니까?

1

[0,1]에서 증가하는 N 개의 난수 시퀀스를 생성하는 일반적인 방법은 임의의 범위에서 N 개의 난수를 생성 한 다음 총합으로 나눈 다음 한 번에 하나씩 합산하여 순서.

시퀀스 2, 2, 5, 8, 6을 생성하십시오.
그들의 합은 23이므로 합산하는 숫자는 2/23, 2/23, 5/23, 8/23 및 6/23입니다.
마지막 순서는 2/23, 4/23, 9/23, 17/23, 23/23입니다.

X와 Y 모두에 대해 이러한 값을 생성하여 2D로 확장 할 수 있습니다. N을 늘려 원하는 세분성을 얻을 수 있습니다.


@teodron의 비슷한 대답에서, 당신은 큰 시간 척도로 효율성 문제를 인용했습니다. 현재 직면하고있는 실제 문제를 알지 못하면 해당 문제가 유효한지 알 수 없습니다. 그러나 또 다른 옵션은 작은 N에 대해 생성 하고 결과를 부드럽게하는 것입니다. 응용 프로그램에 따라 실제로 더 나은 결과를 얻을 수 있습니다.

여기에 이미지 설명을 입력하십시오
N = 100, 스무딩 없음

여기에 이미지 설명을 입력하십시오
평활화와 함께 N = 15


스무딩을 위해 무엇을하든 결과가 함수 (약 x = 0.95)조차 만들지 않은 것 같습니다. 그것이 그래프 프로그램의 인공물인지 실수인지 확실하지 않습니다. 단 조성은 또한 약 0.7을 위반 한 것으로 보입니다. 어쨌든, 나는 "통상적 인 방법"에 익숙하다 – 나는 일반적인 방법이 엉터리라고 의심하기 때문에이 질문을하고있다. Pre-Perlin-noise는 결국 가치 노이즈의 거대한 LUT에 문제가 없었습니다. 그것은 단지 "일반적인 방법"이었습니다. 오늘날 우리는 훨씬 더 유연 하고 효율적인 방법을 가지고 있습니다.

3
BlueRaja에 동의합니다 : 예제에 관계없이 단 조성을 위반하지 않고 잘 알려진, 구현하기 쉬운 스무딩 방법이 있습니다. 예를 들어 이동 평균 또는 그리기 스플라인. 그러나 @JoeWreschnig 문제는 관련이 없습니다. 게임 규칙과 메카닉은 기능을 후퇴하지 않는 객체에 따라 달라질 수 있습니다. 요구자는 실제로 자신이 필요로하는 것을 필요로하지 않는다고 가정하는 것은 거의 좋은 생각이 아닙니다.
Superbest

1
@BlueRaja : 이와 같은 부분적인 접근 방식에 대한 기본적인 불만은 teodrone에 대한 응답으로 설명됩니다. "가장 견고하고 수학적으로 정확한 결과"를 찾는 것이 아니라 이전에 우리에게 알려지지 않은 수학 도구를 사용하여 새로운 가능성을 여는 것입니다. 다시 말하지만, 거대 가치 노이즈 LUT와 Perlin 노이즈의 비유를 고려하십시오. 이 사이트의 모든 질문에 지능형 CS 언더 그레이드가 강의 사이에 튀어 나올 수있는 "충분히 좋은"답변이 필요한 것은 아닙니다. 때로는 독창적이고 전문적인 일을 위해 쏴 보자.

1
또는이 사이트를 계속해서 변환 매트릭스에 대해 90 %의 초등적인 혼란에 빠뜨릴 수있었습니다. 10 %는 "게임을 중단하도록 도와줍니다!" 그것은 모든 전문가가 좋아할 멋진 Q & A 사이트를 만들 것입니다.

2
@Joe : 음. 당신은 당신의 기준에 맞는 해결책을 요청했습니다. 단순하기 때문에 나쁘지 않습니다.
BlueRaja-대니 Pflughoeft

1

이 구현은 프랙탈 노이즈에서 발견되는 옥타브의 합계에서 영감을 얻었으며 여기저기서 저렴한 엉덩이가 섞여 있습니다. 나는 그것이 빠르고 빠르며 약 정밀도의 손실로 매개 변수에 저장된 것보다 적은 옥타브를 요구하여 조정할 수 있다고 생각합니다 1/2^octave.

O (log (pieces)) 시간 만 필요한 부분 별 구현으로 볼 수 있습니다 . 파라미터 배열은 분할 및 정복 피벗 위치와 피벗에 도달 할 때 이동 한 거리 모두에 사용됩니다.

template<int N> struct Trajectory
{
    Trajectory(int seed = 0)
    {
        /* The behaviour can be tuned by changing 0.2 and 0.6 below. */
        if (seed)
            srand(seed);
        for (int i = 0; i < N; i++)
            m_params[i] = 0.2 + 0.6 * (double)(rand() % 4096) / 4096;
    }

    double Get(double t, int depth = N)
    {
        double min = 0.0, max = 1.0;
        for (int i = 0, dir = 0; i < N && i < depth; i++)
        {
            int j = (dir + 1 + i) % N;
            double mid = min + (max - min) * m_params[j];
            if (t < m_params[i])
            {
                dir += 1;
                t = t / m_params[i];
                max = mid;
            }
            else
            {
                dir ^= i;
                t = (t - m_params[i]) / (1.0 - m_params[i]);
                min = mid;
            }
        }
        t = (3.0 - 2.0 * t) * t * t; // Optional smoothing
        return min + (max - min) * t;
    }

    double m_params[N];
};

3 배 많은 정보를 저장하는 비용으로 부동 소수점 분할을 사전 계산하여 더 빠르게 만들 수 있습니다.

이것은 빠른 예입니다.

다섯 가지 궤적

예제는 다음 코드로 얻었습니다.

for (int run = 0; run < 5; run++)
{
    /* Create a new shuffled trajectory */
    Trajectory<12> traj;

    /* Print dots */
    for (double t = 0; t <= 1.0; t += 0.0001)
        printf("%g %g\n", t, traj.Get(t));
}

0

큰 소리로 생각하고 미적분을 인정하는 것이 나의 강점이 아닙니다. 아마도 불가능할까요? 명백한 패턴을 피하려면, x의 변화에 ​​대한 잡음 함수의 평균은 0에 ​​가까워 야하며, 단 조성을 보장하기 위해서는 x의 변화에 ​​대한 잡음의 진폭이 x의 변화보다 작아야합니다. x에 비해 x '에서 더 낮은 값을 초래합니다. 그러나 이는 dx를 0으로 줄이면 그러한 함수는 dA (여기서 A는 진폭)를 0으로 줄여야한다는 의미입니다. 이는 호환되는 잡음 함수에서 아무런 영향을받지 않습니다.

x가 1에 가까워 질수록 잡음 기여도를 점차적으로 감소시키는 함수를 공식화하는 것이 가능하다고 생각할 수 있지만 x가 1에 가까워지면 감속하는 곡선 함수를 제공합니다.


1
SkimFlux가 말한 것처럼 노이즈 함수의 통합으로 표준화하면 거의 동일한 함수를 얻을 수 있습니다. 함수 가 존재하기 때문에 , 그것이 가능한 코드화 가 가능한지의 문제 일뿐 입니다. 따라서 math.se 대신 여기에 묻습니다.

예를 들어, x가 1에 가까워 g(x) = 1 - f(1 - x)

물론, 함수가 존재합니다-당신은 teodron처럼 하나를 그릴 수 있습니다-그러나 그들은 '소음'기능입니까? 노이즈는베이스 라인에 대한 암시 적 진폭을 가진 의사 랜덤 입력에 기반한 연속 기능을 의미합니다. 그리고 그 진폭이 너무 높으면 출력 간 단조를 유지하기에 충분한 단계 간 차이가 낮다는 것을 보장 할 수 없습니다. 그러나 소음의 밀도와 보간 단계는 귀하의 사양을 충족시키기 위해 만들어 질 수 있습니다.
Kylotan

노이즈는 단지 "예측할 수 없음"을 의미하며, 생성 방법 (또는 기술적으로는 연속성, 애니메이션의 경우 거의 항상 코 히어 런트 노이즈를 원하지만)에 대해서는 아무 것도 언급하지 않습니다. 고정 된 엔드 포인트가이 기능의 가능한 진폭을 다소 제한하지만 전체적으로 제한하지는 않습니다. 다른 노이즈 함수는 비슷한 속성을 가지고 있습니다 (예 : 정수 x에 대해 Perlin (x) = 0). 단 조성은 그보다 더 강한 보장이지만, 그것이 그렇게 강력하다고 생각하지는 않습니다.

@JoeWreschnig Perlin 노이즈 기능이 몇 가지 기준을 심각하게 위반한다는 것을 알고 있습니다. 먼저 그리드 노드에서 0을 통과하므로 f (x + d) -f (x)는 특정 (일반적으로 간격이 지정된) x에 대해 d의 상수 배수입니다. 또한 그 영리한 캐싱 트릭으로 인해 큰 그리드에서도 반복됩니다. 고전적인 노이즈의 경우 참조 구현은 그리드 타일 (x, y)가 타일 (x + 256, y + 256)과 동일해야한다고 생각합니다. 이것이 수용 가능한지, 어느 정도까지 명시해야합니다.
Superbest
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.