Another billboarding problem

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:

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 :slight_smile: )
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;
}

edit:
corrected some mistakes.

I’ve adopted your method and it works fine. Thanks for help and sorry for my english :slight_smile:
Best Regards.

Hmm…I’ve just noticed that billboard rotating around ALL axes. How to do an axis(Y) aligned rotation ?
Thx for help.

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. :slight_smile: