Clang with no bang
#11
The fix seems to be playing pretty well with no issues, so I'm ready to pass it on to you guys.  Here's what I did:

In physics.c, do_physics_sim()

Code:
    /* As this engine was not designed for that high FPS as we intend, we use F1_0/30 max. for sim_time to ensure
       scaling and dot products stay accurate and reliable. The object position intended for this frame will be scaled down later,
       after the main collision-loop is done.
       This won't make collision results be equal in all FPS settings, but hopefully more accurate, the higher our FPS are.
    */
    /* This is the wrong approach for making the math accurate, and is causing 0-damage collisions. -- CED */
    sim_time = FrameTime; //PhysTime; //FrameTime;

        . . .  (lots of code here)

        // As sim_time may not base on FrameTime, scale actual object position to get accurate movement
    /*
    if (PhysTime/FrameTime > 0)
    {
        vms_vector md;
        vm_vec_sub(&md, &obj->pos, &start_pos);
        vm_vec_scale(&md, F1_0/((float)PhysTime/FrameTime));
        vm_vec_add(&obj->pos,&start_pos, &md);
        //check for and update correct object segment
        if(!get_seg_masks(&obj->pos, obj->segnum, 0, __FILE__, __LINE__).centermask == 0)
        {
            if (!update_object_seg(obj)) {
                if (!(Game_mode & GM_MULTI))
                    Int3();
                compute_segment_center(&obj->pos,&Segments[obj->segnum]);
                obj->pos.x += objnum;
            }
        }
    }
    */

Running the code to find and deal with collisions at a different step size than the objects are actually moving, and then backing them up after it's been run, makes the results significantly less accurate and is contributing to a few bugs -- the most noticeable of which is the zero-damage gauss shots.  I have reverted the sim_time to FrameTime, and commented out the code for adjusting objects' positions based on the difference between them.

This is the 'modern era' problem I mentioned in the other thread, and applies to both D1 and D2.  It's essentially making pyro hitboxes in multiplayer both large and kinda random, neither of which are effects we want.


The second, original problem, is in fvi.c, check_vector_to_sphere_1(): There's a false assumption.  Essentially, it tries to discard vectors which can't reach the sphere, but it does it comparing the distance between the vector's point of origin and the sphere's radius, and concluding it can't reach if this is larger than the vector's length + the sphere's radius.  Perfectly true, a vector that fails that test can't reach the sphere in question.  Unfortunately, the inverse isn't true; there are vectors that can't reach the sphere that nonetheless pass that test -- they just have to be heading for the edge.

The code assumes any vector which fails that test but which nonetheless is on a path to intersect the sphere must already be inside it, and returns the intersection at the vector's point of origin.  Close, but no cigar; weapons clipping the edge of a sphere are thus reliably detonated some distance away from it, and more frequently at higher framerates. 

What I did to solve the problem was add an extra check; before assuming a vector starts inside a sphere . . . check to see if it's really in there.  If yes, return the intersection.  If no, though . . . return 'no hit', because we're looking at the 'will hit next frame' case.

Code:
        if (int_dist > mag_d || int_dist < 0) {
            //past one or the other end of vector, which means we're inside <-- original comment

            // CED -- BZZZT, WRONG!  Either you're inside OR you didn't quite make it!
            if(vm_vec_dist(p0, sphere_pos) < sphere_rad) {
                *intp = *p0;        //don't move at all

                // Would like to move to edge to avoid messing up damage values,
                // but for some reason this makes you bounce off of powerups you can't pick up
                // I can't figure out why that's happening, so there's a hack in
                // collide_player_and_weapon to handle this case
                //vm_vec_scale_add(intp,p0,&dn,int_dist);   
                return 1;
            } else {
                return 0;
            }
        }

This is the 'original' bug I was talking about in the other thread, the one more likely to be tickled at high framerates.  It is in the 58.1 source, it's on the original D1 source, and it's in the D2 source.  I'm sure I don't need to tell you that a bug in a routine for intersecting vectors and spheres has far-reaching consequences.


That comment about returning a true intersection point for vectors inside the sphere -- In the course of my extensive testing and analysis, I determined that Descent tries to always detonate a blast weapon exactly on the hull of the ship.  The code to modify the intersection point in the weapons collision area actually made it worse, when that point wasn't exactly on the hull.  Somehow -- and I don't know how -- gauss (and other) shots occasionally get a little inside the pyro, doing extra damage because of the closer distance, even though this clearly isn't intended and doesn't happen 90% of the time. 

I wanted to fix it in the intersection routine -- make a rule that the intersection had to be on the surface of the sphere -- but alas, those far-reaching consequences. Wink  So I settled for fixing it where the weapons collide.

This code is a little different for D1 and D2.  In D2, I modify the collision location, since you have it.  In D1, I have to modify the position of the weapon itself.  In both cases, I do it in collide.c collide_player_and_weapon()

D1:
Code:
    if ( Weapon_info[weapon->id].damage_radius ) {
        vms_vector player2weapon;
        vm_vec_sub(&player2weapon, collision_point, &player->pos);
        fix mag = vm_vec_mag(&player2weapon);
        if(mag < player->size && mag > 0) {
            vm_vec_scale_add(collision_point, &player->pos, &player2weapon, fixdiv(player->size, mag));
            weapon->pos.x = collision_point->x;
            weapon->pos.y = collision_point->y;
            weapon->pos.z = collision_point->z;
        }

        explode_badass_weapon(weapon);
    }

D2:
Code:
    if ( Weapon_info[weapon->id].damage_radius ) {
        vms_vector player2weapon;
        vm_vec_sub(&player2weapon, collision_point, &playerobj->pos);
        fix mag = vm_vec_mag(&player2weapon);
        if(mag < playerobj->size && mag > 0) {
            vm_vec_scale_add(collision_point, &playerobj->pos, &player2weapon, fixdiv(playerobj->size, mag));
        }
        
        explode_badass_weapon(weapon,collision_point);

    }


I hope you find that helpful!  Let me know if I can answer any questions about what I did and whether it was a good idea. Smile
Reply
#12
Your analysis is striking as always. Smile

I got to the problem in sphere intersection already. And I noticed the same issue with the powerups - like you noted in the comment of the code. But I am interested: Is this the only consequence you noticed by determining the distance in fvi?

What I however didn't notice so far is you statement about the semi-cap in physics.
You got that right that it contributes to the problem. That's my bad. It solves a few things but it's not straight forward. In fact, if anything - and it would make sense - the whole physics should be capped to a 30FPS behaviour - similar to the homers, interpolating the movement in between. But if I could, I'd try to prevent that, if I can figure out the other problems occurring when FrameTime gets too small. Cause this is what I wanted to prevent in the first place - making wall collisions a walk on nails. That are rusty. And on fire. Poisonous fire.
The greatest pleasure in life is to do what people say you cannot do.
Uhm... Honey, there's a head in the toilet!
Reply
#13
Quote:Your analysis is striking as always.

I appreciate that.  Most of my analysis isn't here, because it's dull -- this time it consisted of printing out the positions of things at various points, the math leading up to it, and scratching my head a lot. Wink


Quote:I got to the problem in sphere intersection already. And I noticed the same issue with the powerups - like you noted in the comment of the code. But I am interested: Is this the only consequence you noticed by determining the distance in fvi?

Yes, but we didn't test it extensively.  As soon as people started bouncing off of powerups, I realized it was foolish to try to rewrite the function's contract in the first place.  I never should have done that, as it's very difficult to predict what the consequences will be.

Granted, doing a total analysis on that is tempting; if weapon collisions are having problems with unexpected answers from that function, who knows what else might be.  And encouragingly, it is only called in one place . . . but the values returned go all over the code from there.

I do feel it's pretty safe and important to switch it from giving the right answer 90% of the time to 100%, precisely because the answers are used in so many places.  Alas, a full analysis of the impact is a bit beyond the scope of the problem I was trying to solve.  But as I said in the other thread, I fully expect the change to banish any number of subtle bugs associated with high framerates that we may or may not have noticed yet, and I will be truly surprised if it breaks anything.


Quote:What I however didn't notice so far is you statement about the semi-cap in physics.
You got that right that it contributes to the problem. That's my bad. It solves a few things but it's not straight forward. In fact, if anything - and it would make sense - the whole physics should be capped to a 30FPS behaviour - similar to the homers, interpolating the movement in between. But if I could, I'd try to prevent that, if I can figure out the other problems occurring when FrameTime gets too small. Cause this is what I wanted to prevent in the first place - making wall collisions a walk on nails. That are rusty. And on fire. Poisonous fire.

I thought that code might be you. Wink

Maybe you can shed some light on what you were trying to solve with it, and I can try attacking the problem directly for you.  Because I can't, at the moment, imagine what good that code might doing, and I can analytically prove that it's doing a lot of bad!  In addition to the gauss bug, it's responsible for three other unrelated bugs: homers behaving inconsistently in the final dodge (seriously annoying high level pilots!), DKH being able to reliably get sparks/no clang and the other way around on a still ship with fusion, and direct hits with smart missiles being too easy to escape.

What were you trying to do?  Are there steps to reproduce the problem?  The comment mentions making dot products and the like more accurate, but that makes no sense to me.  There's a lot of extra precision in those fixints.  Flip mentioned something about getting stuck to walls or corners or some such, but I really didn't get the full story.  If you can point me in the direction of the trouble, I'd be happy to take a look.  Rusty-nails-on-poisonous-fire math bugs are really, really my cup of tea. Wink

I would generally be against running the overall engine at 30 FPS.  The draw of 200 isn't smooth visuals, it's fast response time -- 5ms to your own ship!  If all you want is smooth visuals, you could just cap the game at 80 like d1x did and call it a day.  But smooth control is really quite valuable to a pilot, particularly an elite one.  Raising the cap to 200 was an ambitious project that caused a lot of problems, but I think it was valuable, too, and is something that -- once achieved -- I would hate to see thrown away.
Reply
#14
Quote:Yes, but we didn't test it extensively.  As soon as people started bouncing off of powerups, I realized it was foolish to try to rewrite the function's contract in the first place.  I never should have done that, as it's very difficult to predict what the consequences will be.

Granted, doing a total analysis on that is tempting; if weapon collisions are having problems with unexpected answers from that function, who knows what else might be.  And encouragingly, it is only called in one place . . . but the values returned go all over the code from there.

I do feel it's pretty safe and important to switch it from giving the right answer 90% of the time to 100%, precisely because the answers are used in so many places.  Alas, a full analysis of the impact is a bit beyond the scope of the problem I was trying to solve.  But as I said in the other thread, I fully expect the change to banish any number of subtle bugs associated with high framerates that we may or may not have noticed yet, and I will be truly surprised if it breaks anything.

Yes, based on the fact that the fvi code works on false assumptions, it's safe to assume the game logic builds on that and fixing the problem in fvi caused the logic to fail. The reason I ask is because while I think the check in weapon/player collision is probably okay to keep - even in the long run - we DO change fvi either way and while you just return 1, it's still not 0 - which we assume is what the game is build on to in this case.

I hope I did explain that right.

Bumping off powerups is actually just a very logical conclusion considering there is no real handling for this in the physics code. If HIT_OBJECT is reached you'll collide and bump. It's also interesting to note that physics.c has a handler for powerups - yet disabled. I wonder.

So I think what I am trying to say - we have a changed situation in object/object collision - one or the other way. I would like to see how to proceed best from there. After all your initial attempt was correct.


Quote:Maybe you can shed some light on what you were trying to solve with it, and I can try attacking the problem directly for you.

That code is already a bit older and I hope I can explain it right. In fact I did fiddle with the whole physics/fvi fiasco in the past a lot but I am not an expert with it which is why I also considered a lot of game design tutorials and other game engines to examine the ways and see what's what.

In fact the problem you isolated in the sphere collision isn't the only thing fvi does wrong. With higher FrameTime (which now reflects sim_time) you'll see that with higher frame time wall collisions get increasingly inaccurate. In short: More FPS = slower sliding. Along with some other effects.

Back in the days when I wrote the code I did make a lot of tests to see HOW accurate it is and I still try to find out, why I did NOT find the sphere collision effect. Cause - believe it or not - I DID test that assuming my fix was intended for object/plane not object/object.

Quote:I would generally be against running the overall engine at 30 FPS.  The draw of 200 isn't smooth visuals, it's fast response time -- 5ms to your own ship!  If all you want is smooth visuals, you could just cap the game at 80 like d1x did and call it a day.  But smooth control is really quite valuable to a pilot, and something that -- once achieved -- I would hate to see thrown away.

Indeed this is to consider. And in fact this isn't what I want to change. Like I said, I considered some other projects and lots of literature back in the day. It's surprising how many game engines run their collision/physics at awfully low frames per cycle. More than once these codes are never meant to be scaled but rather executed at fixed times - with interpolated results. Descent uses a lot of text-book code here - which is however never meant to scale to FPS.

The trick is to isolate the time-cap to the collision and interpolate each frame - you don't have to restrict the user input on that either. It can be done each frame. I did that - albeit half-cooked. I used values based in PhysTime to get rid of inaccuracies from high FPS and interpolated the movement. The problem is that the code STILL ran it's collisions in every frame. That's wrong.

Again, I am not talking about capping the controls and response time - jut how often do_physics_sim (and fvi) is called. To get it smooth you can interpolate for every frame. And if that's not accurate it's not that important. It just has to be, when do_physics_sim is due again. How that works - yes, that needs to be tested.

I , however, agree with you saying it would be best to have physics in every frame - especially since Descent isn't demanding in that regard. Like you know me from homers I rathe rhave it properly scaled than capped. But one way or another I have to get back to that code. If cause either if sim_time = PhysTime or sim_time = FrameTime - both isn't doing the job 100% right.

If you want to give it a try, that would be cool. Much appreciated. Smile

EDIT: For note, I double checked the "stick to walls"-fix (fix_illegal_wall_intersection). At least this doesn't (like I said before) not contribute to this problem in any way. It's both physics code but the anti-stick fix is unrelated to the problem.
The greatest pleasure in life is to do what people say you cannot do.
Uhm... Honey, there's a head in the toilet!
Reply
#15
I wouldn't say it was completely unrelated. As soon as you put that collision mod in, this underlaying problem became much more evident.
Reply
#16
No, the fix that gets you from not entering walls (which you addressed in your first post) has nothing to do with the physics frame cap (which Drakona addressed). Both are meant to improve wall-collisions but are unrelated to each other in how they function. I just wanna clear that up to avoid confusion since what I first said: "The code preventing you from entering walls is NOT the problem". That's still true. Thing is probably that both additions happened at the same time - between 0.56 and 0.57. And that's mainly what took me so long. Since these collision bugs were reported after 0.58 I locked between these releases and did not go back to changes of 0.56 immediately.
The greatest pleasure in life is to do what people say you cannot do.
Uhm... Honey, there's a head in the toilet!
Reply
#17
It is not related too much I guess but how about ship to ship collision? It's been quite often that in narrow passages ships are able to pass through each other which doesn't seem to happen with weapon-ship collisions. Same with laggy player, he would be skipping, warping sometimes but his missiles wont. I'm guessing it's because missile has fixed direction (behaviour - homers) and can be displayed (path calculated) locally - client side. I wonder if there is some way to make... position probing more accurate (smooth) to the point when no 'ghost behaviour' (passing through each other) would happen.

Quote:he would be skipping, warping sometimes but his missiles wont
Does it mean that if such warpy player is harder to hit, his homers,smarts will work just fine - like for the others?
Does it create some advantage?
I know we did discuss such case before and you said that it is also hard for such player to hit anyone else, is it still valid for homing weapons?
Practice shows that lossy connections suffer much more on their upload side which means 'sending important packet' is happening more often than 'receiving important packet' (I hope you would give it some thoughts for a while).
I guess that I already know the answer based on gaming experience, I'm looking for confirmation while hoping there is some way to improve things.
Reply
#18
(01-12-2014, 05:36 PM)aqqman link Wrote: position probing more accurate (smooth) to the point when no 'ghost behaviour' (passing through each other) would happen.

My best guess is that this is a result of both players occupying the same space on their own end. Adding movement and lag into it, it just sems like something that might naturally occur from how internet works.
Reply
#19
Ship to Ship is indeed something that is a bit tricky. However this is not necessarily related to the physics code. Buu it's probably for the best to check all object/object collisions also ship vs ship - soon as I get back to the physics code. But there is another thing here.

As it is with the Multiplayer, the ship positions, orientation and velocity come from another player. I already dealt with a bug coming from this when your ship will suddenly get incredibly high damage from another player which is due to the fact that the constant updates still have a small delay. That is as soon as you collide with another player, the physics code would like to "bounce" both objects apart. However even with a ping of a few milliseconds it's possible for a little time-window where your bump-partner sending a positional update which - for him - represents the status before the bump (or he sent before the bump but it arrives on you after the collision). That means you basically get a full collision two times. The result is comparable to the impossible case of two unstoppable objects colliding.

I managed to get the damage effect under control but you can see which implications this brings. Specifically in the case where you describe jumpy movements, your local physics code may be unable to make heads or tails of it and it's possible you might go tru each other. However with regular and reliable updates this SHOULD not happen. But I'll get this on my list. After all the bug Drakona fixed making vulcan shots not affect you, could be responsible for what you describe as well.

For the case of "warping" players:
Positions are always updated. At least they should depending on the PPS setting. This is mainly what PPS does - say how often positional packets are supposed to be sent. If these updates are not regular - packets even in the wrong order - this can result in those jumpy movements.
This however does not affect projectiles. A weapon projectile is just created once. Soon as a FIRE packet reaches you, a projectile will be created on the gun point of the player who fired it. From there it just moves as the weapon data in your game content would move it. I.e. homing missiles from another player move according to the homing routines of your game. So this weapon fire moves like your own - as it's only done by your game.
And is such a jumpy player harder to hit? Probably. Remember: Hits are client controlled. The trick is to shoot not where you SEE the player but where it actually is. Means if the ship of your opponent is jumpy it's probably safe to assume that where you see the ship is not where it actually *is*. If you can predict such jumpy movements - you could use that and try aiming where you assume the player.
However I would say this player hardly has an advantage. Remember I said that fire is created where the player is. So even if that lossy players aim is perfect, chances are he/she will not hit - cause due to his/her false positions on your screen, the weapon fire of this player will be misguided - since it always originates from that ship. And if the ship updates are false, the weapon fire comes from wrong positions, too. So this is a lose/lose scenario for both factions.

It might be wroth analyzing however if such lossy games could be improved. With "-verbose" enabled, the game will also print out traffic statistics. If a lossy player could send me his/her gamelog.txt after such a problematic game - probably even one where the player was removed due to missed packets, I could probably see what could be done - i.e. if this is a problem that can be fixed or if it's really just a bad connection.
The greatest pleasure in life is to do what people say you cannot do.
Uhm... Honey, there's a head in the toilet!
Reply
#20
All that is OK, I get it and I'm fine with it, my concern is - homing weapons: homers, smart blobs,megas. How those behave under such conditions? since they are in my game which runs smooth for me on my PC, they don't suffer any lag when trying to get me. Another thing is: does 'important packet' check only host upload and clients download? If it is, it should also check if client didnt fail to send important update to the host in given minimum time, which is more important in terms of fair multiplayer than the former, because it affects more everyone else not only one player.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)