• 13
• 18
• 19
• 27
• 9

# Moving light in a circle in 3D

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

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


##### 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 on other sites

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

##### 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 on other sites

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

##### 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!