Advertisement

Moving light in a circle in 3D

Started by October 29, 2016 08:45 PM
7 comments, last by Lactose 8 years, 1 month ago

I would like to move the position of the light in a circle in 3D in the XZ plane. I have the time delta which is in milleseconds. the behaviour is the light is oscillating and flickers on the surface.

here is how I do it


while(!Finished)
{
static int cnt = 0;

cnt += time*100;
raster.light_source.x = (float)cos((float)2*3.14598*(float)cnt /5);
raster.light_source.z = (float)sin((float)2*3.14598*(float)cnt /5);
}

Game Programming is the process of converting dead pictures to live ones .
What makes you think that the source of the flickering is in the lines of code you posted?

Also, it's a good idea to give names to your constants, like this:

  const float large_value_of_pi = 3.14598;

:)
Advertisement

What you posted seems to be just a snippet (and looks like an infinite while loop), and might not contain the actual bug.

Additionally, your value of pi (?) is, like Álvaro hinted at, larger than normal :P

With that amount of decimals, your pi value should be 3.14159f

With that said, I would probably do this along the lines of...

1) Have a float variable keeping track of elapsed time.

2) Every tick/update, increment the elapsed time variable by delta time.

3) Calculate the position using the elapsed time variable, and the sin/cos stuff you're doing.

I would probably also have two additional variables, 1 for radius, and 1 for controlling how rotational speed (alternatively, the variable could be for how long it should take to do a full revolution, and compute the speed from that).

Hello to all my stalkers.

while(!Finished)
{
static int cnt = 0;

cnt += time*100;
raster.light_source.x = (float)cos((float)2*3.14598*(float)cnt /5);
raster.light_source.z = (float)sin((float)2*3.14598*(float)cnt /5);
}


So, if time and cnt are in milliseconds, then sin((cnt+=100*time)/5 * 2*pi) describes an oscillation at 20000 Hz, which is probably 30000 to 40000 times faster than you need. :^)

Try describing it in terms of cycles per second:


int delta_time; // ms
const float two_pi = 3.1415926.f * 2;

const float cycles_per_second = 1 / 3.0;  // 3 seconds per cycle
const float radius = 10;                  // in units

while ( !Finished ) {
    timer += delta_time;

    // convert from ms to seconds, and multiply by frequency, and then convert to radians
    float phase = (timer / 1000.f) * cycles_per_second * two_pi;

    // and finally, displace the light some units away from the origin
    raster.light_source.x = (float)sin(phase) * radius;
    raster.light_source.z = (float)cos(phase) * radius;


    // (and hopefully you’re letting the graphics render here)
}
Perhaps a bit off topic, but the handling of types in the original code and even in fastcall22's code is all over the place. `1' is an `int' constant, `3.0' is a double constant and `1000.0f' is a float constant.

Here's how I would have written it:

int delta_time; // in milliseconds
const float tau = std::atan(1.0f) * 8.0f; // tau is another name for 2*pi

const float angular_frequency = tau / 3.0f;  // 3 seconds per cycle
const float radius = 10.0f;

while ( !Finished ) {
    timer += delta_time * 0.001f;

    float phase = timer * angular_frequency;

    raster.light_source.x = sin(phase) * radius;
    raster.light_source.z = cos(phase) * radius;

}
The functions `sin' and `cos' that take a float already return a float, so casting to float there only demonstrates confusion on the part of the programmer.

the light is normalized vector, so should I clamp the sin and cos to 0 -> 1 ?

Game Programming is the process of converting dead pictures to live ones .
Advertisement

the light is normalized vector, so should I clamp the sin and cos to 0 -> 1 ?

Unless you're using something very special, sin and cos return a value between -1 (inclusive) and 1 (inclusive). No reason to clamp to 0, I would have thought...

Hello to all my stalkers.

so I shouldn't multiply it with radius ? that would scale the amplitude a lot

Game Programming is the process of converting dead pictures to live ones .
so I shouldn't multiply it with radius ? that would scale the amplitude a lot

You don't need to clamp what sin/cos returns -- sin/cos will return something between -1.0f and 1.0f.

You should scale those values by radius, to be able to adjust the size of the circle movement.

Clamping is cutting off values that are too high or too low. In code, it would be something like:


if (value < min)
    value = min;
if (value > max)
    max = max;

You don't need that here, since sin/cos return what you what.

They return values which are appropriate to use as a ratio -- what kind of distance do the x and y coordinates have from the origin.

Because it's just a ratio, you want to scale it by the radius.

Sin returning 0.25f means that the x coordinate should be 25% of the way from the origin to the radius.

Hello to all my stalkers.

This topic is closed to new replies.

Advertisement