Move/Jump problem.

View previous topic View next topic Go down

Move/Jump problem.

Post by S33m3 on Sun Jul 17, 2011 1:40 pm

'lo !

Just installed your last version.
I did it first on my (low-end) desktop, and the movement was really fast, and jumping make me take off above montains !

Some problem for my high-end computer (i7-950 + gtx580), but the other way arround, jump are really fast, and make my take off some centimeter, movement are really slow.

Seems your physic is dependent of the speed of your update routine Smile

Some little other thinks :
- Stars are visible during daytime (maybe by purpose ?)
- From time to time in fly mode, I can "feel" the chunk that are generated in front of me by a tiny "freeze".

S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by Slaihne on Wed Jul 20, 2011 2:18 pm

Looks like i boobed bigtime Sad

I was more interested in getting collisions to work properly to be honest.

But, i've just uploaded a new version with a totally different take on the simulation part. I've now got a completely seperate thread handling player updates (and eventually all mob updates). The physics now run at 50 frames a second with fixed time steps. It's rather like that articale you linked to ages ago but using it's own thread instead of in the render thread.

I'm interested in how it works for you.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by S33m3 on Wed Jul 20, 2011 3:19 pm

Hehe you remember this article. Even if at the beginning the "fixed time step" seems overkill, I quickly faced big problem with physics (movements, jump, collision, ...) stability. Physic on variable time step is possible, but much more complicated than what it seems at first. It is also tricky to debug, as it is difficult to reproduce the same conditions that did make the physic go crazy !

Now Fixed time step.

From there you have 2 paths :
The one you have chosen is not the easiest (by far) ! Mainly because you will need between threads synchronisation !! (Update thread <=> Render thread). The fact is, without synchronisation (Locking) around all operation and variables that are not thread safe in the Update thread you will face random problems.
A simple example : A matrix multiplication consist of several differents operations, that are not thread safe (The thread could be put on sleep state during a matrix modification), at this time if your render thread decide to read this matrix value, then it will have a completly random value ==> Pretty bad.
With your solution, except putting lock nearly everywhere (Awful), is to use a double buffering mechanism. One buffer with the latest objects states is used by the rendering thread, while the other buffer is being filled by the update thread. When the update buffer is finished the buffers are switched. (Kind of thing you do with your ligting I thing).

The other way arround : Update and Render in the same thread with the mechanism explained in the article i linked previously.

While the mechanism is easy to put in place, there is one big challenge : Handling the Interpolations !
The fact is that in most cases, a simulation at 30 refresh per second is more then enough. The big problem in this case, is that the mouvement can not be as smooth as a simulation at 120 refresh per second. The interpolation are there for that purpose ! To interpolate the values between 2 computed values. The cost of the interpolation is even less than the one to compute brand new value (trough physic simulation), it' pretty good.

It will also have other effects like input handling not as easy to do as before...

Here is my main game loop :
Code:

            //The Pump !
            RenderLoop.Run(D3dEngine.GameWindow, () =>
            {
                if (FixedTimeSteps)
                {
                    _updateWithoutrenderingCount = 0;
                    while (Stopwatch.GetTimestamp() > _next_game_update && _updateWithoutrenderingCount < _maxRenderFrameSkip)
                    {
                        _gameTime.Update(FixedTimeSteps);
                        Update(ref _gameTime);

                        _next_game_update += GameUpdateDelta;
                        _updateWithoutrenderingCount++;
                    }

                    _interpolation_hd = (double)(Stopwatch.GetTimestamp() + GameUpdateDelta - _next_game_update) / GameUpdateDelta;
                    _interpolation_ld = (float)_interpolation_hd;
                    Interpolation(ref _interpolation_hd, ref _interpolation_ld); //Call before each Draw !
                }
                else
                {
                    _gameTime.Update(FixedTimeSteps);
                    Update(ref _gameTime);
                }
                Draw();
            });

As explained in the article, to smooth thing out, each variables that are time dependant needs to be interpolated.
And the rendering is only happening on the interpolated values.
To do interpolation, you need to stored each variables twice, the previous and the current one. And the interpolation is done between these 2 values.
For it I have created a special variables wrapper I called FTSValue (Fixed time step value) :

Code:

public class FTSValue<T>
    {
        public T Value;
        public T ValuePrev;
        public T ValueInterp;

        public T ActualValue
        {
            get
            {
                if (D3DEngine.FIXED_TIMESTEP_ENABLED)
                {
                    return ValueInterp;
                }
                else
                {
                    return Value;
                }
            }
        }

        public void BackUpValue()
        {
            ValuePrev = Value;
        }
    }

With this structure the draw call has just to call the FTSValue<T>.ActualValue to get the value.

If I resume for my fixed time steps :

For each game component :

- Update() called at fixed interval of time. Inside wich for the values that are time dependant I do :
1) FTSValue<T>. BackUpValue()
2) FTSValue<T>.Value = MynewComputedValue;

- Before every Draw an Interpolation() fct is called where the FTSValue<T>.ValueInterp is computed, based on FTSValue<T>.Value and FTSValue<T>.ValuePrev. (Using Vector3.Lerp, or Quaternion.Slerp for rotations)

- Draw is called using the FTSValue<T>.ActualValue();

This is working pretty well for the moment for me. hope it helps you a little bit Smile

S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by Slaihne on Thu Jul 21, 2011 7:51 am

I store several sets of data for each mob...

D1, D2, D

are only used by the Sim thread

D is the value that the sim thread is currently working on, a work in progress if you will.

D1 is the value that was true at time T = N * SimFrameTime, where N is the number of sim 'frames' and SimFrameTime is the amount of time in each Frame

D2 is the value that was true at time T = (N+1) * SimFrametime

The sim thread works on the D value and when all mobs are completely processed it holds a lock while it does the following for each mob...

D1 = D2
D2 = D

Then it releases the lock.


I also store the following for use by the render thread...

iD1, iD2, iD

The render thread holds the same lock while it does the following...

iD1 = D1
iD2 = D2

then it releases the lock.

At this stage it signals the sim thread to start work on the next sim frame.

the render thread is now free to interpolate between iD1 and iD2.
I perform this in bulk at the start of the render loop, this gives me correctly interpolated values (iD).


The render thread and sim thread can only clash on the very short copies so each thread will not stall the other for very long.

Also, the render thread should never have to wait for any calculations in the sim thread since the sim thread is building it's next frame when the render thread starts to sample from the current sim frame.

I've tested it with no vertical synch, with 1 frame and with 2 frames and it seems to work fine.

I also tried testing it with the synch being chosen at random between none, 1 frame and 2 frames.

I was less happy with the performance there since it still seemed choppy.
But i'm not sure if i should realistcally expect a smooth feeling in this situation anyways.


It needs some more testing and some re-factoring but the concept seems good at least.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by S33m3 on Thu Jul 21, 2011 12:04 pm

Nice implementation.

How are you handling the case where after an Update(), your update time is already exceeded ?

In my implementation, I keep on doing the update() until ahead of update time.


S33m3

Posts : 54
Join date : 2011-03-23

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by Slaihne on Thu Jul 21, 2011 12:26 pm

Basically the same here, the code is as follows...

Code:

    ' check if we're trying to sample from a 'future' sim frame we haven't generated yet
    ' if so, then get that future frame generated
    ' this can happen if rendering takes a long time
    While SampleTime() >= rThisSimTime
      FrameStartSignal.Set()
      FrameDoneSignal.WaitOne()
      GetPositionsForInterpolation()
    End While
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by Slaihne on Fri Jul 22, 2011 8:39 am


From time to time in fly mode, I can "feel" the chunk that are generated in front of me by a tiny "freeze".

I notice this myself all the time. It was the Garbage Collector in DotNet kicking in as i hit the 1.5/1.6 GB memory usage mark.

I've pretty much got that solved now by using a reusable buffer pool where i build my meshes rather than using as hoc lists as i was before.

Now the dilemma; this would allow me to move back to DotNet 2.0 possibly. Anyone got any thoughts on the matter?

The only factor i'm thinking of at the moment is that DotNet 2.0 let me down loads of times with out of memory errors. I still haven't gotten one of these in DotNet 4.0. The worst i've got is the little delay every now and again.
avatar
Slaihne

Posts : 264
Join date : 2011-03-17
Age : 49

View user profile

Back to top Go down

Re: Move/Jump problem.

Post by Sponsored content


Sponsored content


Back to top Go down

View previous topic View next topic Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum