# Thread: Random Vectors problem solved

1. ## Random Vectors problem solved

Hi guys, some days ago, i asked, if someone knows, how to produce a random vector around a "normal". I didnīt get so much replies, maybe because it is hard to explain.
However, thanks to my math-teacher, i solved the problem now, and i think, it would be interessting for all those people, who think of the same problem, because it can be very usefull in particle-systems.
So hereīs the solution (quite long):

VECTOR RandomVector (VECTOR Normal, int iMaxAlpha, float iDesiredLength)
{
/* THEORY
We want to produce a vector, which points in the direction of "Normal"
but has a deviation of maximal "iMaxAlpha" into any direction.

To produce a random vector, we take a vector parallel to the x-axis (1,0,0)
and rotate it first around the z-axis. If we did this by 45 degree, we would
for example get (0.7, 0.7, 0)
Then we rotate it around the x-axis by a random angle between 0 and 360 degree.
For example, if we did this by 90 degree, we would get (0.7, 0, 0.7).

Then we have a random vector around the x-axis. To get it to be a vector around
"Normal", we have to rotate it around two axis by the angle between "Normal" and
the used axis.

Thats all

To do this, you need a simple 3x3 matrix class and a vector class. And you
need a function, to multiply the matrix with the vector.

Because you need sin and cos very often, you may precalculate the values and
store them in an array, just as i did. (Therefore i shorten the float-angles
to int-angles.)

Hope, you may find it usefull.
*/

//calculate the length of "Normal" in the XY-plane
float lengthxy = Normal.x*Normal.x + Normal.y*Normal.y; // sqared length
lengthxy = sqrt (lengthxy); // real length

//calculate the angle between the x-axis and "Normal" in the XY-plane
float alphaxy = Normal.y / lengthxy; // sin alpha = y / hypotenuse
int ialphaxy = (int) (asin (alphaxy)*180.0f/3.141f);//convert it to degree

//calculate the length of "Normal" in the XZ-plane
float lengthxz = Normal.x*Normal.x + Normal.z*Normal.z; // sqared length
lengthxz = sqrt (lengthxz); // real length

//calculate the angle between the x-axis and "Normal" in the XZ-plane
float alphaxz = Normal.z / lengthxz; // sin alpha = z / hypotenuse
int ialphaxz = (int) (asin (alphaxz)*180.0f/3.141f);//convert it to degree

//now we take a vector, which is parallel to the x-axis and rotate it to create a
//random vector

VECTOR n (1,0,0);//x-axis

int alpha = rand () % iMaxAlpha;//we will rotate it by alpha around the z-axis

//here comes our matrix, which will rotate the vector around the z-axis
MATRIX3X3 mat (COS[alpha], -SIN[alpha], 0,
SIN[alpha], COS[alpha], 0,
0 , 0 , 1);

//we multiply mat and n (matrix multiplication), to rotate n and store it in d
VECTOR d = mat * n;

//our new vector lies in the XY-plane (because we rotated it around the z-axis),
//now we rotate it around the x-axis, so it will lie in all three planes
int beta = rand () % 360; // rotation around x-axis

//here comes our rotation matrix
mat.SetMatrix (1,0,0,
0,COS[beta],-SIN[beta],
0,SIN[beta],COS[beta]);

// multiply d and mat
d = mat * d;

//now we have a random vector around the x-axis
//but we want it to be a random vector around "Normal", so we will rotate it by
//ialphaxy and ialphaxz, to produce a vector around "Normal"

//rotate the vector around the z-axis (by ialphaxy)
mat.SetMatrix (COS[ialphaxy],-SIN[ialphaxy],0,
SIN[ialphaxy],COS[ialphaxy],0,
0,0,1);
d = mat * d;

//rotate the vector around the y-axis (by ialphaxz)
mat.SetMatrix (COS[ialphaxz],0,SIN[ialphaxz],
0,1,0,
-SIN[ialphaxz],0,COS[ialphaxz]);
d = mat * d;

//thats all, we have a random vector, now we can do some extra stuff

d.Normalize (); // unit-length

//and strecht it to the desired length
d *= iDesiredLength;

return (d);
}

Have fun with it.
Jan.

2. ## Re: Random Vectors problem solved

Lol! I was just working on tidying up my Vector class. I'll add this method in there too. I can imagine its going to be really useful.

Thanks!

4. ## Re: Random Vectors problem solved

I donīt know, what gaussian noise is, but when you explain it to me, i might do it.

Jan.

5. ## Re: Random Vectors problem solved

and when you've done it, I'll copy and paste it into my class

6. ## Re: Random Vectors problem solved

There is a problem -- a divide by zero if the vector is parallel to the Y axis.

The easiest way to do it is to give your emitter an orientation (rather than just a direction), generate a random vector in the emitter's space according to your criteria, and then transform it into world space. My emitter creates random vectors in a cone around the Z axis:
Code :
```
vector r, v;

a = randfloat( 0.f, CONE_ANGLE );
b = randfloat( 0.f, TWO_PI );

r.x = cos( b ) * sin( a );
r.y = sin( b ) * sin( a );
r.z = cos( a );

v = EmitterSpaceToWorldSpace( r );```

7. ## Re: Random Vectors problem solved

Originally posted by Jambolo:

vector r, v;

a = randfloat( 0.f, CONE_ANGLE );
b = randfloat( 0.f, TWO_PI );

r.x = cos( b ) * sin( a );
r.y = sin( b ) * sin( a );
r.z = cos( a );

v = EmitterSpaceToWorldSpace( r );

[/CODE]
How to convert the emitter space to world space? Given Eye, Right and Up for the emitter, are you performing some kind of orthonormal basis transform? If so, how do you do this?

Cheeeaaarrs.

8. ## Re: Random Vectors problem solved

You are right, it should crash, if Normal is parallel to the y-axis because then Normal.x*Normal.x + Normal.z*Normal.z is zero. And it should also crash, when Normal is parallel to the z-axis, because then the same thing happens again.
However i used the function with a vector that is parallel to the y-axis and it didnīt crash, thatīs strange.

Well, you should just add two if-statements and test if lengthxy is zero or lengthxz is zero and if it is then you set ialphaxy or ialphaxz to zero. That should do it, i didnīt test it, yet.

Chears,
Jan.

9. ## Re: Random Vectors problem solved

Wouldn't it be easier to just take the "approximate direction" vector, add some random number to each component, then normalize?

10. ## Re: Random Vectors problem solved

Wouldn't work. Well it would depend on the direction vector. Same with the spherical version above; most points will be around the poles of the sphere. What we need is a function that will provide a uniform distribution around the normal. No idea how to do this!

Page 1 of 2 12 Last

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•