# Billboarding around a specific vector ?

My favorit subject - billboard I want to billboard trees around a sphere.

To be able to do this I need to rotate each billboard quad around the surface normal at the point on the sphere where the tree sits.

Any ideas how to billboard around an arbitrary vector ?

I figure if I answer keep answering these, all billboarding questions will go away If you constrain your billboard to be rotating about only one axis, then the billboard’s normal sweeps out a plane during this rotation. If we project the vector from the camera to the center of the billboard onto this plane, that will be the vector we want to rotate to.

So, here would be pseudo-code. I haven’t tested this, so there will, of course, be mistakes like missing minus signs. But it wouldn’t be fun if I did all the work ‘x’ = vector cross product
‘%’ = vector dot product
‘*’ = regular multiplication

Vector n = billboardNormal;
Vector c = cameraVector - billboardPositionVector;
Vector axis = axis we want to rotate around (i.e. direction of laser travel or sphere normal)
Vector temp;
Vector target;
float angle;

// If not already normalized, do this
n.normalize();
c.normalize();

// First need 2 orthogonal vectors to define a plane. One is n, the other is n x c

temp = n x c;

// Now temp and n define our plane. Project c onto this plane
// This is the sum of the projection of c onto n and temp

target = ((n % c) * n) + ((temp % c) * temp);

// target is the vector we want to rotate the billboard to
angle = acos(target % n) * 180.0 / PI;

glRotatef(angle, axis.x, axis.y, axis.z);

Let me know if this works – Zeno

i dont really know if that helps you, but its a code-sample wich works nicely and perhaps does some help here, too… the idea is simple: create a normalized angle ( as TTvec, here… and then you can rotate around it…:
TTvec r( 0, 1, 0 );
TTvec v( 1, 0, 0 );
r.RotateAroundMe( 90, v, v );

result should be v == ( 0, 0, 1 ) ( or ( 0, 0, -1 )hm… dont know )

perhaps this helps here… who knows? ( not me )

void TTvec::RotateAroundMe(float degrees, TTvec *dst, const TTvec& src)
{
float s = sinf( degrees ), c = cosf( degrees );
float uinvc = 1.f - c;

float xx = x * x, xy = x * y, xz = x * z, yy = y * y, yz = y * z, zz = z * z, xs = x * s, ys = y * s, zs = z * s;

TTvec v;
v.x = src.x * ( uinvc * xx + c ) + src.y * ( uinvc * xy - zs ) + src.z * ( uinvc * xz + ys );
v.y = src.x * ( uinvc * xy + zs ) + src.y * ( uinvc * yy + c ) + src.z * ( uinvc * yz - xs );
v.z = src.x * ( uinvc * xz - ys ) + src.y * ( uinvc * yz + xs ) + src.z * ( uinvc * zz + c );
dst->x = v.x;
dst->y = v.y;
dst->z = v.z;
}

Doh!

As happens too often - I realise how daft I was to even ask Thanks zeno - it was the bit about projecting the view-billboard vector onto the billboard normal plane that was eluding me.

thanks

Rob