Torque3D/Engine/source/T3D/gameBase/extended/extendedMove.cpp
DavidWyand-GG 35374f939e ExtendedMove class and support
The ExtendedMove class can optionally replace the standard Move class to
allow the passing of absolute position and rotation information from the
client's input device to the server.  It is enabled by changing
$TORQUE_EXTENDED_MOVE to true in buildFiles/config/project.conf and
re-running the project generator.
2013-01-23 01:52:46 -05:00

259 lines
7.7 KiB
C++

#include "T3D/gameBase/extended/extendedMove.h"
#include "core/stream/bitStream.h"
#include "math/mathIO.h"
#include "core/module.h"
#include "console/consoleTypes.h"
#include "core/strings/stringFunctions.h"
MODULE_BEGIN( ExtendedMoveManager )
MODULE_INIT_AFTER( MoveManager )
MODULE_INIT
{
ExtendedMoveManager::init();
}
MODULE_END;
S32 ExtendedMoveManager::mPosX[ExtendedMove::MaxPositionsRotations] = { 0, };
S32 ExtendedMoveManager::mPosY[ExtendedMove::MaxPositionsRotations] = { 0, };
S32 ExtendedMoveManager::mPosZ[ExtendedMove::MaxPositionsRotations] = { 0, };
F32 ExtendedMoveManager::mRotAX[ExtendedMove::MaxPositionsRotations] = { 0, };
F32 ExtendedMoveManager::mRotAY[ExtendedMove::MaxPositionsRotations] = { 0, };
F32 ExtendedMoveManager::mRotAZ[ExtendedMove::MaxPositionsRotations] = { 0, };
F32 ExtendedMoveManager::mRotAA[ExtendedMove::MaxPositionsRotations] = { 1, };
void ExtendedMoveManager::init()
{
for(U32 i = 0; i < ExtendedMove::MaxPositionsRotations; ++i)
{
char varName[256];
dSprintf(varName, sizeof(varName), "mvPosX%d", i);
Con::addVariable(varName, TypeS32, &mPosX[i],
"X position of controller in millimeters. Only 13 bits are networked.\n"
"@ingroup Game");
dSprintf(varName, sizeof(varName), "mvPosY%d", i);
Con::addVariable(varName, TypeS32, &mPosY[i],
"Y position of controller in millimeters. Only 13 bits are networked.\n"
"@ingroup Game");
dSprintf(varName, sizeof(varName), "mvPosZ%d", i);
Con::addVariable(varName, TypeS32, &mPosZ[i],
"Z position of controller in millimeters. Only 13 bits are networked.\n"
"@ingroup Game");
dSprintf(varName, sizeof(varName), "mvRotX%d", i);
Con::addVariable(varName, TypeF32, &mRotAX[i],
"X rotation vector component of controller.\n"
"@ingroup Game");
dSprintf(varName, sizeof(varName), "mvRotY%d", i);
Con::addVariable(varName, TypeF32, &mRotAY[i],
"Y rotation vector component of controller.\n"
"@ingroup Game");
dSprintf(varName, sizeof(varName), "mvRotZ%d", i);
Con::addVariable(varName, TypeF32, &mRotAZ[i],
"Z rotation vector component of controller.\n"
"@ingroup Game");
dSprintf(varName, sizeof(varName), "mvRotA%d", i);
Con::addVariable(varName, TypeF32, &mRotAA[i],
"Angle rotation (in degrees) component of controller.\n"
"@ingroup Game");
}
}
const ExtendedMove NullExtendedMove;
#define CLAMPPOS(x) (x<0 ? -((-x) & (1<<(MaxPositionBits-1))-1) : (x & (1<<(MaxPositionBits-1))-1))
#define CLAMPROT(f) ((S32)(((f + 1) * .5) * ((1 << MaxRotationBits) - 1)) & ((1<<MaxRotationBits)-1))
#define UNCLAMPROT(x) ((F32)(x * 2 / F32((1 << MaxRotationBits) - 1) - 1.0f))
ExtendedMove::ExtendedMove() : Move()
{
for(U32 i=0; i<MaxPositionsRotations; ++i)
{
posX[i] = 0;
posY[i] = 0;
posZ[i] = 0;
rotX[i] = 0;
rotY[i] = 0;
rotZ[i] = 0;
rotW[i] = 1;
}
}
void ExtendedMove::pack(BitStream *stream, const Move * basemove)
{
bool alwaysWriteAll = basemove!=NULL;
if (!basemove)
basemove = &NullExtendedMove;
// Write the standard Move stuff
packMove(stream, basemove, alwaysWriteAll);
// Extended Move
const ExtendedMove* extBaseMove = static_cast<const ExtendedMove*>(basemove);
bool extendedDifferent = false;
for(U32 i=0; i<MaxPositionsRotations; ++i)
{
bool check = (posX[i] != extBaseMove->posX[i]) ||
(posY[i] != extBaseMove->posY[i]) ||
(posZ[i] != extBaseMove->posZ[i]) ||
(rotX[i] != extBaseMove->rotX[i]) ||
(rotY[i] != extBaseMove->rotY[i]) ||
(rotZ[i] != extBaseMove->rotZ[i]) ||
(rotW[i] != extBaseMove->rotW[i]);
extendedDifferent = extendedDifferent || check;
}
if (alwaysWriteAll || stream->writeFlag(extendedDifferent))
{
for(U32 i=0; i<MaxPositionsRotations; ++i)
{
// Position
if(stream->writeFlag(posX[i] != extBaseMove->posX[i]))
stream->writeSignedInt(posX[i], MaxPositionBits);
if(stream->writeFlag(posY[i] != extBaseMove->posY[i]))
stream->writeSignedInt(posY[i], MaxPositionBits);
if(stream->writeFlag(posZ[i] != extBaseMove->posZ[i]))
stream->writeSignedInt(posZ[i], MaxPositionBits);
// Rotation
if(stream->writeFlag(rotX[i] != extBaseMove->rotX[i]))
stream->writeInt(crotX[i], MaxRotationBits);
if(stream->writeFlag(rotY[i] != extBaseMove->rotY[i]))
stream->writeInt(crotY[i], MaxRotationBits);
if(stream->writeFlag(rotZ[i] != extBaseMove->rotZ[i]))
stream->writeInt(crotZ[i], MaxRotationBits);
if(stream->writeFlag(rotW[i] != extBaseMove->rotW[i]))
stream->writeInt(crotW[i], MaxRotationBits);
}
}
}
void ExtendedMove::unpack(BitStream *stream, const Move * basemove)
{
bool alwaysReadAll = basemove!=NULL;
if (!basemove)
basemove=&NullExtendedMove;
// Standard Move stuff
bool isBaseMove = !unpackMove(stream, basemove, alwaysReadAll);
// ExtendedMove
const ExtendedMove* extBaseMove = static_cast<const ExtendedMove*>(basemove);
if (alwaysReadAll || stream->readFlag())
{
isBaseMove = false;
for(U32 i=0; i<MaxPositionsRotations; ++i)
{
// Position
if(stream->readFlag())
posX[i] = stream->readSignedInt(MaxPositionBits);
else
posX[i] = extBaseMove->posX[i];
if(stream->readFlag())
posY[i] = stream->readSignedInt(MaxPositionBits);
else
posY[i] = extBaseMove->posY[i];
if(stream->readFlag())
posZ[i] = stream->readSignedInt(MaxPositionBits);
else
posZ[i] = extBaseMove->posZ[i];
// Rotation
if(stream->readFlag())
{
crotX[i] = stream->readInt(MaxRotationBits);
rotX[i] = UNCLAMPROT(crotX[i]);
}
else
{
rotX[i] = extBaseMove->rotX[i];
}
if(stream->readFlag())
{
crotY[i] = stream->readInt(MaxRotationBits);
rotY[i] = UNCLAMPROT(crotY[i]);
}
else
{
rotY[i] = extBaseMove->rotY[i];
}
if(stream->readFlag())
{
crotZ[i] = stream->readInt(MaxRotationBits);
rotZ[i] = UNCLAMPROT(crotZ[i]);
}
else
{
rotZ[i] = extBaseMove->rotZ[i];
}
if(stream->readFlag())
{
crotW[i] = stream->readInt(MaxRotationBits);
rotW[i] = UNCLAMPROT(crotW[i]);
}
else
{
rotW[i] = extBaseMove->rotW[i];
}
}
}
if(isBaseMove)
{
*this = *extBaseMove;
}
}
void ExtendedMove::clamp()
{
// Clamp the values the same as for net traffic so the client matches the server
for(U32 i=0; i<MaxPositionsRotations; ++i)
{
// Positions
posX[i] = CLAMPPOS(posX[i]);
posY[i] = CLAMPPOS(posY[i]);
posZ[i] = CLAMPPOS(posZ[i]);
// Rotations
crotX[i] = CLAMPROT(rotX[i]);
crotY[i] = CLAMPROT(rotY[i]);
crotZ[i] = CLAMPROT(rotZ[i]);
crotW[i] = CLAMPROT(rotW[i]);
}
// Perform the standard Move clamp
Parent::clamp();
}
void ExtendedMove::unclamp()
{
// Unclamp the values the same as for net traffic so the client matches the server
for(U32 i=0; i<MaxPositionsRotations; ++i)
{
// Rotations
rotX[i] = UNCLAMPROT(crotX[i]);
rotY[i] = UNCLAMPROT(crotY[i]);
rotZ[i] = UNCLAMPROT(crotZ[i]);
rotW[i] = UNCLAMPROT(crotW[i]);
}
// Perform the standard Move unclamp
Parent::unclamp();
}