From 0ee47bf1c7c07cf1bc86b112cc7b14da47bca57c Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Wed, 16 Mar 2016 11:17:09 +0200 Subject: [PATCH] actor position interpolation --- dengapi.d | 2 ++ xmain_d2d.d | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/dengapi.d b/dengapi.d index f488077..a66c286 100644 --- a/dengapi.d +++ b/dengapi.d @@ -398,6 +398,8 @@ public void loadMapMonsters () { adef.loadGraphics(); } //Actor.dumpActors(); + + conwriteln("initial snapshot size: ", Actor.snapshotSize, " bytes"); } diff --git a/xmain_d2d.d b/xmain_d2d.d index 18eeef2..f4127e5 100644 --- a/xmain_d2d.d +++ b/xmain_d2d.d @@ -38,6 +38,15 @@ __gshared bool scanlines = false; // ////////////////////////////////////////////////////////////////////////// // +// interpolation +__gshared ubyte[] prevFrameActorsData; +__gshared uint[65536] prevFrameActorOfs; // uint.max-1: dead; uint.max: last +__gshared MonoTime lastthink = MonoTime.zero; // for interpolator +__gshared MonoTime nextthink = MonoTime.zero; +__gshared bool frameInterpolation = true; + + +// ////////////////////////////////////////////////////////////////////////// // enum MaxLightRadius = 512; @@ -106,6 +115,11 @@ void initOpenGL () { Actor.resetStorage(); loadMapMonsters(); + // save first snapshot + prevFrameActorsData = new ubyte[](Actor.actorSize*65536); // ~15-20 megabytes + prevFrameActorOfs[] = uint.max; // just for fun + Actor.saveSnapshot(prevFrameActorsData[], prevFrameActorOfs.ptr); + { import core.memory : GC; GC.collect(); } } @@ -184,10 +198,20 @@ __gshared bool movement = false; __gshared float iLiquidTime = 0.0; -void renderScene () { +void renderScene (MonoTime curtime) { //enum BackIntens = 0.05f; enum BackIntens = 0.0f; + float atob = cast(float)((curtime-lastthink).total!"msecs")/cast(float)((nextthink-lastthink).total!"msecs"); + //{ import core.stdc.stdio; printf("atob=%f\n", cast(double)atob); } + /* + { + int framelen = cast(int)((nextthink-lastthink).total!"msecs"); + int curfp = cast(int)((curtime-lastthink).total!"msecs"); + { import core.stdc.stdio; printf("framelen=%d; curfp=%d\n", framelen, curfp); } + } + */ + glUseProgram(0); // build background layer @@ -214,10 +238,49 @@ void renderScene () { shad["iDistortTime"] = iLiquidTime; drawAtXY(map.texgl.ptr[map.AllLiquids], 0, 0); }); - // monsters, items + // monsters, items; we'll do linear interpolation here + // we need this for saved frame anyway, so let's play dirty and speed up the things + uint fxofs = Actor.fields["x"].ofs; + uint fyofs = Actor.fields["y"].ofs; + uint fzAnimstateofs = Actor.fields["zAnimstate"].ofs; + uint fdirofs = Actor.fields["dir"].ofs; + uint fzAnimidxofs = Actor.fields["zAnimidx"].ofs; + uint fclasstypeofs = Actor.fields["classtype"].ofs; + uint fclassnameofs = Actor.fields["classname"].ofs; glColor3f(1.0f, 1.0f, 1.0f); Actor.forEach((ActorId me) { // `act` is always valid here + auto aptr = me.data.ptr; + auto ctstr = StrId(*cast(uint*)(aptr+fclasstypeofs)); + auto cnstr = StrId(*cast(uint*)(aptr+fclassnameofs)); + if (auto adef = findActorDef(ctstr, cnstr)) { + ctstr = StrId(*cast(uint*)(aptr+fzAnimstateofs)); + if (auto isp = adef.animSpr(ctstr, *cast(uint*)(aptr+fdirofs), *cast(int*)(aptr+fzAnimidxofs))) { + auto ofs = prevFrameActorOfs.ptr[me.id&0xffff]; + if (frameInterpolation && ofs < uint.max-1) { + import core.stdc.math : roundf; + auto xptr = prevFrameActorsData.ptr+ofs; + int ox = *cast(int*)(xptr+fxofs); + int nx = *cast(int*)(aptr+fxofs); + int oy = *cast(int*)(xptr+fyofs); + int ny = *cast(int*)(aptr+fyofs); + int x = cast(int)(ox+roundf((nx-ox)*atob)); + int y = cast(int)(oy+roundf((ny-oy)*atob)); + //conwriteln("actor ", me.id, "; o=(", ox, ",", oy, "); n=(", nx, ",", ny, "); p=(", x, ",", y, ")"); + drawAtXY(isp.tex, x-isp.vga.sx, y-isp.vga.sy); + } else { + int nx = *cast(int*)(aptr+fxofs)-isp.vga.sx; + int ny = *cast(int*)(aptr+fyofs)-isp.vga.sy; + //conwriteln("actor ", me.id, "; nx=", nx, "; ny=", ny); + drawAtXY(isp.tex, nx, ny); + } + } else { + conwriteln("no animation for actor ", me.id, " (", me.classtype!string, ":", me.classname!string, ")"); + } + } else { + conwriteln("not found actor ", me.id, " (", me.classtype!string, ":", me.classname!string, ")"); + } + /+ if (auto adef = findActorDef(me.classtype!StrId, me.classname!StrId)) { if (auto isp = adef.animSpr(me.zAnimstate!StrId, me.dir!uint, me.zAnimidx!int)) { int y = me.y!int-isp.vga.sy; @@ -229,6 +292,7 @@ void renderScene () { } else { conwriteln("not found actor ", me.id, " (", me.classtype!string, ":", me.classname!string, ")"); } + +/ }); // do liquid coloring drawAtXY(map.texgl.ptr[map.LiquidMask], 0, 0); @@ -257,7 +321,6 @@ void renderScene () { enum LYOfs = 1; - renderLight( 27, 391-0+LYOfs, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 100); renderLight(542, 424-0+LYOfs, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 100); renderLight(377, 368-0+LYOfs, SVec4F(0.0f, 0.0f, 0.0f, 0.0f), 32); @@ -316,7 +379,8 @@ void renderThread () { MonoTime prevFrameStartTime = MonoTime.currTime; version(use_vsync) {} else MonoTime ltt = MonoTime.currTime; MonoTime lasttime = MonoTime.currTime; - MonoTime nextthink = MonoTime.currTime; + nextthink = MonoTime.currTime; + lastthink = nextthink; // for interpolator nextthink += dur!"msecs"(D2DFrameTime); MonoTime fstime, fetime; enum MaxFPSFrames = 16; @@ -332,9 +396,14 @@ void renderThread () { // "D2D frames" if (nextthink <= fstime) { + lastthink = fstime; nextthink = fstime; nextthink += dur!"msecs"(D2DFrameTime); + // save snapshot for interpolator + Actor.saveSnapshot(prevFrameActorsData[], prevFrameActorOfs.ptr); + // process actors doActorsThink(); + // some timing int thinkTime = cast(int)((MonoTime.currTime-fstime).total!"msecs"); if (thinkTime > 9) { import core.stdc.stdio; printf("spent on thinking: %d msecs\n", thinkTime); } } @@ -358,7 +427,7 @@ void renderThread () { } else { // render scene iLiquidTime = cast(float)((fstime-MonoTime.zero).total!"msecs"%10000000)/18.0f*0.04f; - renderScene(); + renderScene(fstime); sdwindow.mtLock(); scope(exit) sdwindow.mtUnlock(); sdwindow.swapOpenGlBuffers(); @@ -642,6 +711,7 @@ void main (string[] args) { if (ch == 's') scanlines = !scanlines; if (ch == '1') scale = 1; if (ch == '2') scale = 2; + if (ch == 'i') frameInterpolation = !frameInterpolation; if (ch == ' ') movement = !movement; }, ); -- 2.11.4.GIT