I am converting a particle emitter from 2d to 3d.
In the 2d system the original coder used a random angle variance and added it to the angle. So it would be something like:
thisAngle = emitterAngle + angleVariance * RANDOM_MINUS_1_TO_1();
I want to do the same thing in 3d using an emission vector (vec3) and again an angleVariance. My specific variance for this particle will still be angleVariance * RANDOM_MINUS_1_TO_1(). But how do I apply that angle a 3d vector so that the new vector could be any value X degrees off of center. So if the original vector is straight up (0,1,0) the new vector could be off in the X or the Z and still normalized to 1.
Any hints? I have all the matrix and vector functions at my disposal.
=====
Thanks to nathan I was able to write this code. Not sure if I've over complicated it somewhere. Once I test it I'll checkmark his answer:
// first pick a random Z from [cos(angleVariance), 1]
GLfloat varianceZ = [self randomFloatBetween:myCosf(angleVariance) andLargerFloat:1.0];
// and a random angle for the azimuth
GLfloat rndA = [self randomFloatBetween:0.0 andLargerFloat:360.0];
// then calculate the X & Y to make this a vector off of the +Z axis with a max width of angleVariance
GLfloat varianceX = sqrt(1 - varianceZ*varianceZ) * myCosf(rndA); // my functions input degrees not radians
GLfloat varianceY = sqrt(1 - varianceZ*varianceZ) * mySinf(rndA);
Up to here the above code works. It makes a variance angle off center but it is aligned to the +z axis. The next part is supposed to rotate/transform the angle to my emissionVector angle so it's a variance off of that. But so far this part isn't working.
// next find an axis to rotate the point around to put it in line with the emmissionVector
vec3 rotationAxis = normalizeVec3(crossProduct(vec3Make(0.0, 0.0, 1.0), emissionVector));
GLfloat rotationAngle = acos(degreesToRadians(emissionVector.z));
// make a quaternion out of the rotation axis and angle
vec4 q = quaternionVector(rotationAxis, rotationAngle);
// turn the quaternion into a matrix
mat4 rotMat4;
mat3 rotMat3;
matrixQuaternion(q, rotMat4);
getMat3FromMat4(rotMat4, rotMat3);
// multiply the variance vector by the matrix to get a resulting vector with the variance added
vector = matrixTransformVec3(rotMat3, vec3Make(varianceX, varianceY, varianceZ));
=====
The above code doesn't appear to be correct. I'm still working on the solution and will fix the above code when I get it working.