Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Is this code correct ? (http://www.velocityreviews.com/forums/t594922-is-this-code-correct.html)

 johnnash 02-28-2008 06:31 PM

Is this code correct ?

In my project I need to shoot rays from the source.I know you cannot
follow all the rays from the source as you can actually shoot rays at
infinite angles,therefore my plan is to launch rays from the
trasmitter in all directions spaced eg. x degrees or something. This
is the logic I have used for a C program -

consider the source to be centre of the unit sphere.

0<=theta<=180(zenith)
0<=phi<=360 (azimuth)

Then run a for loop like this -

for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
degree difference or there will be infinite rays */
for( phi = 0; phi <=360; phi = phi + 5 )
{
/*Calculate the cartesian coordinates of a point p(a struct) on
sphere*/
P.x = r*sin(theta)*cos(phi);

P.y = r * sin(theta) *sin(phi);

P.z = r * cos(theta);

direction[index] = VectorSubtract(P, Center_of_Sphere);

VectorNormalize(direction[index]);

/*direction is just a list that will store ray directions */

 Eric Sosman 02-28-2008 06:55 PM

Re: Is this code correct ?

johnnash wrote:
> In my project I need to shoot rays from the source.I know you cannot
> follow all the rays from the source as you can actually shoot rays at
> infinite angles,therefore my plan is to launch rays from the
> trasmitter in all directions spaced eg. x degrees or something. This
> is the logic I have used for a C program -
>
> consider the source to be centre of the unit sphere.
>
> 0<=theta<=180(zenith)
> 0<=phi<=360 (azimuth)
>
> Then run a for loop like this -
>
> for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
> degree difference or there will be infinite rays */
> for( phi = 0; phi <=360; phi = phi + 5 )
> {
> /*Calculate the cartesian coordinates of a point p(a struct) on
> sphere*/
> P.x = r*sin(theta)*cos(phi);
>
> P.y = r * sin(theta) *sin(phi);
>
> P.z = r * cos(theta);
>
> direction[index] = VectorSubtract(P, Center_of_Sphere);
>
> VectorNormalize(direction[index]);
>
> /*direction is just a list that will store ray directions */

Your outline looks all right, but there are a few
points worth mentioning:

1) C's trigonometric functions work in radians, not
in degrees, so the code as written will not give the
results you presumably expect. Multiply each argument
by pi/180 before passing it to sin() or cos().

2) Your phi steps from 0 degrees up to and including
360 degrees. Since 0 and 360 are the same angle, each
zenith has one ray that's shot twice.

3) It is not good to worry too much about efficiency,
but some features of your code are so inefficient that
I can't resist pointing them out. In the inner loop you
evaluate sin(theta) twice and cos(theta) once -- but
theta remains unchanged while phi steps all around the
circle, so you get the same pair of answers over and over
again. Instead, consider calculating the functions of
theta once before entering the phi loop:

for (theta = 0; theta <= 180; theta += 5) {
double sint = sin(pi / 180 * theta);
double cost = cos(pi / 180 * theta);
for (phi = 0; phi < 360; phi += 5) {
P.x = r * sint * cos(pi / 180 * phi);
P.y = r * sint * sin(pi / 180 * phi);
P.z = r * cost;
...

3b) To avoid even more function evaluations, consider
interchanging the theta and phi loops and pre-calculating
sin(pi / 180 * phi) and cos(pi / 180 * phi) instead. (In
the inner theta loop, you would of course call sin() only
once.)

4) Since you say you're using a unit sphere, I imagine
that r == 1 -- in which case, why bother multiplying by it?

--
Eric.Sosman@sun.com

 johnnash 02-28-2008 07:02 PM

Re: Is this code correct ?

On Feb 28, 11:55 pm, Eric Sosman <Eric.Sos...@sun.com> wrote:
> johnnash wrote:
> > In my project I need to shoot rays from the source.I know you cannot
> > follow all the rays from the source as you can actually shoot rays at
> > infinite angles,therefore my plan is to launch rays from the
> > trasmitter in all directions spaced eg. x degrees or something. This
> > is the logic I have used for a C program -

>
> > consider the source to be centre of the unit sphere.

>
> > 0<=theta<=180(zenith)
> > 0<=phi<=360 (azimuth)

>
> > Then run a for loop like this -

>
> > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
> > degree difference or there will be infinite rays */
> > for( phi = 0; phi <=360; phi = phi + 5 )
> > {
> > /*Calculate the cartesian coordinates of a point p(a struct) on
> > sphere*/
> > P.x = r*sin(theta)*cos(phi);

>
> > P.y = r * sin(theta) *sin(phi);

>
> > P.z = r * cos(theta);

>
> > direction[index] = VectorSubtract(P, Center_of_Sphere);

>
> > VectorNormalize(direction[index]);

>
> > /*direction is just a list that will store ray directions */

>
>
> Your outline looks all right, but there are a few
> points worth mentioning:
>
> 1) C's trigonometric functions work in radians, not
> in degrees, so the code as written will not give the
> results you presumably expect. Multiply each argument
> by pi/180 before passing it to sin() or cos().
>
> 2) Your phi steps from 0 degrees up to and including
> 360 degrees. Since 0 and 360 are the same angle, each
> zenith has one ray that's shot twice.
>
> 3) It is not good to worry too much about efficiency,
> but some features of your code are so inefficient that
> I can't resist pointing them out. In the inner loop you
> evaluate sin(theta) twice and cos(theta) once -- but
> theta remains unchanged while phi steps all around the
> circle, so you get the same pair of answers over and over
> again. Instead, consider calculating the functions of
> theta once before entering the phi loop:
>
> for (theta = 0; theta <= 180; theta += 5) {
> double sint = sin(pi / 180 * theta);
> double cost = cos(pi / 180 * theta);
> for (phi = 0; phi < 360; phi += 5) {
> P.x = r * sint * cos(pi / 180 * phi);
> P.y = r * sint * sin(pi / 180 * phi);
> P.z = r * cost;
> ...
>
> 3b) To avoid even more function evaluations, consider
> interchanging the theta and phi loops and pre-calculating
> sin(pi / 180 * phi) and cos(pi / 180 * phi) instead. (In
> the inner theta loop, you would of course call sin() only
> once.)
>
> 4) Since you say you're using a unit sphere, I imagine
> that r == 1 -- in which case, why bother multiplying by it?
>
> --
> Eric.Sos...@sun.com

Thank you very much. However I did not understand the 2nd point.

 Micah Cowan 02-28-2008 07:23 PM

Re: Is this code correct ?

johnnash wrote:
> On Feb 28, 11:55 pm, Eric Sosman <Eric.Sos...@sun.com> wrote:
>> johnnash wrote:
>>> for( phi = 0; phi <=360; phi = phi + 5 )

>> 2) Your phi steps from 0 degrees up to and including
>> 360 degrees. Since 0 and 360 are the same angle, each
>> zenith has one ray that's shot twice.

> Thank you very much. However I did not understand the 2nd point.

There are 360 degrees to a circle. 0 through 360 is 361. Shooting at phi
== 0 and again at phi == 360 is exactly the same as shooting at phi == 0
twice.

You want that for statement to begin like:
for (phi = 0; phi < 360; phi += 5)
^^^
rather than with <=.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/

 Coos Haak 02-28-2008 07:54 PM

Re: Is this code correct ?

Op Thu, 28 Feb 2008 10:31:20 -0800 (PST) schreef johnnash:

> In my project I need to shoot rays from the source.I know you cannot
> follow all the rays from the source as you can actually shoot rays at
> infinite angles,therefore my plan is to launch rays from the
> trasmitter in all directions spaced eg. x degrees or something. This
> is the logic I have used for a C program -
>
> consider the source to be centre of the unit sphere.
>
> 0<=theta<=180(zenith)

0<=theta<=90 is enough.
--
Coos

Re: Is this code correct ?

johnnash wrote:
> In my project I need to shoot rays from the source.I know you cannot
> follow all the rays from the source as you can actually shoot rays at
> infinite angles,therefore my plan is to launch rays from the
> trasmitter in all directions spaced eg. x degrees or something. This
> is the logic I have used for a C program -
>
> consider the source to be centre of the unit sphere.
>
> 0<=theta<=180(zenith)
> 0<=phi<=360 (azimuth)
>
> Then run a for loop like this -
>
> for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
> degree difference or there will be infinite rays */
> for( phi = 0; phi <=360; phi = phi + 5 )
> {
> /*Calculate the cartesian coordinates of a point p(a struct) on
> sphere*/

Be aware that the distribution you get with this approach will not be
uniform. You will have a hot spot at 90 degrees zenith darkening as your
angle approaches 0 and 180 degrees.

I am not a graphics programmer, but I think to get a uniform distribution,
you should aim each vector at an equal-size portion of a sphere at a given
distance. You could do this, for each zenith angle, by going around a
circle on a unit sphere at equal spacing.

--

 Keith Thompson 02-29-2008 06:08 AM

Re: Is this code correct ?

johnnash <johnnash86@gmail.com> writes:
> In my project I need to shoot rays from the source.I know you cannot
> follow all the rays from the source as you can actually shoot rays at
> infinite angles,therefore my plan is to launch rays from the
> trasmitter in all directions spaced eg. x degrees or something. This
> is the logic I have used for a C program -
>
> consider the source to be centre of the unit sphere.
>
> 0<=theta<=180(zenith)
> 0<=phi<=360 (azimuth)
>
> Then run a for loop like this -
>
> for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
> degree difference or there will be infinite rays */
> for( phi = 0; phi <=360; phi = phi + 5 )
> {

[snip]

Your rays are spaced much more tightly near the poles than near the
equator. If your sphere were the surface of the Earth, then on the
equator you'd have one ray about every 550 kilometers. On the circle
5 degrees from either pole, your rays are less than 50 kilometers
apart. And at the pole itself, you have 72 rays at the same spot.

Computing N points on a sphere that are perfectly equally placed is
tricky, and likely impossible for most values of N. But you can vary
the number of points on each parallel of latitude should give you
decent results.

--
Keith Thompson (The_Other_Keith) <kst-u@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

 Ernie Wright 02-29-2008 04:15 PM

Re: Is this code correct ?

> johnnash wrote:
>
>> In my project I need to shoot rays from the source. [...]
>>
>> consider the source to be centre of the unit sphere.
>>
>> 0<=theta<=180(zenith)
>> 0<=phi<=360 (azimuth)
>>
>> Then run a for loop like this -
>>
>> for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
>> degree difference or there will be infinite rays */
>> for( phi = 0; phi <=360; phi = phi + 5 )

>
> Be aware that the distribution you get with this approach will not be
> uniform. You will have a hot spot at 90 degrees zenith darkening as
> your angle approaches 0 and 180 degrees.
>
> I am not a graphics programmer, but I think to get a uniform
> distribution, you should aim each vector at an equal-size portion of a
> sphere at a given distance. You could do this, for each zenith angle,
> by going around a circle on a unit sphere at equal spacing.

There are a number of ways to approach this. One would be to scale the
steps in phi by the sine of theta,

for ( phi = 0; phi < 360; phi += 5.0 / sin( theta )) ...

The poles, where theta = 0 or 180, are treated as a special case, since
there's no need to test different increments of phi.

A better way would be to use the vertex coordinates of a spherical
tessellation. The icosahedron is a roughly spherical shape made of 12
equally spaced vertices and 20 equilateral triangles. You can use the
3D cartesian coordinates of the vertices directly as a uniform sample of
the unit sphere. For a higher sampling rate, subdivide each triangle.

The OP desperately needs to acquaint himself with the fundamentals of
3D graphics. Basic raytracing in particular is well understood, well
documented, and thoroughly covered in any good first-semester college
course on 3D. The textbooks used in those courses would be a *much*
better source of information than c.l.c.

- Ernie http://home.comcast.net/~erniew

 johnnash 03-05-2008 09:36 AM

Re: Is this code correct ?

> johnnash wrote:
> > In my project I need to shootraysfrom the source.I know you cannot
> > follow all theraysfrom the source as you can actually shootraysat
> > infinite angles,therefore my plan is to launchraysfrom the
> > trasmitter in all directions spaced eg. x degrees or something. This
> > is the logic I have used for a C program -

>
> > consider the source to be centre of the unit sphere.

>
> > 0<=theta<=180(zenith)
> > 0<=phi<=360 (azimuth)

>
> > Then run a for loop like this -

>
> > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
> > degree difference or there will be infiniterays*/
> > for( phi = 0; phi <=360; phi = phi + 5 )
> > {
> > /*Calculate the cartesian coordinates of a point p(a struct) on
> > sphere*/

>
> Be aware that the distribution you get with this approach will not be
> uniform. You will have a hot spot at 90 degrees zenith darkening as your
> angle approaches 0 and 180 degrees.
>
> I am not a graphics programmer, but I think to get a uniform distribution,
> you should aim each vector at an equal-size portion of a sphere at a given
> distance. You could do this, for each zenith angle, by going around a
> circle on a unit sphere at equal spacing.
>
> --

I thought what would actually happen over here is that I would get a
thicker density of rays near the poles as opposed to when zenith
becomes 90

 johnnash 03-05-2008 09:38 AM

Re: Is this code correct ?

> There are a number of ways to approach this. One would be to scale the
> steps in phi by the sine of theta,
>
> for ( phi = 0; phi < 360; phi += 5.0 / sin( theta )) ...
>
> The poles, where theta = 0 or 180, are treated as a special case, since
> there's no need to test different increments of phi.
>

why increment phi in steps of sin(theta) ?? if we do this, then when
zenith is 90, the rays will far apart whereas near the poles, they
would be bundled closely and there will be a very thick density.

All times are GMT. The time now is 03:17 AM.