ReX357
ReX357

Reputation: 1229

Animating a sine wave infinitely

I need a function to animate a sine wave infinitely over time. The sine wave moves to the left.

My sine wave is built using the following equation:

A * sin(B * x + C) + D

Now to animate the sine wave as if it is moving to the left, I simply increase C by 1 everytime I refresh the screen. Now this is all fine and dandy for a few minutes but I need to have that animation run for hours. I can't just have an integer build up 60 times a second forever. How does someone deal with this? Do I just try to find a point where the sine wave crosses 0 and then restart the animation from 0?

I just need to have the logic of something like this explained.

EDIT #1 I forgot to mention that there's a randomized component to my sine. The sine is not continuously the same. A and D are sinusoidal functions tied to that integer at the moment. The sine needs to look random with varying periods and amplitudes.

EDIT #2

Edited see Edit 3

EDIT #3

@Potatoswatter I tried implementing your technique but I don't think I'm getting it. Here's what I got:

        static double i = 0;
        i = i + (MPI / 2); 
        if ( i >= 800 * (MPI / 2) ) i -= 800 * (MPI / 2);

                    for (k = 0; k < 800; ++k)
        {
            double A1 = 145 * sin((rand1 * (k - 400) + i) / 300) + rand3;       // Amplitude
            double A2 = 100 * sin((rand2 * (k - 400) + i) / 300) + rand2;       // Amplitude
            double A3 = 168 * sin((rand3 * (k - 400) + i) / 300) + rand1;       // Amplitude

            double B1 = 3 + rand1 + (sin((rand3 * k) * i) / (500 * rand1));     // Period
            double B2 = 3 + rand2 + (sin((rand2 * k) * i) / 500);           // Period
            double B3 = 3 + rand3 + (sin((rand1 * k) * i) / (500 * rand3));     // Period

            double x = k;                               // Current x

            double C1 = 10 * i;                         // X axis move
            double C2 = 11 * i;                         // X axis move
            double C3 = 12 * i;                         // X axis move

            double D1 = rand1 + sin(rand1 * x / 600) * 4;               // Y axis move
            double D2 = rand2 + sin(rand2 * x / 500) * 4;               // Y axis move
            double D3 = rand3 + cos(rand3 * x / 400) * 4;               // Y axis move


            sine1[k] = (double)A1 * sin((B1 * x + C1) / 400) + D1;
            sine2[k] = (double)A2 * sin((B2 * x + C2) / 300) + D2 + 100;
            sine3[k] = (double)A3 * cos((B3 * x + C3) / 500) + D3 + 50;

        }

How do I modify this to make it work?

Halp!

Upvotes: 1

Views: 1912

Answers (3)

ReX357
ReX357

Reputation: 1229

I decided to change my course of action. I just drive i with the system's monotonic clock like so:

        struct timespec spec;
        int ms;
        time_t s;
        static unsigned long long etime = 0;

        clock_gettime(CLOCK_MONOTONIC, &spec);
        s = spec.tv_sec;
        ms = spec.tv_nsec / 10000000;
        etime = concatenate((long)s, ms);

Then I simply changed i to etime in my sine equations. Here's the concatenating function I used for this purpose:

unsigned concatenate(unsigned x, unsigned y) {
    x = x * 100;
        return x + y;        
}

Upvotes: 0

Potatoswatter
Potatoswatter

Reputation: 137830

sin is periodic, with a period of 2π. Therefore, if the argument is greater than 2π, you can subtract 2 * M_PI from it and get the same answer.

Instead of using a single variable k to compute all waves of various speeds, use three variables double k1, k2, k3, and keep them bound in the range from 0 to 2π.

if ( k2 >= 2 * M_PI ) k2 -= 2 * M_PI;

They may be individually updated by adding some value each frame. If the increment may be more than 2π then subtracting a single 2π won't bring them back into range, but you can use fmod() instead.

Upvotes: 0

Andrey Mishchenko
Andrey Mishchenko

Reputation: 4206

Sine has a period of 2 pi, meaning that sin(x) = sin(x + 2 * M_PI), for any x.

So, you could just increase C by, say, pi/n where n is any integer, as you refresh the screen, and after 2n refreshes, reset C (to 0, or whatever).

Edit for clarity: the integer n is not meant to change over time.

Instead, pick some n, for example, let's say n = 10. Now, every frame, increase x by pi / 10. After 20 frames, you have increased x by a total of 20 * pi / 10 = 2 * pi. Since sin(x + 2 * pi) = sin(x), you may as well just reset your sin(...) input to just x, and start the process over.

Upvotes: 2

Related Questions