Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Professional Discussion / [Tutorial] Axially Aligned Billboards (eg gunshot particle trails)

Author
Message
Aralox
19
Years of Service
User Offline
Joined: 16th Jan 2007
Location: Melbourne
Posted: 30th Sep 2010 14:54 Edited at: 30th Sep 2010 14:55
Hey guys, someone asked for this a long time ago (http://forum.thegamecreators.com/?m=forum_view&t=25481&b=1), and since i havent been able to find any answers to this question, i wrote a tutorial.

So what is an axially aligned billboard you ask? It is a regular billboard (essentially a textured plane which always faces the camera) but instead of rotating around a point, it rotates about its own arbitary axis to face the camera. This is useful for depicting the smoke trail of a gunshot, and lasers. (eg the laser shots we see released from the barrel of a storm trooper's blaster in SWBF2 are axially-aligned planes)

Here are a few useful links:
http://nehe.gamedev.net/data/articles/article.asp?article=19
http://www.flipcode.com/archives/Billboarding-Excerpt_From_iReal-Time_Renderingi_2E.shtml

They help with getting your mind around the general idea, but i struggled with their mathematical explanations, and couldnt figure out how they managed to make the billboard 'face the camera' using matrices.

After some deep pondering, I had a eureka moment at about 1 am and figured out that 'to face the camera' mathematically meant that the billboard's normal has to fit in the plane formed by the view and billboard tangent vectors (henceforth the Viewplane). I might post up a diagram later if people are interested in this and want me to, but this shouldnt be too hard to visualise. (Ultimately, this is only my opinion on what 'facing the camera' means; but I like it, so ill stick with it. )

How to actually go about doing this was a bit complex. At first I found the cross product of the viewplane and the plane normal and tried to get the angle between the billboard's normal and this vector in order to match the normal to it; but as anyone who has dabbled in angles will know, angles are not friendly. (cue - someone mentions EZrotate) Due to some annoying camera-under-billboard problems, i tried changing the camera coordinates to coordinates relating to the billboard using matrices (vector change of basis), but to cut a long story short, i decided that the fastest and easiest method to understand/implement would be to rotate the billboard to fit the viewplane by trial and error.

This screenie doesnt really do the program justice, as you dont see the billboards rotating to face the camera.



The following is in the code below, but ill mention it here for anyone who wants to know at a glance how hard this program works.

As a summary, what is done each game loop that is mathematically significant/intensive FOR EACH BILLBOARD is:
- A normalization (view vector)
- A cross product (V cross Tangent)
- An initial dot product
- If the camera is moving (very likely), which would mean the billboards have to realign themselves:
- A dot product for each iteration (approx 5-10 iterations)
(- a roll object command)

And here is the real tutorial (see the handleShotBoards() function)

I can handle about 70 billboards with very little fps loss (from 450 running nothing at all to about 380). This is very good, considering that in a proper game, only about 20-30 billboards would be in existance at any one time.
Note on optimisation: It would be quite easy and beneficial to check if a billboard is visible before running calculations on it.

Thank you for reading this, and I hope it helps someone. It certainly helped me in the creation of it.
Aralox



http://www.freewebs.com/aralox/
dark coder
23
Years of Service
User Offline
Joined: 6th Oct 2002
Location: Japan
Posted: 30th Sep 2010 18:26
Interesting, however, doing iterations like that is computationally expensive when the target direction can be found in constant time. I understand that rotating the object using Euler angles for such a task is a massive mess, but it still means your method has a large overhead. There's a 'best of both worlds' scenario I use in my current GDK library, whereby I use a single object for all of my billboard lines(thus rendering is very rapid), but to handle all the planes like this I must edit the vertex data of the object. But this isn't a bad thing, as it allows me to do the simple calculation of the cross product between the camera-to-line and lineA-lineB normalized vectors and simply write the positions without having to mess with angles. So that may be worth looking into.

Also, using the above method you can easily modify it to create ribbon trails, and as the billboards are contained within a single object, you can easily have multiple ribbons being drawn per object, thus also very fast(because lots of objects in DBPro = slow).

Aralox
19
Years of Service
User Offline
Joined: 16th Jan 2007
Location: Melbourne
Posted: 1st Oct 2010 03:13
I would love to know how to simplify this task to manipulating vertices!
How do you mean that the target can be found in constant time? (I don't know anything about 'constant time', just whats on wikipedia)
How do you make the object actually rotate using vertexdata commands? I had a go at writing one using them, but set vertexdata normals affects the vertex, but not the plane on a whole. (A perfect command would be 'set object normals')
And one more question - when you say that you use one object to hndle all the planes, do you mean using a limb for each plane?

Thanks for the reply dark coder - I love knowing theres a better way to do this, and I really want to find out how to pull it off
Aralox



http://www.freewebs.com/aralox/
SH4773R
16
Years of Service
User Offline
Joined: 18th Jan 2010
Location: AMERICA!!!
Posted: 1st Oct 2010 04:05
If u had dark physics couldent u just attach a partical emmiter to a object? Oh ya, wouldent that be really heavy on the engine?
dark coder
23
Years of Service
User Offline
Joined: 6th Oct 2002
Location: Japan
Posted: 1st Oct 2010 05:30
Quote: "How do you mean that the target can be found in constant time? (I don't know anything about 'constant time', just whats on wikipedia)"


I mean that the solution can be calculated in a specific set of commands, your code uses a loop with a variable amount of iterations to find the final angle(which can still be off by one degree). Thus the speed of your algorithm depends on the angle of the billboards, so there is a differing best and worst case scenario.


Quote: "How do you make the object actually rotate using vertexdata commands? I had a go at writing one using them, but set vertexdata normals affects the vertex, but not the plane on a whole. (A perfect command would be 'set object normals')"


A plane is just 4 vertices, so you just need to move all 4 and you've moved your plane. This requires a basic understanding of vertex data and index data:

Basically, say you have index data for 2 triangles(2tris*3verts = 6 indices) and you have 4 vertices(one in each corner). You begin by specifying which vertex is which corner, in my case 0 is top-left, 1 is top-right, 2 is bottom-left and 3 is thus bottom-right, where the top is the front of the line and the bottom is the back. I then order my indices as such: 0,1,2, 2,1,3. Which if you draw on paper you'll see creates two clockwise triangles where the triangle split goes from top-right to bottom-left.

Now, you can just position the vertices so the first two vertices are at the end of the line and the latter two are at the back and if you enable wireframe you'll see a 3D line. It's now just a case of finding: offset = crossProduct( normalize(cameraPos-pointA), normalize(pointA-pointB) ) then you just need to add this to the positions of vertices 0 and 2 and subtract it from 1 and 3 and you'll have a 3D billboard that rotates to the camera!

Repeat this for all the active lines(make sure you increment the index data for each plane) and you'll have some pretty efficient billboard lines.

Neuro Fuzzy
18
Years of Service
User Offline
Joined: 11th Jun 2007
Location:
Posted: 1st Oct 2010 07:05
Quote: "as it allows me to do the simple calculation of the cross product between the camera-to-line and lineA-lineB normalized vectors and simply write the positions without having to mess with angles. So that may be worth looking into."


!!! That's a great idea! Definitely the way to go.

Another way (that would be a pain to do in DBPro but useful if you were managing the rendering code) you could transform a point to screen space, and paste an image there, keeping z depth in mind (and z distance for proper scaling). I would imagine that would be faster if you had access to that kind of poking and prodding.

Aralox
19
Years of Service
User Offline
Joined: 16th Jan 2007
Location: Melbourne
Posted: 1st Oct 2010 15:07
Darkcoder, that is really brilliant.
This reply is so late because I wanted to go and learn about indices and vertices (from one of your posts here on the forums, as it happens) before I tried your idea. I actually get what you're talking about now, and its really quite smart - you just move the vertices in the direcion of the 'view plane' normal, thus creating an 'face normal' which fits in the view plane.

I wrote a simple program that implements your idea - (its very messy and can probably be written with much less lines.)



But before I alter my tutorial, there are a few things I need help with:
1. When I positioned the vertices in the plane, I had to inverse the x and z components of the position vector. Why is this? Is it because DBP has some kind of default rotation on a plane primitive? (I did convert the world position to the plane's object space just to make things clear to myself but I know its unnecessary as the plane 'object' is at 0,0,0)

2. The plane disappears when the point 0,0,0 is out of the camera's viewport. My guess is that the vertex positions havent been properly updated and the camera thinks the whole plane object is out of the screen. How do i fix this?

Thanks,
Aralox



http://www.freewebs.com/aralox/
Sven B
21
Years of Service
User Offline
Joined: 5th Jan 2005
Location: Belgium
Posted: 1st Oct 2010 19:00
Quote: "2. The plane disappears when the point 0,0,0 is out of the camera's viewport. My guess is that the vertex positions havent been properly updated and the camera thinks the whole plane object is out of the screen. How do i fix this?"


You might be able to position the vertices relative to their mid point, and then position the object as a whole.

Cheers!
Sven B

revenant chaos
DBPro Master
19
Years of Service
User Offline
Joined: 21st Mar 2007
Location: Robbinsdale, MN
Posted: 2nd Oct 2010 03:28
You could also use calculate object bounds after manipulating the vertices, but this should only be done after the object changes size.
Aralox
19
Years of Service
User Offline
Joined: 16th Jan 2007
Location: Melbourne
Posted: 2nd Oct 2010 05:09
Thanks for the suggestions.
@Sven B: Im not sure if I want to manipulate the object on a whole; darkcoder mentioned that using a single object for his billboards was faster - so I intend on using a different limb (with a plane mesh) for each billboard. Also, even if i did do that, I have a feeling that dbp would still think that the vertices' positions have not changed, which would mean my billboard is culled when its midpoint is slightly out of the camera's frustum (depending on the plane size)

@revenant chaos: That worked perfectly thanks. (I only had to call this after positioning the vertices initially, not in a loop.)



http://www.freewebs.com/aralox/

Login to post a reply

Server time is: 2026-06-10 05:51:59
Your offset time is: 2026-06-10 05:51:59