How Render Tweening Works?

Blitz3D Forums/Blitz3D Programming/How Render Tweening Works?

Gabriel(Posted 2007) [#1]
I'm trying to get my head around render tweening, because I like the results and I'd like to implement it in my non-B3D game.

As far as I can see, the idea is something like this :

1) Get the amount of time which passed during the previous frame.

2) Using a fixed delta update your entities/physics once for every full time the fixed delta goes into the frame time. Store the remaining time in an "accumulator".

3) Generate a decimal fraction ( 0.0-1.0 ) by dividing the value in the accumulator by your fixed delta. Use this value to tween your entities.

I think that's right, anyway.

But then I get horribly confused when it comes to the actual tweening. When you tween you end up with the objects in a state other than the one you just put them in, don't you?

So my first instinct is to say that this means that you have to go back and "internally" put them back where they would have been had you not tweened as soon as rendering is done.

For example :

Let's say I have a cube which is currently at 0,0,0. If I say PositionEntity(Cube,0,0,100) but when it comes to tweening, the tween value is 0.66, I will end up with that entity at (0,0,66)

However, if I want to retrieve the Z coord with EntityZ#() at the beginning of the next frame, I'm going to expect it to be 100, aren't I? So insinctively, I'm thinking I should set it back to 100 after rendering. But that can't be right either, can it? Because if the tween value next frame is 0.5 then it's going in the wrong direction, isn't it?

Immediately after you render, you have to capture the state of the world again so you have something to tween against. Here again, I'm getting all twisted trying to figure out what the values I capture should be.

I think I'm missing something fundamental about this, and I'd appreciate it if someone could set me straight. There's very little information available on render tweening. I've googled extensively but I haven't been able to find much of anyone doing things the way Blitz3D does them. Or can do them if you choose to use CaptureWorld and all that.


Gabriel(Posted 2007) [#2]
Small semi-piece of inspiration :

Am I capturing at the wrong time? Phrasing all my confusions out like that had me thinking about things a little differently. Should I be capturing at the beginning of each update instead of at the end of each render?


puki(Posted 2007) [#3]
http://www.blitzbasic.com/codearcs/codearcs.php?code=1497


Gabriel(Posted 2007) [#4]
That doesn't actually address any of my questions though. I know how to do RenderTweening in Blitz3D because we're not doing any rendertweening. Mark did all that behind the scenes / under the hood and we only have to use it.

That's not what I want to know at all. I want to know how it's working under the hood so that I can implement a similar system myself.


John Blackledge(Posted 2007) [#5]
Render Tweening is "under the hood" controlling the smoothness of animated characters. No matter what the frame-rate is, if I've previously set 30 walk frames per footstep in Milkshape then RT will make my character walk that complete step even if the system was only able to achieve e.g. 15 actual frames to the screen within that last second. (And I _have_ tested my software on systems that could only achieve 8 fps!).

And Puki, you're forgiven everything for including my link.


Gabriel(Posted 2007) [#6]
No matter what the frame-rate is, if I've previously set 30 walk frames per footstep in Milkshape then RT will make my character walk that complete step even if the system was only able to achieve e.g. 15 actual frames to the screen within that last second. (And I _have_ tested my software on systems that could only achieve 8 fps!).

Delta timing does exactly the same thing. That's not render tweening, that's just the fixed delta timing that render tweening forces you to use.

Render tweening is the final step where you interpolate between the current frame and the previous frame based on a linear approximation of how far the rendering is ahead of the physics.

I think I was right earlier when I said that I was doing my capturing all wrong though, so I'm going to try rewriting that, probably split it into a capture_begin and capture_end and see if that does it.


Mr Snidesmin(Posted 2007) [#7]
this is how i would do it, and I expect the blitz3d internal tweening works similar.

instead of repositioning all the entities, use 2 sets of entities - one set is always hidden and represents the world at the start of the frame, and the other set is tweened from the first set.

at the end of each frame you would have to do a captureworld type thing, which would be to position the entities in the base set.

This jellyfish anim I created uses a similar principle:

http://www.blitzbasic.co.nz/codearcs/codearcs.php?code=1472


Gabriel(Posted 2007) [#8]
That's what I thought too, but we were both wrong.

The capturing has to be done inside the update loop, so that it is not called on a frame when you render but don't update and is called once for each update if you update multiple times before rendering. At least I think that's correct, because that's how I've just changed it to work and it appears to be working correctly now. I Have to abstract it and implement it for all my visible entity classes and then I have to write some proper test code, but initial impressions are that it works now.


Mr Snidesmin(Posted 2007) [#9]
Gabriel:
The capturing has to be done inside the update loop


Me:
at the end of each frame you would have to do a captureworld type thing


Yep Gabriel, you are right - sorry that's kind of what I meant but I'm so used to having 1 update and 1 frame render per game loop that I mistakenly said the wrong thing. . .

In my projects for some reason the update always seems to be the bottleneck and not the render. . . probably because of a few reasons: 1) I'm not the most efficient coder in terms of speed 2) I try to do quite a lot of stuff in my updates 3) I have a pretty decent CPU/RAM/VIDEO set up, so rendering a lot is never much of a problem.

For this reason render tweening is a good option for me, but I've started experimenting with calling the update loop every frame, but only updating a fraction of the entities in each update (with execption to basic motion which is updated every loop).

After 5 - 10 updates all entities have been dealt with. This helps smooth out the processing so that you don't get into a situation where there is 5 or 6 fast frames and then 1 slow one.

A drawback is that occasionally you notice some entities being slightly out of sync with others, though this can be minimized by prioritizing nearby entities.

Another issue is that you have to track a separate delta time for each entity because they don't always get updated.


Gabriel(Posted 2007) [#10]
Ah, I see what you meant now. And you're right, most people do only have one update and one render per loop.

I think I have render-tweening working now. I had a few teething problems, but I solved those by adding a No-Tween flag so that entities can skip tweening at any given frame to eliminate those morphing effects you get when you want the entity to make a sudden change.

Updating things every N'th frame can be a good way to go, with rendering also. Things like updating cubemaps and shadows can be sped up dramatically be reducing the frequency with which they are updated.

I would still consider rendertweening as well though. Blitz2D spoils us by making render tweening very easy and it's really very effective. I remember Skid's Skidmarks Construction Kit demo he released years back. I'd never seen anything run as smooth as that did, and he did that with render tweening.

Anyway, thanks for the help. All the dialogue certainly helped me get my brain working and so far it looks like it might actually be working.