PDA

View Full Version : billboarded line



Jan
04-04-2003, 07:49 AM
Ok, i think some of you have played Jedi Knight 2. When one lets the triangles be displayed, then one can see how they have done the lightsaber:

To create the flare around the blade, they use around 30 billboards.
However for the core they use only one texture which is size 64*256.

Now i am curious how they align this texture. Aligning a quad is easy, since you only have one center and create a billboard from that. But a line needs two "centers". And imagine you look exactly along that line, then there is no solution for aligning it (although you could check for that possibility and donīt draw it at all).

So, i would be interessted in the maths, which you need to billboard a line.

Jan.

amerio
04-04-2003, 09:35 AM
Here is one way to do this :
Let p0-p1 be the 2 end points of your segment to be "billboarded"
You will draw a segment along u = (p1-p0).normalized() (u=unit vector)
Let 'front' be the front vector (or 'lookat') of the view matrix (the camera is looking in the 'front' direction). It is the 3rd row (or column, just check this) of the camera matrix.
You now build the points
m0=p0+(u^front)*radius
m1=p1+(u^front)*radius
m2=p0-(u^front)*radius
m3=p1-(u^front)*radius
Et voila : m0-m1-m3-m2 is the quad you are looking for.

Jan
04-04-2003, 09:53 AM
Sounds good.

But one question: What do you mean with "u^front" ? I would expect it to be the cross product, but i am not sure.

Anyway, thanks a lot !

Jan.

amerio
04-04-2003, 10:00 PM
Yes, 'u^front' is the cross product. (I overloaded the ^ operator, just don't forget the enclosing parentesis ;> )
I use this 'billboarded line' technique a lot, for example for lasers, but also for smoke trails ! Instead of just two points, use a segments-array, and average the 'm' points between successive segments. Works great for me.

Coluna
04-05-2003, 03:24 PM
Hi guys,
I'm doing that this way:

glGetFloatv(GL_MODELVIEW_MATRIX, mat);
mat.Transpose(tmat);
VECTOR3D front(tmat[8],tmat[9],tmat[10]);

to get the front vector. Is it right or i dont need to calculate the transpose matrix, just get the values from the original? And amerio, could you send me a link to an demonstration of your laser-billboarding-line program ( with source hehehe)?
Thanx

Korval
04-05-2003, 05:24 PM
There's an article (and demo) on nVidia's site about "1D Point Sprites", which is the same concept. You pass 2 points that define a rectangle. This one, however, also chooses which piece of the texture to use based on the distance (in screen space) between the two points. Think of it as a 3D imposter optimized for cylindrical objects. Because a cylinder looks the same as long as the two endpoints are at the same distance in screen space, all you need to select a different image is the distance.

Granted, this works best for transparent 3D cylindrical objects. But the 1D point sprite demo does some very amazing things with very simple rules.

Jan
04-06-2003, 07:12 AM
@amerio Your explanation was very very useful to me. With that i got it working.
However i found out, that my laser wasnīt always oriented to the camera how i expected it to be. And it was rotating when i look up and down, which was definitely recognizable for the viewer.

So i played a bit around and found a way, which yields to even better results in my opinion.

@Colune here is my code, get happy with it ;-)

void CAMERA3D::CreateBillboardLine (VECTOR3Df vCenters[2], float fHalfSize, VECTOR3Df vCorners[4])
{
VECTOR3Df normal = vCenters[1] - vCenters[0];

VECTOR3Df CameraToLine = vCenters[0] - m_vCameraPosition;

VECTOR3Df side = normal.Cross (CameraToLine);

side.Normalize ();
side *= fHalfSize;

vCorners[0] = vCenters[0] - side;
vCorners[1] = vCenters[0] + side;
vCorners[2] = vCenters[1] + side;
vCorners[3] = vCenters[1] - side;
}

Jan.

[This message has been edited by Jan2000 (edited 04-06-2003).]

amerio
04-07-2003, 12:05 AM
Your code is <<almost>> what I proposed.
Actually, if your focal is short, or if both points are near the center, then both solutions should give the same quad.
Yet, with a large focal or points far from the center of the view, you may see artifacts. It's up to you to choose the prefered solution.
If you want an always working (yet more costly), just compute 'front' like you did (camera to vertex), but for EVERY point (begin and end point, not just begin point like you did)

Coluna
04-07-2003, 07:09 PM
Jan2000, and what if you rotate your cam around an axis? Its position doesnt change,the vertexes are still the same and some artifacts come up....I think u should use the front vector, as amerio sais, from the view matrix...but i tried out a lot of implementations, and no one worked great...if one of you find a "perfect" code, please show us...I'm gonna check some books in my university, and if i got one working code i'll put it here...see u