protected virtual void GenerateBillboardAxes( ref Vector3 x, ref Vector3 y, Billboard bb )
{
// If we're using accurate facing, recalculate camera direction per BB
if ( this.accurateFacing &&
( this.billboardType == BillboardType.Point ||
this.billboardType == BillboardType.OrientedCommon ||
this.billboardType == BillboardType.OrientedSelf ) )
{
// cam -> bb direction
this.camDir = bb.Position - this.camPos;
this.camDir.Normalize();
}
switch ( this.billboardType )
{
case BillboardType.Point:
if ( this.accurateFacing )
{
// Point billboards will have 'up' based on but not equal to cameras
y = this.camQ * Vector3.UnitY;
x = this.camDir.Cross( y );
x.Normalize();
y = x.Cross( this.camDir ); // both normalised already
}
else
{
// Get camera axes for X and Y (depth is irrelevant)
x = this.camQ * Vector3.UnitX;
y = this.camQ * Vector3.UnitY;
}
break;
case BillboardType.OrientedCommon:
// Y-axis is common direction
// X-axis is cross with camera direction
y = this.commonDirection;
x = this.camDir.Cross( y );
x.Normalize();
break;
case BillboardType.OrientedSelf:
// Y-axis is direction
// X-axis is cross with camera direction
// Scale direction first
y = bb.Direction;
x = this.camDir.Cross( y );
x.Normalize();
break;
case BillboardType.PerpendicularCommon:
// X-axis is up-vector cross common direction
// Y-axis is common direction cross X-axis
x = this.commonUpVector.Cross( this.commonDirection );
y = this.commonDirection.Cross( x );
break;
case BillboardType.PerpendicularSelf:
// X-axis is up-vector cross own direction
// Y-axis is own direction cross X-axis
x = this.commonUpVector.Cross( bb.Direction );
x.Normalize();
y = bb.Direction.Cross( x ); // both should be normalised
break;
}
#if NOT
// Default behavior is that billboards are in local node space
// so orientation of camera (in world space) must be reverse-transformed
// into node space to generate the axes
Quaternion invTransform = parentNode.DerivedOrientation.Inverse();
Quaternion camQ = Quaternion.Zero;
switch (billboardType) {
case BillboardType.Point:
// Get camera world axes for X and Y (depth is irrelevant)
camQ = camera.DerivedOrientation;
// Convert into billboard local space
camQ = invTransform * camQ;
x = camQ * Vector3.UnitX;
y = camQ * Vector3.UnitY;
break;
case BillboardType.OrientedCommon:
// Y-axis is common direction
// X-axis is cross with camera direction
y = commonDirection;
y.Normalize();
// Convert into billboard local space
camQ = invTransform * camQ;
x = camQ * camera.DerivedDirection.Cross(y);
x.Normalize();
break;
case BillboardType.OrientedSelf:
// Y-axis is direction
// X-axis is cross with camera direction
y = billboard.Direction;
// Convert into billboard local space
camQ = invTransform * camQ;
x = camQ * camera.DerivedDirection.Cross(y);
x.Normalize();
break;
case BillboardType.PerpendicularCommon:
// X-axis is common direction cross common up vector
// Y-axis is coplanar with common direction and common up vector
x = commonDirection.Cross(commonUpVector);
x.Normalize();
y = x.Cross(commonDirection);
y.Normalize();
break;
case BillboardType.PerpendicularSelf:
// X-axis is direction cross common up vector
// Y-axis is coplanar with direction and common up vector
x = billboard.Direction.Cross(commonUpVector);
x.Normalize();
y = x.Cross(billboard.Direction);
y.Normalize();
break;
}
#endif
}