Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Quasar

3D Object Clipping == Disaster

Recommended Posts

I don't know how it happened exactly, but 3D object clipping is completely broken. Standing on top of an object in a moving sector causes you to be thrown to the floor and stops the sector from moving, making both it and yourself get stuck. Also, getting pressed on by a thing from above will ram you down into the floor.

I have tried for hours upon hours to find a new solution, even going as far as creating a new fork of the source code with all 3D object clipping stripped out and attempting to find a new, more rigorous algorithm for shifting things up and down, but I cannot find a solution. Simple chains of objects aren't sufficient because they can't deal with gaps of open space.

Unless somebody knowledgeable in the domain of this problem comes forward and can help, we are at a deadlock and will have to remove the feature from Eternity until it can be repaired (which could be indefinitely the way things are going right now), so this is a serious request for help.

Share this post


Link to post

I'll help as much as I can, though I never really solved this problem in EDGE to my satisfaction (very tough nut to crack).

When an object in standing on another one, do you keep a pointer to the below object? In EDGE I have both above_mo and below_mo.

The floorz field of the upper object should also be the top of the below_mo (the object below is like solid ground).

You could do the sector move, then "fixup" all affected things so that the height relationships are correct (i.e. floorz of above_mo == below_mo->floorz + below_mo->height).

Another idea: when checking if object X fits, don't use the plain height, but add in the above_mo (and it's above_mo, etc).

Also, some sector moves "widen" the space (floor down, ceiling up), and can therefore use simplified checks (e.g. you wouldn't need the fixup I just described in this case).

Lastly, you can allow objects which are stuck together to move apart (fixing the symptom rather than the cause). In P_TryMove, ignore any objects that are "behind" the current move vector.

I'm happy to discuss this in as much detail as you like (yay for holidays).

Share this post


Link to post

Our very first implementation worked this way and was based on the over/under code taken out of BOOM. However, it had a bunch of problems, such as things' over/under pointers not being properly updated in some circumstances. In retrospect these were probably bugs in the code and not design issues, but I have a question.

Given that one thing could possibly be standing over multiple things while multiple things stand over it, how can a single pointer for each ever accurately model complex situations, such as for example a herd of cacodemons trying to fly over each other? Without an absolutely air-tight handling of every object, they end up stuck together.

To solve this kind of stuff, SoM created an elaborate system that adjusts the floorz and ceilingz of things based on the things around them using the blockmap, and every time a thing moves, it has to update everything around it. The sheer complexity of this system is what has proven to be the nightmare, as it keeps breaking. I'm not entirely sure sector movement has ever been completely correct, but at the moment it doesn't work at all.

Share this post


Link to post
Quasar said:

Without an absolutely air-tight handling of every object, they end up stuck together.

That suggests something fundamental is wrong. EDGE is using such a "loose" system, yet flying monsters can go over other monsters, the player can walk over a bunch of imps, etc, without anything getting stuck together.

A single above_mo/below_mo at least keeps things simple. EDGE computes the new below_mo in PIT_CheckRelThing (btw we split up relative moves and absolute moves like spawning).

BTW, I just noticed EDGE never sets the above_mo. You could probably go without, or at least ensure that thing->below_mo->above_mo = thing.

Managing multiple below objects may be the best way, but is much more complicated of course. I've had an idea though: are you familiar with how the Boom touchnodes work? If not, get familiar with it. You could use the same type of system to implement multiple below/above objects.

Flying monsters can be optimised a little, since they don't need to be supported like gravity-affected things.

Sounds like you need to pull out SoM's code and do your own thing. You can't fix serious problems in code that you don't fully understand. Maybe have a look at the way EDGE and/or ZDoom tackle this problem.

Share this post


Link to post
Ajapted said:

That suggests something fundamental is wrong. EDGE is using such a "loose" system, yet flying monsters can go over other monsters, the player can walk over a bunch of imps, etc, without anything getting stuck together.

A single above_mo/below_mo at least keeps things simple. EDGE computes the new below_mo in PIT_CheckRelThing (btw we split up relative moves and absolute moves like spawning).

BTW, I just noticed EDGE never sets the above_mo. You could probably go without, or at least ensure that thing->below_mo->above_mo = thing.

Managing multiple below objects may be the best way, but is much more complicated of course. I've had an idea though: are you familiar with how the Boom touchnodes work? If not, get familiar with it. You could use the same type of system to implement multiple below/above objects.

Flying monsters can be optimised a little, since they don't need to be supported like gravity-affected things.

Sounds like you need to pull out SoM's code and do your own thing. You can't fix serious problems in code that you don't fully understand. Maybe have a look at the way EDGE and/or ZDoom tackle this problem.


ZDoom's sector movement code has given me some ideas, but unfortunately its basic over/under code is still derived from Hexen so that gives me licensing difficulties. I'm not sure I can (or should) combine Eternity's floorz/ceilingz crap with ZDoom's method of sector movement; I think it would not be guaranteed to work, and we have issues with maintaining the floorz/ceilingz anyways.

The chief problem with our existing system is this. Let's say the player is standing on a barrel, and has a cacodemon over his head. The player moves. The barrel's ceilingz should now be the cacodemon's z level, and the cacodemon's floorz should now be the top of the barrel. How must this be accomplished? The player must do a blockmap traversal and find every object affected by his move. Then every one of these objects must do blockmap traversals to find all objects that set their floorz or ceilingz. A nightmare in and of itself, and since there are so many special cases of movement in DOOM, sometimes it doesn't happen like it should and things get out of sync. The result is something getting stuck or hanging in midair. And when it comes to sector movement, the floorz/ceilingz values are no longer valid and are of no help at all in determining whom must move up or down what, and it's nearly impossible to keep something from being adjusted more than it should be.

So those are the problems with the existing system. Something simpler like you describe is quite tempting, however I fear EDGE has probably gone too "true 3D" to be of direct use to me. We don't have move vectors, for instance. Movements are still split into XY and Z planes and this creates some complication (though manageable I believe, as ZDoom deals with it fine).

Share this post


Link to post

EDGE still has XY and Z movement as separate functions (I always wanted to merge them, but it's not so easy :).

Quasar said:

Let's say the player is standing on a barrel, and has a cacodemon over his head. The player moves. The barrel's ceilingz should now be the cacodemon's z level, and the cacodemon's floorz should now be the top of the barrel. How must this be accomplished?

Does it need to be? For example, does it matter if the barrel has a wrong ceilingz? As for the cacodemon, the correct floorz will be computed the next time it tries to move (even if unsuccessful).

When a monster is standing on the player and the player moves away, the next time it tries to move (3-10 tics) it will get a correct floorz, and hence P_ZMovement will notice he is above the ground and so should drop with gravity. Nobody gets stuck in the air.

If you have above_mo/below_mo fields, and the above_mo (the cacodemon) is going to be set to NULL (player moved out), then you could recompute the cacodemon's floorz. Likewise for below_mo and ceilingz.

SoM's code which recomputes every floorz/ceilingz of every nearby monster sounds way too complicated (and slow). I think a multiple above_mo/below_mo system would be much better, if you wanted 100% robustness.

Share this post


Link to post

One problem with that is that some things never move again. A lamp for example: if dropped onto the player's head by a lift, it will not fall to the ground when the player moves if its floorz isn't updated. This is because it never acquires any z momentum. I have, however, found out how zdoom addresses this issue too.

Anyway, I completely agree. The floorz/ceilingz system has to go.

Right now I'm trying to put in a version of zdoom's system. I'm not sure I'm completely getting around the licensing issue, but I'm trying to reuse code from Eternity as much as possible and will worry about the rest later.

Share this post


Link to post

Can't you make a DLL based on Hexen's code and distribute it separately for use with Eternity, with a license compatible with Raven's?

Share this post


Link to post

No, the GPL doesn't permit linking in commercial libraries. Frankly I think the amount of Raven code left in here is on the order of individual lines. With sufficient further rearrangement it could be completely unrecognizable. Also, so much of it is stuff you can do by using code segments that already exist in the DOOM source (blockmap traversals, secnode traversals, iterator loops), it's hard to see how there can be any claim on it.

I'm no lawyer but doesn't a work have to have original substance to be subject to copyright? :P (This is not an invitation to start one of those copyright issues flame wars so everybody reholster the guns).

Share this post


Link to post

A company or group can claim copyright to whole sections or documents of code but single lines and fragments cannot, as it is not considered unique.

Share this post


Link to post
Quasar said:

No, the GPL doesn't permit linking in commercial libraries. Frankly I think the amount of Raven code left in here is on the order of individual lines.



Does it really matter? No matter how you twist it, much of Heretic's code pointers in Eternity are already problematic concerning the license. Since much of that code looks exactly the same as the original it is really irrelevant whether you coded them separately. The functions even have the same names and they perform the same actions so in the (purely hypothetical) case that your code was ever analyzed for license conformance it would already fail there.

Which brings us back to the GPL. Frankly, I hate this license due to this 'all inclusive' clause. As a result from this I wouldn't ever release any code under it. I'd prefer the LGPL but in the case of Doom that's unfortunately not possible.

Share this post


Link to post

I'm working on replacing as much of it as possible, but the problem is there's only one way to do a lot of that stuff and it's the same way as Raven did it, so you can see the problem :/

Example: Knight attack. Shoot one of two axes or do a melee attack. Doom's only got one set of functions for all of that stuff.

But yes you're right, EE does have some strict GPL compliance issues due to use of some Raven code. I've never denied it, I'd just like to get it ironed out if possible . And if it's not, well... I dunno.

I've completed integrating zdoom's 3D clipping. It seems to work after some initial difficulties getting it to work with some MBF features like touchy things, so hopefully this little crisis is coming to a close.

Share this post


Link to post

Quasar said:
I've completed integrating zdoom's 3D clipping. It seems to work after some initial difficulties getting it to work with some MBF features like touchy things, so hopefully this little crisis is coming to a close.


When you have a new build, can you post the compiled binary as well instead of only making it available through SVN (which Joe did lately)? With the amount of playtesting I do on the same maps, bugs or oddities are very well noticed.

Share this post


Link to post
Quasar said:

with some MBF features like touchy things.



... which reminds me that this is something I always wanted to add to ZDoom as well but never found the time...

Share this post


Link to post

They require a bit of a hack to work with the 3D clipping. You have to push the player up with some z momentum if he runs on top of them, and you also have to disallow the player to walk into them while they're dying (ie health <= 0 but MF_SOLID hasn't been cleared yet). Otherwise you can walk through them all the time due to the fact that as soon as you touch them, they acquire the MF_CORPSE flag. Those are things to keep in mind if you decide to put them in ZDoom :)

Share this post


Link to post

I would like to say that my could would probably have worked 100% of the stupid object clipping funcions originally in doom didn't use globals and could recurse. In this case the code would have functioned sort of like the BSP algo. But as it stands, my code could never work 100%... :(

Share this post


Link to post

Actually one of the main problems is that we weren't splitting up the different kinds of sector plane movement fully enough. In ZDoom Randy's created different iterator functions for floor up, floor down, ceiling up, and ceiling down. This does however create a bit of a quandry for 3DMidTex -- you gotta treat the move as both a floor and a ceiling move because, for example, a move down needs to move stuff on top down but be blocked by things below. I fixed this up just tonight and it seems to be airtight now.

I had to make everything behave as though it has the PASSMOBJ ZDoom flag, however. Is there any particular reason ZDoom doesn't treat everything fully 3D or is it just a design decision? Non-PASSMOBJ things didn't work in the presence of 3DMidTex at all and caused lots of bad glitches (such as suddenly ending up stuck inside a lamp screaming like you're falling and getting hurt like you're being crushed ?!?!?!)

Share this post


Link to post
Quasar said:

I had to make everything behave as though it has the PASSMOBJ ZDoom flag, however. Is there any particular reason ZDoom doesn't treat everything fully 3D or is it just a design decision? Non-PASSMOBJ things didn't work in the presence of 3DMidTex at all and caused lots of bad glitches (such as suddenly ending up stuck inside a lamp screaming like you're falling and getting hurt like you're being crushed ?!?!?!)


The reason this flag still exists is mostly that many, many maps have things overlap. A good example are the many torches in P:AR's E1M6. Since ZDoom's code tries to separate overlapping things when a sector move takes place they didn't behave properly without this flag.

Share this post


Link to post
Graf Zahl said:

The reason this flag still exists is mostly that many, many maps have things overlap. A good example are the many torches in P:AR's E1M6. Since ZDoom's code tries to separate overlapping things when a sector move takes place they didn't behave properly without this flag.

Oh, haha I remember something like that happening in Lutz's Millennium boss map. A torch pillar arises and I wondered why, in ZDoom, all the torches suddenly exploded into a tower of their own. Would've been a great 'feature' in a joke map.

Share this post


Link to post

Quasar said:
Stuff about TOUCHY flag


I've found that this tag is mostly suited for non-solid things, like a mine you can walk over. For solid (sentient) things you really have to push into them before the touchy flag gets triggered.

I guess you can get a better result with a flag that checks against things being in melee range.

Graf Zahl said:
The reason this flag still exists is mostly that many, many maps have things overlap.


Important to notice is that things overlap is NOT an unwanted glitch, but can/will be used as a design feature. You'll have to allow for things overlap, so only try to correct it in cases when it's really obvious that it shouldn't be happening (moving sentient things during gameplay).

Share this post


Link to post

Mordeth said:


I've found that this tag is mostly suited for non-solid things, like a mine you can walk over. For solid (sentient) things you really have to push into them before the touchy flag gets triggered.

I guess you can get a better result with a flag that checks against things being in melee range.
[/B]


Indeed. After some analysis I really can't see much use in it. And checking for things in melee range can easily be done with A_Look/A_Chase and entering the meleestate. This is an old trick that has been used by some vanilla-compatible Dehacked patches already.



Important to notice is that things overlap is NOT an unwanted glitch, but can/will be used as a design feature. You'll have to allow for things overlap, so only try to correct it in cases when it's really obvious that it shouldn't be happening (moving sentient things during gameplay).


And that's why the flag is still there in ZDoom.

Share this post


Link to post

Haha. If you want some more, here's a feature that ZDoom could easily add. I tried it on a complete whim and it works.

         if(!(onmo = P_GetThingUnder(mobj)))
         {
            P_ZMovement(mobj);
            mobj->intflags &= ~MIF_ONMOBJ;
         }
         else
         {
            // haleyjd: Here is where to put code for burning somebody's
            // feet when they stand on a hot object like a torch!
            // Hack to test:
            if(onmo->type == E_ThingNumForName("FireBrazier"))
               P_DamageMobj(mobj, onmo, onmo, 2, MOD_UNKNOWN);
That code segment is in P_MobjThinker, in case my changes make it hard to recognize (I doubt it). With the proper fields (an "overdamage" or something similar) you could allow customizable burn damage for standing on top of things.

Share this post


Link to post
Mordeth said:

I've found that this tag is mostly suited for non-solid things, like a mine you can walk over. For solid (sentient) things you really have to push into them before the touchy flag gets triggered.

I guess you can get a better result with a flag that checks against things being in melee range.

Important to notice is that things overlap is NOT an unwanted glitch, but can/will be used as a design feature. You'll have to allow for things overlap, so only try to correct it in cases when it's really obvious that it shouldn't be happening (moving sentient things during gameplay).


TOUCHY objects can have new use along with 3D object clipping, however. With "bridge" style objects, you can make a "falling bridge" Castlevania-style that explodes as the player runs across it. I like running across rows of touchy barrels, making them explode in my wake. It's a rush.

Share this post


Link to post
Quasar said:

Haha. If you want some more, here's a feature that ZDoom could easily add. I tried it on a complete whim and it works.

         if(!(onmo = P_GetThingUnder(mobj)))
         {
            P_ZMovement(mobj);
            mobj->intflags &= ~MIF_ONMOBJ;
         }
         else
         {
            // haleyjd: Here is where to put code for burning somebody's
            // feet when they stand on a hot object like a torch!
            // Hack to test:
            if(onmo->type == E_ThingNumForName("FireBrazier"))
               P_DamageMobj(mobj, onmo, onmo, 2, MOD_UNKNOWN);
That code segment is in P_MobjThinker, in case my changes make it hard to recognize (I doubt it). With the proper fields (an "overdamage" or something similar) you could allow customizable burn damage for standing on top of things.



Nice idea. ;)

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×