In the game i’m currently working I have developed a system for allowing high speed updating of Line of Sight and also a Fog of War to represent the visiblity of the local players line of sight.
I will try to share some of the experience I had developing this, starting out with the realtime updated Line of Sight.

I started out with thinking about the factors I had to keep in mind when designing the system. Some of these factors is that it has to support 2 players with up to 100 interactive objects each. All these objects needs to know if they can see the opponents objects. Some levels has over 500 objects to block the sight, meaning I have to do some superfast raytesting. With a framerate of 60FPS, each frame can take as much as a maximum for 16MS to calculate before the game would start dropping in FPS and the player would notice “lagspikes”.
So what obvious optimizations can we think of?
1. If I see you, you see me to, right? In most cases yes, it might be some abilities or visiblityfields restricting this rule, but we can add this on later. The first phase of updating the Line of Sight is to do the raytesting and by enforcing this rule we can cut these tests down to the half.
2. In some cases you might not need to know exactly which object can see which object, it might be enought to know if one in the players team can see the other soldier and you don’t need to do more tests on it. This does not work in my case though. I need to know exactly which object each object can see. I some cases one needs to fire upon another and then I can just go and look in earlier collected data if the target acually is in line of sight instead of having to do a new test.
3. One important thing is to not update objects that don’t need to be updated. This can be a bit tricky though when making use of rule 1. For example Obj1 Sees Obj2 and vice versa. Then if Obj1 one moves and needs to update it’s line of sight we must also keep in mind that Obj2 might not see Obj1 anymore. The safe procedures to follow is to keep an boolean in each object to tell if it’s line of sight needs to be updated or not. Once this is changed we need iterate through all objects that sees this object and remove itself from their lists before trying it’s line of sight towards them again.
4. When doing the raytest between two objects to see if another object is blocking the line we might wan’t to think about if we can get the amount of objects to test against down some how. Maybe by checking range, altitude or any other case/state that would remove them from the testing. I will go into this more in detail later on using volumizing.
5. What typ of tests can we do, do we have to do per vertex or is it possible to go for boundingbox or boundingsphere? how about hitboxes? Don’t use more advanced tests then necesarry. Some objects might need per vertex but a house might settle with a boundingboxtest.
These rules are a couple of those i’m using. They might not fit into your game and you might have oppertunities to use other rules. You have to think of every case of scenario where you can in some how cut down on the amount of raytests. Ask yourself following: “When do one object NOT need to be testet against?”
The procedures i follow to update the line of sight in my game is as follows:
1. Make all opponent objects invisible.
2. Run through all objects and check if their line of sight is outdated. If so then remove itself from the LOS-lists of all objects and then do a test again each one of them. If they are spotted then add itself to their list aswell as add them to its own list.
3. Run through the lists of all of my objects and make the opponents visible if their not already visible. Also check for specialcases such as maximumrange, stealth etc etc.
I will know talk about two more general optimizations that will work in almost every case of game and make a huge difference.
Volumizing
When a Raytests is being sent between two objects it means that it might have to test if all objects in the scene is blocking the path. This is totaly unnecessary. There is tons of techniques of cutting down the amount of objects to test against depending on each special case and how optimized it has to be done. Words to google for would be: “Octree”, “Quadtree” and ”Bounding volumes”. I will present my own touch of techniques here:

I simply precalculate a xy-grid( I’m lucky to not have to keep z-axis in mind in my game) of large boundinboxes covering the whole level. These boundingboxes contains a list of objects located inside the larger boundingbox. Once I do a test I can use these to calculate which meshes I need to test against. This can save a HUGE amount of tests.
Here is a 16×16 grid calculated using VB.net, this is not a complete sample, you will have to figure out where to allocate some variables and such simple stuff by yourself but it will be obvious.
‘ Allocate memory in a 2D array
VolumePrecision = 16 ‘ 16×16
Volume2DArray( VolumePrecision, VolumePrecision )
‘ Compute volumesizes
dim VolumeDepth = LevelDepth / VolumePrecision
dim VolumeWidth = LevelWidth / VolumePrecision
‘ Compute the volumes
For x = 0 to VolumePrecision
For y = 0 to VolymePrecisionThats it for the precomputing part!
‘ This is a simple class, you will understand how to create it.
Dim Obj as cVolumeObject = new cVolumeObject
‘ Compute Volumeboundings
Obj.Min.x = (x * VolumeWidth) – (LandWidth * 0.5F)
Obj.Min.z = (y * volumeDepth) – (LandDepth * 0.5F)
Obj.Min.y = 0
Obj.Max.x = ( (x + 1) * VolumeWidth) – (LandWidth * 0.5F)
Obj.Max.z = ( (y + 1) * VolumeDepth) – (LandDepth * 0.5F)
Obj.Max.y = 0
‘ Loop through all meshe sin the scene and do a AABB test, you can google this if you don’t know how to.
…. your code
.. if collision accurs add the obect to the volume, for example:
Obj.AddObject( CollidedObject )
Volume2DArray(x,y) = Obj
Next
Next
Now you need to make use of it. This time during runtime. The procedure is to calculate the length between the start and the end destination and then run through the boundingvolumes one by one in the order of the direction, meaning that the probability of a collision is bigger closer to the startingposition and if a collision accurs there, then we don’t have to continue testing beacuse the line of sight is already blocked.
Here’s a sample for the RaytracingFunction in Vb.net
‘ Calculate number of possible volumes to test
Dim LengthVec As Vector2 = StartVec – EndVec
Dim Length As Single = Math.Length(LengthVec)
Dim NumSteps As Integer = 1 + CInt(Length/min(VolumeWidth,VolumeHeight))That’s it!
You will certainly notice a difference in time to do a test.
Here is some results from my tests(big collisiontest for Fog of War based on Line of Sight)
‘ Calculate the direction of the testing
Dim DirVec As Vector2 = LengthVec / NumSteps
‘ Initiate testing
For CurrStep as Integer = 0 To NumSteps
‘ Calculate the arrayposition, this is faster then iterating
Dim x As Integer = CInt((StartVec.x – (CSng(CurrStep) * DirVec.x) * LandWidth * 0.5F) / min(VolumeWidth,VolumeHeight)
Dim y As Integer = CInt((StartVec.y – (CSng(CurrStep) * DirVec.y) * LandDepth * 0.5F) / min(VolumeWidth,VolumeHeight)
Dim E as IEnumerator = VolumeArray2D(x,y)
While(E.MoveNExt())
‘ If collision then we can return, the line of sight is blocked!
…. Your collisiontest here.
If Collision(Start, End)
Return true
End If
End While
End If
Next
‘ If we reach this point then there was nothing plocking the sight
return false
No boundingvolumes: 40 576 MS
24×24 boundingvolumes: 10208 MS
28x28x boundingvolumes: 8064 MS
40x40x boundingvolumes: 8448 MS
Multithreading ( + a little info about my Fog of War )
Okey, another thing that you can do if you like to optimize the line of sight further more or if you wan’t to precalculate a line of sight based Fog of War as i did is to implement Multi threading, it’s really simple using VB.net or pthreads in c++.
For a Fog of War it’s not enought to test the line of sight between opponents, it need’s to be tested against ALL terrain, well it needs to be accurate enought to be pleasent to look at and make use of.
This need’s some heavy precalculation. You can’t update it in realtime, it would drop the FPS to the bottom. The way I solved it was to precompute a 72×72 grid on the landscape of the level and did tests between each of them. This needed tons of optimizations to be pleasent to wait for but It’s another chapter. The point is that I implemented Multithreading here and it saved cut the testresults down from 8000 MS to 5000 MS on my dualcore. It’s almost 50%.
You should really look into it. What you do is that you create a couple of extra threads to run some heavy calculations and in the mainthread you just sleep and lets it wait for all the newly created threads to be completed and then you make use of the data they worked up for you. This is how you should use multithreading, to compute heavy CPU-loaded content. You might accually want to run the Line of Sight updating in a sepate thread for the entire game. I will probably implement that. Then It wont affect the other parts of the game either if it would against all odds cause a lagspike.
That’s all, I hope you learned something. I did when I researched this