Sign in to follow this  

Moving light in a circle in 3D

This topic is 412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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);
}
 

 

Share this post


Link to post
Share on other sites
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;

:)

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites

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 [tt]time[/tt] and [tt]cnt[/tt] are in milliseconds, then [tt]sin((cnt+=100*time)/5 * 2*pi)[/tt] 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)
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

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...

Edited by Lactose!

Share this post


Link to post
Share on other sites
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.

Edited by Lactose!

Share this post


Link to post
Share on other sites

This topic is 412 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this