I have following problem with billboarding:
I have a bunch of objects placed on their local origins.
For facing objects to camera view i’m using following function
void doBillboarding(float *cam, float *worldPos) {
float lookAt[3]={0,0,1},objToCamProj[3],upAux[3],angleCosine;
// objToCamProj is the vector in world coordinates from the local origin to the camera
// projected in the XZ plane
objToCamProj[0] = cam[0] - worldPos[0] ;
objToCamProj[1] = 0;
objToCamProj[2] = cam[2] - worldPos[2] ;
// normalize both vectors to get the cosine directly afterwards
mathsNormalize(objToCamProj);
// easy fix to determine wether the angle is negative or positive
// for positive angles upAux will be a vector pointing in the
// positive y direction, otherwise upAux will point downwards
// effectively reversing the rotation.
mathsCrossProduct(upAux,lookAt,objToCamProj);
// compute the angle
angleCosine = mathsInnerProduct(lookAt,objToCamProj);
// perform the rotation. The if statement is used for stability reasons
// if the lookAt and v vectors are too close together then |aux| could
// be bigger than 1 due to lack of precision
if ((angleCosine < 0.99990) && (angleCosine > -0.9999))
glRotatef(acos(angleCosine)*180/3.14,upAux[0], upAux[1], upAux[2]);
}
This is straight from Lighthouse3D billboarding tutorial.
When i’m drawing my billboards:
The problem is that damn billboards flying around the scene not just rotating the Y axis of their local origins.
I have tried all (modelview matrix modification etc.). What’s wrong ??? (stupid thing i suppose )
Thanks for ANY help.
Best Regards.
If I understand you correctly, you want to create a single matrix to transform all your sprites.
If that’s the case, then good luck my friend. You could create a single rotation matrix, but translation is another matter, since I assume that each sprite in your scene has a unique position, hence the orbiting sprite frenzy you mentioned. You simply can’t use a single matrix to both rotate and translate all the sprites.
I strongly recommend getting rid of the glRotatef(…) and acos() calls. There are much better (faster) ways to generate a sprite basis. Here’s an alternative method:
void makeSprite( Vector eyeLeft, Vector eyeUp, Vector spritePos, float spriteRadius, Vector result[4] )
{
Vector left = eyeLeft * spriteRadius;
Vector up = eyeUp * spriteRadius;
result[0] = spritePos + left + up;
result[1] = spritePos - left + u;
result[2] = spritePos - left - up;
result[3] = spritePos + left - up;
}
Holrin, just set eyeUp = Vector(0,1,0), then cross this vector with your forward vector.
newEyeLeft = cross( eyeUp, eyeForward );
then proceed normally using newEyeLeft instead of eyeLeft.
But take care that eyeForward doesn’t coincide with the y axis, or you will have a nasty case where the cross will give you a zero vector. To solve that problem, you can pick another suitable vector to replace it.
In fact, you can generalize this whole thing into what’s known as a rope sprite:
void makeRopeSprite( Vector eyePos, Vector ropeStart, Vector ropeEnd, float radius, Vector result[4] ) {
Vector up = cross(eyePos-ropeStart, ropeEnd-ropeStart );
up = normalize( up );
up = up * radius;
result[0] = ropeStart+ up;
result[1] = ropeEnd + up;
result[2] = ropeEnd - up;
result[3] = ropeStart- up;
}
The 2 end points of the rope define the axis of rotation - just another way to think about it.
By the way, your English is 1,000,000,000 times better than my Polish.