Bug #818516 - Multiple Overlapping Items
<i>This post was originally made by <b>danij</b> on the dengDevs blog. It was posted under the categories: Beta 6, Games, jDoom, jHeretic, jHexen, Version 1.9.</i>
Yesterday I thought I'd have a go at implementing something to address this particular issue (see <a href="http://sourceforge.net/tracker/index.php?func=detail&aid=818516&group_id=74815&atid=542099">bug report</a>).
The plan is to bundle together objects of the same type when close enough together that we would like to consider them as one object for rendering purposes.
As mobjs can be spawned at any time and there is no prior warning about them moving I came to the conclusion that a mechanism for this which happened as a byproduct of <tt>P_MobjSetPosition</tt> was probably the best bet.
Here is what I came up with (in unidiff format): <a href='http://www.dengine.net/blog/wp-content/uploads/2008/07/overlappingmobjsdiff.txt'>overlappingmobjsdiff</a>
Now, there remains an issue in the above code in that we should bundle based on distance from an averaged position among all mobjs in the proposed bundle. However, I'm more interested at this stage in getting feedback on the approach used and whether this is the "Right Way" to handle this.
Yesterday I thought I'd have a go at implementing something to address this particular issue (see <a href="http://sourceforge.net/tracker/index.php?func=detail&aid=818516&group_id=74815&atid=542099">bug report</a>).
The plan is to bundle together objects of the same type when close enough together that we would like to consider them as one object for rendering purposes.
As mobjs can be spawned at any time and there is no prior warning about them moving I came to the conclusion that a mechanism for this which happened as a byproduct of <tt>P_MobjSetPosition</tt> was probably the best bet.
Here is what I came up with (in unidiff format): <a href='http://www.dengine.net/blog/wp-content/uploads/2008/07/overlappingmobjsdiff.txt'>overlappingmobjsdiff</a>
Now, there remains an issue in the above code in that we should bundle based on distance from an averaged position among all mobjs in the proposed bundle. However, I'm more interested at this stage in getting feedback on the approach used and whether this is the "Right Way" to handle this.
Comments
While this adds some extra burden to the vismobj collection, the good part is that only the mobjs in the visible sectors get processed. The overhead of checking the coordinates shouldn't be too massive, especially if the blockmap is also utilized to rule obvious non-matches. Or something like this? This would require no changes at all to the game code.
On the other hand, if you prefer to handle this gameside, I would do it at the map loading phase, not during actual gameplay. (Which avoids the time-criticalness issue.) At least the original bug report was regarding the cases where a map author has placed multiple items in the same place, not when multiple items are spawned at runtime in the same place. Although the issue here is that the games must be modified to understand that a single item can sometimes have a stronger effect than normally, depending on the bundling.
Actually, doing this when building/sorting the vissprites might not be a bad idea except the question then is "How does the engine know which vismobjs should be bundled, or does it not matter?". Note though that there are other things to consider, like the mobj shadows which arn't currently produced for vissprites but for sector-linked mobjs.
However given that sorting the vissprites is already a fairly costly task, I would prefer to only do the bundling when necessary (mobjs have moved).
I have no preference as to whether we do this game-side or engine-side. It could be argued that it belongs on either side really.
I did consider whether to actually change the game-side handling of items so that the amount given on collection is an attribute of the mobj (e.g. AMMOBOX * 4) as a consequence of the bundling and then actually remove the other mobjs. However, that means that all games would need to implement the same handling and I just thought it would make more sense given that we only need this for rendering purposes not to change the game code around too much.