Commit d3c0b9e1 authored by NY00123's avatar NY00123 Committed by Evan Ramos
Browse files

SW: Add the currently-unused interpso.* files, enabling interpolation

of sector objects as whole groups of points and sprite angles.

The following goals are intended to be achieved with this code:
- Make it easy to let the user toggle sector object interpolation.
- Interpolate the angles of sprites carried by sector objects.
- Use the right amount of samples for interpolating a sector object,
depending on the players' locations, as done in the checks within
DoSector. Unfortunately, modifying DoSector itself to
unconditionally call MoveSectorObjects(sop, synctics) technically
changes the way sectors move (in the logical sense), and was
found out to make a specifically constructed user map unbeatable.
- Make it easy to disable interpolation of a whole sector object in
case of a need. This is especially important if such an object
is controlled by a player in multiplayer, mostly since this
isn't compatible with the way player prediction is working.
parent 9ea0503b
......@@ -776,6 +776,7 @@ sw_game_objs := \
hornet.cpp \
interp.cpp \
interpsh.cpp \
interpso.cpp \
inv.cpp \
jplayer.cpp \
jsector.cpp \
......
......@@ -208,6 +208,7 @@
<ClCompile Include="..\..\source\sw\src\hornet.cpp" />
<ClCompile Include="..\..\source\sw\src\interp.cpp" />
<ClCompile Include="..\..\source\sw\src\interpsh.cpp" />
<ClCompile Include="..\..\source\sw\src\interpso.cpp" />
<ClCompile Include="..\..\source\sw\src\inv.cpp" />
<ClCompile Include="..\..\source\sw\src\jbhlp.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
......@@ -327,6 +328,7 @@
<ClInclude Include="..\..\source\sw\src\GrpFile.game.h" />
<ClInclude Include="..\..\source\sw\src\grpscan.h" />
<ClInclude Include="..\..\source\sw\src\interp.h" />
<ClInclude Include="..\..\source\sw\src\interpso.h" />
<ClInclude Include="..\..\source\sw\src\inv.h" />
<ClInclude Include="..\..\source\sw\src\jnames.h" />
<ClInclude Include="..\..\source\sw\src\jsector.h" />
......@@ -374,4 +376,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -85,6 +85,9 @@
<ClCompile Include="..\..\source\sw\src\interpsh.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\source\sw\src\interpso.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\source\sw\src\inv.cpp">
<Filter>Source Files</Filter>
</ClCompile>
......@@ -333,6 +336,9 @@
<ClInclude Include="..\..\source\sw\src\interp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\source\sw\src\interpso.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\source\sw\src\inv.h">
<Filter>Header Files</Filter>
</ClInclude>
......@@ -463,4 +469,4 @@
<Filter>Header Files\midi</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
</Project>
//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment
This file is part of Shadow Warrior version 1.2
Shadow Warrior is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------
#include "compat.h"
#include "pragmas.h"
#include "game.h"
#include "interp.h"
#include "interpso.h"
#define SO_MAXINTERPOLATIONS MAXINTERPOLATIONS
static struct so_interp
{
struct interp_data
{
void *curipos;
int32_t oldipos;
int32_t bakipos;
int32_t lastipos;
int32_t lastoldipos;
int32_t lastangdiff;
int32_t spriteofang;
} data[SO_MAXINTERPOLATIONS];
int32_t numinterpolations;
int32_t tic, lasttic;
} so_interpdata[MAX_SECTOR_OBJECTS];
static void so_setpointinterpolation(so_interp *interp, int32_t *posptr)
{
int32_t i;
if (interp->numinterpolations >= SO_MAXINTERPOLATIONS)
return;
for (i = 0; i < interp->numinterpolations; i++)
if (interp->data[i].curipos == posptr)
return;
so_interp::interp_data *data = &interp->data[interp->numinterpolations++];
data->curipos = posptr;
data->oldipos = *posptr;
data->lastipos = *posptr;
data->lastoldipos = *posptr;
data->spriteofang = -1;
}
static void so_setspriteanginterpolation(so_interp *interp, int16_t *posptr, int32_t spritenum)
{
int32_t i;
if (interp->numinterpolations >= SO_MAXINTERPOLATIONS)
return;
for (i = 0; i < interp->numinterpolations; i++)
if (interp->data[i].curipos == posptr)
return;
so_interp::interp_data *data = &interp->data[interp->numinterpolations++];
data->curipos = posptr;
data->oldipos = *posptr;
data->lastipos = *posptr;
data->lastoldipos = *posptr;
data->lastangdiff = 0;
data->spriteofang = spritenum;
}
// Covers points and angles altogether
static void so_stopdatainterpolation(so_interp *interp, void *posptr)
{
int32_t i;
for (i = 0; i < interp->numinterpolations; i++)
if (interp->data[i].curipos == posptr)
break;
if (i == interp->numinterpolations)
return;
interp->data[i] = interp->data[--(interp->numinterpolations)];
}
void so_addinterpolation(SECTOR_OBJECTp sop)
{
SECTORp *sectp;
int32_t startwall, endwall;
int32_t i;
so_interp *interp = &so_interpdata[sop - SectorObject];
interp->numinterpolations = 0;
for (sectp = sop->sectp; *sectp; sectp++)
{
startwall = (*sectp)->wallptr;
endwall = startwall + (*sectp)->wallnum - 1;
for (i = startwall; i <= endwall; i++)
{
int32_t nextwall = wall[i].nextwall;
so_setpointinterpolation(interp, &wall[i].x);
so_setpointinterpolation(interp, &wall[i].y);
if (nextwall >= 0)
{
so_setpointinterpolation(interp, &wall[wall[nextwall].point2].x);
so_setpointinterpolation(interp, &wall[wall[nextwall].point2].y);
}
}
so_setpointinterpolation(interp, &(*sectp)->ceilingz);
so_setpointinterpolation(interp, &(*sectp)->floorz);
}
// interpolate midpoint, for aiming at a remote controlled SO
so_setpointinterpolation(interp, &sop->xmid);
so_setpointinterpolation(interp, &sop->ymid);
so_setpointinterpolation(interp, &sop->zmid);
interp->tic = 0;
interp->lasttic = synctics;
}
void so_setspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp)
{
so_interp *interp = &so_interpdata[sop - SectorObject];
so_setpointinterpolation(interp, &sp->x);
so_setpointinterpolation(interp, &sp->y);
so_setpointinterpolation(interp, &sp->z);
so_setspriteanginterpolation(interp, &sp->ang, sp - sprite);
}
void so_stopspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp)
{
so_interp *interp = &so_interpdata[sop - SectorObject];
so_stopdatainterpolation(interp, &sp->x);
so_stopdatainterpolation(interp, &sp->y);
so_stopdatainterpolation(interp, &sp->z);
so_stopdatainterpolation(interp, &sp->ang);
}
void so_setinterpolationtics(SECTOR_OBJECTp sop, int16_t locktics)
{
so_interp *interp = &so_interpdata[sop - SectorObject];
interp->tic = 0;
interp->lasttic = locktics;
}
void so_updateinterpolations(void) // Stick at beginning of domovethings
{
int32_t i;
SECTOR_OBJECTp sop;
so_interp *interp;
so_interp::interp_data *data;
SWBOOL interpolating = gs.InterpolateSO && !CommEnabled; // If changing from menu
for (sop = SectorObject, interp = so_interpdata;
sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++, interp++)
{
if (sop->xmid == INT32_MAX /*|| sop->xmid == MAXSO*/)
continue;
if (interp->tic < interp->lasttic)
interp->tic += synctics;
for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++)
{
if (data->spriteofang >= 0)
{
USERp u = User[data->spriteofang];
if (u)
u->oangdiff = 0;
if (!interpolating)
data->lastangdiff = 0;
data->oldipos = *(int16_t *)(data->curipos);
}
else
data->oldipos = *(int32_t *)(data->curipos);
if (!interpolating)
data->lastipos = data->lastoldipos = data->oldipos;
}
}
}
// must call restore for every do interpolations
// make sure you don't exit
void so_dointerpolations(int32_t smoothratio) // Stick at beginning of drawscreen
{
int32_t i, delta;
SECTOR_OBJECTp sop;
so_interp *interp;
so_interp::interp_data *data;
// Set the bakipos values separately, in case a point is shared.
// Also set lastipos if there's been an actual change in a point.
for (sop = SectorObject, interp = so_interpdata;
sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++, interp++)
{
if (sop->xmid == INT32_MAX /*|| sop->xmid == MAXSO*/)
continue;
for (i = 0; i < interp->numinterpolations; i++)
interp->data[i].bakipos = (interp->data[i].spriteofang >= 0) ?
*(int16_t *)(interp->data[i].curipos) :
*(int32_t *)(interp->data[i].curipos);
if (interp->tic == 0) // Only if the SO has just moved
{
for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++)
{
data->lastipos = data->bakipos;
data->lastoldipos = data->oldipos;
if (data->spriteofang >= 0)
{
USERp u = User[data->spriteofang];
data->lastangdiff = u ? u->oangdiff : 0;
}
}
}
}
for (sop = SectorObject, interp = so_interpdata;
sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++, interp++)
{
if (sop->xmid == INT32_MAX /*|| sop->xmid == MAXSO*/)
continue;
for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++)
{
int32_t ratio = smoothratio * synctics + 65536 * interp->tic;
ratio /= interp->lasttic;
ratio = (interp->tic == interp->lasttic) ? 65536 : ratio;
if (data->spriteofang >= 0)
*(int16_t *)(data->curipos) = NORM_ANGLE(data->lastoldipos + mulscale16(data->lastangdiff, ratio));
else
{
delta = data->lastipos - data->lastoldipos;
*(int32_t *)(data->curipos) = data->lastoldipos + mulscale16(delta, ratio);
}
}
}
}
void so_restoreinterpolations(void) // Stick at end of drawscreen
{
int32_t i;
SECTOR_OBJECTp sop;
so_interp *interp;
so_interp::interp_data *data;
for (sop = SectorObject, interp = so_interpdata;
sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++, interp++)
{
if (sop->xmid == INT32_MAX /*|| sop->xmid == MAXSO*/)
continue;
for (i = 0, data = interp->data; i < interp->numinterpolations; i++, data++)
if (data->spriteofang >= 0)
*(int16_t *)(data->curipos) = data->bakipos;
else
*(int32_t *)(data->curipos) = data->bakipos;
}
}
int SaveSymDataInfo(MFILE_WRITE fil, void *ptr);
SWBOOL so_writeinterpolations(MFILE_WRITE fil)
{
int32_t i;
SECTOR_OBJECTp sop;
const so_interp *interp;
SWBOOL saveisshot = FALSE;
for (sop = SectorObject, interp = so_interpdata;
sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++, interp++)
{
const so_interp::interp_data *data = interp->data;
MWRITE(&interp->numinterpolations,sizeof(interp->numinterpolations),1,fil);
for (i = 0; i < interp->numinterpolations; i++, data++)
{
saveisshot |= SaveSymDataInfo(fil, data->curipos);
MWRITE(&data->oldipos,sizeof(data->oldipos),1,fil);
MWRITE(&data->spriteofang,sizeof(data->spriteofang),1,fil);
}
}
return saveisshot;
}
int LoadSymDataInfo(MFILE_READ fil, void **ptr);
SWBOOL so_readinterpolations(MFILE_READ fil)
{
int32_t i;
SECTOR_OBJECTp sop;
so_interp *interp;
SWBOOL saveisshot = FALSE;
for (sop = SectorObject, interp = so_interpdata;
sop < &SectorObject[MAX_SECTOR_OBJECTS]; sop++, interp++)
{
so_interp::interp_data *data = interp->data;
MREAD(&interp->numinterpolations,sizeof(interp->numinterpolations),1,fil);
for (i = 0; i < interp->numinterpolations; i++, data++)
{
saveisshot |= LoadSymDataInfo(fil, (void **)&data->curipos);
MREAD(&data->oldipos,sizeof(data->oldipos),1,fil);
MREAD(&data->spriteofang,sizeof(data->spriteofang),1,fil);
data->lastipos = data->lastoldipos = data->oldipos;
data->lastangdiff = 0;
}
interp->tic = 0;
interp->lasttic = synctics;
}
return saveisshot;
}
//-------------------------------------------------------------------------
/*
Copyright (C) 1997, 2005 - 3D Realms Entertainment
This file is part of Shadow Warrior version 1.2
Shadow Warrior is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Original Source: 1997 - Frank Maddin and Jim Norwood
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------
#ifndef INTERPSO_H
#define INTERPSO_H
#include "mfile.h"
extern int32_t so_numinterpolations;
void so_addinterpolation(SECTOR_OBJECTp sop);
void so_setspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp);
void so_stopspriteinterpolation(SECTOR_OBJECTp sop, spritetype *sp);
void so_setinterpolationangdiff(SECTOR_OBJECTp sop, int16_t angdiff);
void so_setinterpolationtics(SECTOR_OBJECTp sop, int16_t locktics);
void so_updateinterpolations(void);
void so_dointerpolations(int32_t smoothratio);
void so_restoreinterpolations(void);
SWBOOL so_writeinterpolations(MFILE_WRITE fil);
SWBOOL so_readinterpolations(MFILE_READ fil);
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment