Move/Jump problem.
2 posters
Page 1 of 1
Move/Jump problem.
'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
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".
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
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
Re: Move/Jump problem.
Looks like i boobed bigtime
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.
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.
Slaihne- Posts : 264
Join date : 2011-03-17
Age : 56
Re: Move/Jump problem.
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 :
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) :
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
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
S33m3- Posts : 54
Join date : 2011-03-23
Re: Move/Jump problem.
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.
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.
Slaihne- Posts : 264
Join date : 2011-03-17
Age : 56
Re: Move/Jump problem.
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.
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
Re: Move/Jump problem.
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
Slaihne- Posts : 264
Join date : 2011-03-17
Age : 56
Re: Move/Jump problem.
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.
Slaihne- Posts : 264
Join date : 2011-03-17
Age : 56
Page 1 of 1
Permissions in this forum:
You cannot reply to topics in this forum
Fri Jul 01, 2016 7:25 am by croxxx
» Source?
Thu Jul 12, 2012 9:55 am by raistlinthewiz
» Version Available (Take 2)
Sat Jun 09, 2012 3:23 am by kamild1996
» Terrain Rendering Bug
Thu May 17, 2012 8:07 am by sackboy789
» Mystery Block!
Thu Mar 29, 2012 4:42 am by Corvin73
» Your procedural tree/plant seeding technique?
Sat Mar 24, 2012 3:10 am by Slaihne
» Voxeliq project
Wed Mar 07, 2012 4:25 am by raistlinthewiz
» What is a Tech-Test?
Wed Jan 18, 2012 12:32 pm by joeydmars
» Images
Fri Jan 06, 2012 6:02 am by croxxx