PDA

View Full Version : Another billboarding problem



Holrin
04-24-2004, 02:37 PM
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) &amp;&amp; (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:

doBillboarding(Camera.Position, Object.origin);
object.draw()
glPopMatrix();

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.

plasmonster
04-24-2004, 03:08 PM
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;
}edit:
corrected some mistakes.

Holrin
04-25-2004, 02:45 AM
I've adopted your method and it works fine. Thanks for help and sorry for my english :)
Best Regards.

Holrin
04-25-2004, 03:37 AM
Hmm...I've just noticed that billboard rotating around ALL axes. How to do an axis(Y) aligned rotation ?
Thx for help.

plasmonster
04-25-2004, 12:40 PM
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. :)