Chciałbym, aby funkcja animowała obiekt przemieszczający się z punktu A do punktu B w czasie, tak że osiąga on B w pewnym ustalonym czasie, ale jego pozycja w dowolnym momencie jest losowo zaburzona w sposób ciągły, ale nigdy nie wraca. Obiekty poruszają się wzdłuż linii prostych, więc potrzebuję tylko jednego wymiaru.
Matematycznie oznacza to, że szukam ciągłych f (x), x ∈ [0,1], takich jak:
- f (0) = 0
- f (1) = 1
- x <y → f (x) ≤ f (y)
- W „większości” punktów f (x + d) - f (x) nie ma oczywistego związku z d. (Funkcja nie jest równomiernie rosnąca ani w inny sposób przewidywalna; myślę, że jest to również równoważne z twierdzeniem, że żaden stopień pochodnej nie jest stały).
Idealnie, chciałbym w jakiś sposób mieć rodzinę tych funkcji, zapewniającą trochę stanu początkowego. Potrzebowałbym co najmniej 4 bitów nasion (16 możliwych funkcji), do mojego obecnego użytku, ale ponieważ nie jest to zbyt wiele przyjemności, aby zapewnić jeszcze więcej.
Aby uniknąć różnych problemów z błędami akumulacji, wolałbym, aby funkcja nie wymagała żadnego rodzaju stanu wewnętrznego. To znaczy, chcę, żeby była to prawdziwa funkcja, a nie „funkcja” programowania.
f'(x)>0
, więc znormalizowana integracja wartości bezwzględnej dowolnej funkcji hałasu spełni wszystkie Twoje wymagania. Niestety nie znam żadnego łatwego sposobu na obliczenie tego, ale może ktoś inny to zna. :)Odpowiedzi:
W tym poście y = f (t), gdzie t jest zmiennym parametrem (czas / postęp), ay jest odległością do celu. Będę mówić o punktach na wykresach 2D, w których oś pozioma to czas / postęp, a pion to odległość.
Myślę, że możesz zrobić sześcienną krzywą Beziera z pierwszym punktem w (0, 1) i czwartym (ostatnim) punktem w (1, 0). Dwa środkowe punkty mogą być losowo umieszczone (x = rand, y = rand) w tym prostokącie 1 na 1. Nie jestem w stanie zweryfikować tego analitycznie, ale po prostu bawię się apletem (tak, śmiej się), wydaje się, że krzywa Beziera nigdy nie zmniejszy się z takim ograniczeniem.
Będzie to twoja elementarna funkcja b (p1, p2), która zapewnia nie malejącą ścieżkę od punktu p1 do punktu p2.
Teraz możesz wygenerować ab (p (1) = (0, 1), p (n) = (1, 0)) i wybrać liczbę p (i) wzdłuż tej krzywej, tak aby 1
Zasadniczo generujesz jedną „ogólną” ścieżkę, a następnie dzielisz ją na segmenty i regenerujesz każdy segment.
Ponieważ potrzebujesz funkcji matematycznej: Załóżmy, że powyższa procedura jest spakowana w jedną funkcję y = f (t, s), która daje odległość w t dla funkcji nasion s. Będziesz potrzebować:
Dlatego każde ziarno musi dostarczyć jedno z poniższych:
Wyobrażam sobie, że możesz to osiągnąć, podając po prostu tablicę liczb jako nasion. Alternatywnie, możesz zrobić coś takiego jak podać jedną liczbę s jako ziarno, a następnie wywołać wbudowany generator liczb losowych za pomocą rand (s), rand (s + 1), rand (s + 2) i tak dalej (lub zainicjować za pomocą s, a następnie nadal dzwonić rand.NextNumber).
Zauważ, że chociaż cała funkcja f (t, s) składa się z wielu segmentów, oceniasz tylko jeden segment dla każdego t. Państwo będzie musiał wielokrotnie obliczać granice segmentów z tej metody, ponieważ trzeba będzie uporządkować je, aby upewnić się nie ma dwóch segmentów zachodzą na siebie. Prawdopodobnie możesz zoptymalizować i pozbyć się tej dodatkowej pracy i znaleźć tylko punkty końcowe jednego segmentu dla każdego połączenia, ale nie jest to dla mnie teraz oczywiste.
Ponadto krzywe Beziera nie są konieczne, wystarczy odpowiednio zachowujący splajn.
Stworzyłem przykładową implementację Matlaba.
Funkcja Beziera (wektoryzowana):
Opisana powyżej złożona funkcja Beziera (celowo pozostawiona bez wektoryzacji, aby wyjaśnić, ile oceny jest potrzebne dla każdego połączenia):
Skrypt, który wykreśla funkcję losowego ziarna (zauważ, że jest to jedyne miejsce, w którym wywoływana jest funkcja losowa, zmienne losowe do wszystkich innych kodów są propagowane z tej jednej losowej tablicy):
Oto przykładowy wynik:
Wygląda na to, że spełnia większość twoich kryteriów. Jednak:
źródło
Wydaje mi się, że zamiast mieszać kilka transformowanych cosinusów (jak dają ci produkty kropkowe w szumie perlin), możesz mieszać kilka funkcji monotonicznych, które zaczynają się od f (0) = 0, np. F (x) = x lub 2x, lub x ^ 2, itd. W rzeczywistości, ponieważ twoja domena jest ograniczona do 0 => 1, możesz również łączyć funkcje trig, które pasują do rachunku w tej domenie, takie jak cos (90 * x + 270). Aby znormalizować metody kończące się na 1, możesz po prostu podzielić ważoną sumę tych metod monotonicznych zaczynając od f (0) = 0 przez f (1). Coś takiego powinno również być dość łatwe do odwrócenia (które, jak rozumiem, chcesz z części o bezpaństwowych funkcjach rzeczywistych kontra funkcjach programowania).
Mam nadzieję że to pomoże.
źródło
Można przeanalizować ten prymitywny obraz. Można uzyskać funkcję, która wykonuje animację w locie, wykorzystując jednolitą funkcję rand. Wiem, że nie jest to dokładna formuła matematyczna, ale tak naprawdę nie ma formuły matematycznej dla funkcji losowej, a nawet gdyby istniała, wiele byś napisał, aby to osiągnąć. Biorąc pod uwagę, że nie określono żadnych warunków płynności, profil prędkości ma ciągłą wartość $ C ^ 0 $ (ale ponieważ nie masz do czynienia z robotami, nie musisz martwić się o nieciągłe profile przyspieszenia).
źródło
Zwykłym sposobem generowania rosnącej sekwencji N liczb losowych z [0,1] jest wygenerowanie N liczb losowych w dowolnym zakresie, następnie podziel je wszystkie przez ich całkowitą sumę, a następnie zsumuj je pojedynczo, aby uzyskać sekwencja.
Można to rozszerzyć na 2D, generując te wartości zarówno dla X, jak i Y. Możesz zwiększyć N, aby uzyskać dowolną szczegółowość.
W podobnej odpowiedzi @ teodron przytoczyłeś obawy dotyczące wydajności w dużych skalach czasowych. Nie znając rzeczywistego problemu, przed którym stoisz, nie mogę stwierdzić, czy ta obawa jest uzasadniona; ale inną opcją byłoby wygenerowanie dla małego N i po prostu wygładzenie wyniku. W zależności od zastosowania może to faktycznie dać lepsze wyniki.
N = 100, bez wygładzania
N = 15, z wygładzaniem
źródło
Proponuję tę implementację zainspirowaną sumą oktaw znalezionych we fraktalnym hałasie, z odrobiną taniego tasowania w tyłku tu i tam. Uważam, że jest dość szybki i można go dostroić, prosząc o mniej oktaw niż zapisanych w parametrach z utratą precyzji około
1/2^octave
.Można to uznać za implementację częściową, która wymaga tylko czasu O (log (kawałki)) . Tablica parametrów jest używana zarówno dla pozycji przestawnej „dziel i rządź”, jak i dla odległości przebytej przy osiągnięciu punktu obrotu.
Można to przyspieszyć, wstępnie obliczając podziały zmiennoprzecinkowe, kosztem przechowywania trzykrotnie większej ilości informacji.
To jest szybki przykład:
Przykład uzyskano z następującego kodu:
źródło
Myślenie na głos i przyznawanie rachunku różniczkowego nie jest moją mocną stroną ... czy to może nie jest możliwe? Aby uniknąć jakiegokolwiek oczywistego wzorca, średnia funkcji szumu dla każdej zmiany x musi być bliska zeru, a dla zagwarantowania monotoniczności amplituda szumu dla tej zmiany x musi być mniejsza niż zmiana x, ponieważ każda większa amplituda mogłaby skutkować niższą wartością przy x 'względem x. Oznaczałoby to jednak, że w miarę zmniejszania dx do 0, funkcja taka musi również zmniejszać dA (gdzie A jest amplitudą) do zera, co oznacza, że nie otrzymujesz żadnego wkładu z żadnej zgodnej funkcji szumu.
Mogę sobie wyobrazić, że można sformułować funkcję, która stopniowo zmniejsza udział hałasu, gdy x zbliża się do 1, ale da ci zakrzywioną funkcję, która zwalnia, gdy x zbliża się do 1, co nie jest tym, co myślę, że chcesz.
źródło
g(x) = 1 - f(1 - x)
, która zamiast tego przyspiesza, gdy x odchodzi od zera.