mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-09 15:30:41 +00:00
Merge branch 'master' into console-func-refactor
Conflicts: Engine/source/app/net/net.cpp Engine/source/console/astNodes.cpp Engine/source/console/compiledEval.cpp Engine/source/console/console.h Engine/source/console/consoleInternal.h Engine/source/console/engineAPI.h
This commit is contained in:
commit
b507dc9555
6487 changed files with 315149 additions and 609761 deletions
|
|
@ -63,7 +63,7 @@ AIClient::AIClient() {
|
|||
mMoveTolerance = 0.25f;
|
||||
|
||||
// Clear the triggers
|
||||
for( int i = 0; i < MaxTriggerKeys; i++ )
|
||||
for( S32 i = 0; i < MaxTriggerKeys; i++ )
|
||||
mTriggers[i] = false;
|
||||
|
||||
mAimToDestination = true;
|
||||
|
|
@ -355,7 +355,7 @@ U32 AIClient::getMoveList( Move **movePtr,U32 *numMoves ) {
|
|||
Point3F targetLoc = mMoveDestination; // Change this
|
||||
|
||||
if( mPlayer ) {
|
||||
if( !mPlayer->getContainer()->castRay( mLocation, targetLoc, InteriorObjectType |
|
||||
if( !mPlayer->getContainer()->castRay( mLocation, targetLoc,
|
||||
StaticShapeObjectType | StaticObjectType |
|
||||
TerrainObjectType, &dummy ) ) {
|
||||
if( !mTargetInLOS )
|
||||
|
|
@ -369,7 +369,7 @@ U32 AIClient::getMoveList( Move **movePtr,U32 *numMoves ) {
|
|||
}
|
||||
|
||||
// Copy over the trigger status
|
||||
for( int i = 0; i < MaxTriggerKeys; i++ ) {
|
||||
for( S32 i = 0; i < MaxTriggerKeys; i++ ) {
|
||||
mMove.trigger[i] = mTriggers[i];
|
||||
mTriggers[i] = false;
|
||||
}
|
||||
|
|
@ -457,8 +457,9 @@ ConsoleMethod( AIClient, getAimLocation, const char *, 2, 2, "ai.getAimLocation(
|
|||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
Point3F aimPoint = ai->getAimLocation();
|
||||
|
||||
char *returnBuffer = Con::getReturnBuffer( 256 );
|
||||
dSprintf( returnBuffer, 256, "%f %f %f", aimPoint.x, aimPoint.y, aimPoint.z );
|
||||
static const U32 bufSize = 256;
|
||||
char *returnBuffer = Con::getReturnBuffer( bufSize );
|
||||
dSprintf( returnBuffer, bufSize, "%f %f %f", aimPoint.x, aimPoint.y, aimPoint.z );
|
||||
|
||||
return returnBuffer;
|
||||
}
|
||||
|
|
@ -470,8 +471,9 @@ ConsoleMethod( AIClient, getMoveDestination, const char *, 2, 2, "ai.getMoveDest
|
|||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
Point3F movePoint = ai->getMoveDestination();
|
||||
|
||||
char *returnBuffer = Con::getReturnBuffer( 256 );
|
||||
dSprintf( returnBuffer, 256, "%f %f %f", movePoint.x, movePoint.y, movePoint.z );
|
||||
static const U32 bufSize = 256;
|
||||
char *returnBuffer = Con::getReturnBuffer( bufSize );
|
||||
dSprintf( returnBuffer, bufSize, "%f %f %f", movePoint.x, movePoint.y, movePoint.z );
|
||||
|
||||
return returnBuffer;
|
||||
}
|
||||
|
|
@ -522,8 +524,9 @@ ConsoleMethod( AIClient, getLocation, const char *, 2, 2, "ai.getLocation();" )
|
|||
AIClient *ai = static_cast<AIClient *>( object );
|
||||
Point3F locPoint = ai->getLocation();
|
||||
|
||||
char *returnBuffer = Con::getReturnBuffer( 256 );
|
||||
dSprintf( returnBuffer, 256, "%f %f %f", locPoint.x, locPoint.y, locPoint.z );
|
||||
static const U32 bufSize = 256;
|
||||
char *returnBuffer = Con::getReturnBuffer( bufSize );
|
||||
dSprintf( returnBuffer, bufSize, "%f %f %f", locPoint.x, locPoint.y, locPoint.z );
|
||||
|
||||
return returnBuffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "T3D/gameBase/moveManager.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
static U32 sAIPlayerLoSMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType;
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(AIPlayer);
|
||||
|
||||
ConsoleDocClass( AIPlayer,
|
||||
|
|
@ -417,33 +419,26 @@ bool AIPlayer::getAIMove(Move *movePtr)
|
|||
// Test for target location in sight if it's an object. The LOS is
|
||||
// run from the eye position to the center of the object's bounding,
|
||||
// which is not very accurate.
|
||||
if (mAimObject) {
|
||||
MatrixF eyeMat;
|
||||
getEyeTransform(&eyeMat);
|
||||
eyeMat.getColumn(3,&location);
|
||||
Point3F targetLoc = mAimObject->getBoxCenter();
|
||||
|
||||
// This ray ignores non-static shapes. Cast Ray returns true
|
||||
// if it hit something.
|
||||
RayInfo dummy;
|
||||
if (getContainer()->castRay( location, targetLoc,
|
||||
InteriorObjectType | StaticShapeObjectType | StaticObjectType |
|
||||
TerrainObjectType, &dummy)) {
|
||||
if (mTargetInLOS) {
|
||||
throwCallback( "onTargetExitLOS" );
|
||||
mTargetInLOS = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!mTargetInLOS) {
|
||||
throwCallback( "onTargetEnterLOS" );
|
||||
if (mAimObject)
|
||||
{
|
||||
if (checkInLos(mAimObject.getPointer()))
|
||||
{
|
||||
if (!mTargetInLOS)
|
||||
{
|
||||
throwCallback("onTargetEnterLOS");
|
||||
mTargetInLOS = true;
|
||||
}
|
||||
}
|
||||
else if (mTargetInLOS)
|
||||
{
|
||||
throwCallback("onTargetExitLOS");
|
||||
mTargetInLOS = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Replicate the trigger state into the move so that
|
||||
// triggers can be controlled from scripts.
|
||||
for( int i = 0; i < MaxTriggerKeys; i++ )
|
||||
for( S32 i = 0; i < MaxTriggerKeys; i++ )
|
||||
movePtr->trigger[i] = getImageTriggerState(i);
|
||||
|
||||
mLastLocation = location;
|
||||
|
|
@ -610,3 +605,112 @@ DefineEngineMethod( AIPlayer, getAimObject, S32, (),,
|
|||
GameBase* obj = object->getAimObject();
|
||||
return obj? obj->getId(): -1;
|
||||
}
|
||||
|
||||
bool AIPlayer::checkInLos(GameBase* target, bool _useMuzzle, bool _checkEnabled)
|
||||
{
|
||||
if (!isServerObject()) return false;
|
||||
if (!target)
|
||||
{
|
||||
target = mAimObject.getPointer();
|
||||
if (!target)
|
||||
return false;
|
||||
}
|
||||
if (_checkEnabled)
|
||||
{
|
||||
if (target->getTypeMask() & ShapeBaseObjectType)
|
||||
{
|
||||
ShapeBase *shapeBaseCheck = static_cast<ShapeBase *>(target);
|
||||
if (shapeBaseCheck)
|
||||
if (shapeBaseCheck->getDamageState() != Enabled) return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
RayInfo ri;
|
||||
|
||||
disableCollision();
|
||||
|
||||
S32 mountCount = target->getMountedObjectCount();
|
||||
for (S32 i = 0; i < mountCount; i++)
|
||||
{
|
||||
target->getMountedObject(i)->disableCollision();
|
||||
}
|
||||
|
||||
Point3F checkPoint ;
|
||||
if (_useMuzzle)
|
||||
getMuzzlePointAI(0, &checkPoint );
|
||||
else
|
||||
{
|
||||
MatrixF eyeMat;
|
||||
getEyeTransform(&eyeMat);
|
||||
eyeMat.getColumn(3, &checkPoint );
|
||||
}
|
||||
|
||||
bool hit = !gServerContainer.castRay(checkPoint, target->getBoxCenter(), sAIPlayerLoSMask, &ri);
|
||||
enableCollision();
|
||||
|
||||
for (S32 i = 0; i < mountCount; i++)
|
||||
{
|
||||
target->getMountedObject(i)->enableCollision();
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, checkInLos, bool, (ShapeBase* obj, bool useMuzzle, bool checkEnabled),(NULL, false, false),
|
||||
"@brief Check whether an object is in line of sight.\n"
|
||||
"@obj Object to check. (If blank, it will check the current target).\n"
|
||||
"@useMuzzle Use muzzle position. Otherwise use eye position. (defaults to false).\n"
|
||||
"@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n")
|
||||
{
|
||||
return object->checkInLos(obj, useMuzzle, checkEnabled);
|
||||
}
|
||||
|
||||
bool AIPlayer::checkInFoV(GameBase* target, F32 camFov, bool _checkEnabled)
|
||||
{
|
||||
if (!isServerObject()) return false;
|
||||
if (!target)
|
||||
{
|
||||
target = mAimObject.getPointer();
|
||||
if (!target)
|
||||
return false;
|
||||
}
|
||||
if (_checkEnabled)
|
||||
{
|
||||
if (target->getTypeMask() & ShapeBaseObjectType)
|
||||
{
|
||||
ShapeBase *shapeBaseCheck = static_cast<ShapeBase *>(target);
|
||||
if (shapeBaseCheck)
|
||||
if (shapeBaseCheck->getDamageState() != Enabled) return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
MatrixF cam = getTransform();
|
||||
Point3F camPos;
|
||||
VectorF camDir;
|
||||
|
||||
cam.getColumn(3, &camPos);
|
||||
cam.getColumn(1, &camDir);
|
||||
|
||||
camFov = mDegToRad(camFov) / 2;
|
||||
|
||||
Point3F shapePos = target->getBoxCenter();
|
||||
VectorF shapeDir = shapePos - camPos;
|
||||
// Test to see if it's within our viewcone, this test doesn't
|
||||
// actually match the viewport very well, should consider
|
||||
// projection and box test.
|
||||
shapeDir.normalize();
|
||||
F32 dot = mDot(shapeDir, camDir);
|
||||
return (dot > camFov);
|
||||
}
|
||||
|
||||
DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (NULL, 45.0f, false),
|
||||
"@brief Check whether an object is within a specified veiw cone.\n"
|
||||
"@obj Object to check. (If blank, it will check the current target).\n"
|
||||
"@fov view angle in degrees.(Defaults to 45)\n"
|
||||
"@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n")
|
||||
{
|
||||
return object->checkInFoV(obj, fov, checkEnabled);
|
||||
}
|
||||
|
|
@ -80,6 +80,8 @@ public:
|
|||
void setAimLocation( const Point3F &location );
|
||||
Point3F getAimLocation() const { return mAimLocation; }
|
||||
void clearAim();
|
||||
bool checkInLos(GameBase* target = NULL, bool _useMuzzle = false, bool _checkEnabled = false);
|
||||
bool checkInFoV(GameBase* target = NULL, F32 camFov = 45.0f, bool _checkEnabled = false);
|
||||
|
||||
// Movement sets/gets
|
||||
void setMoveSpeed( const F32 speed );
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@
|
|||
#include "math/mathUtils.h"
|
||||
#include "math/mTransform.h"
|
||||
|
||||
#ifdef TORQUE_EXTENDED_MOVE
|
||||
#include "T3D/gameBase/extended/extendedMove.h"
|
||||
#endif
|
||||
|
||||
S32 Camera::smExtendedMovePosRotIndex = 0; // The ExtendedMove position/rotation index used for camera movements
|
||||
|
||||
#define MaxPitch 1.5706f
|
||||
#define CameraRadius 0.05f;
|
||||
|
||||
|
|
@ -254,6 +260,7 @@ Camera::Camera()
|
|||
{
|
||||
mNetFlags.clear(Ghostable);
|
||||
mTypeMask |= CameraObjectType;
|
||||
mDataBlock = 0;
|
||||
mDelta.pos = Point3F(0.0f, 0.0f, 100.0f);
|
||||
mDelta.rot = Point3F(0.0f, 0.0f, 0.0f);
|
||||
mDelta.posVec = mDelta.rotVec = VectorF(0.0f, 0.0f, 0.0f);
|
||||
|
|
@ -270,6 +277,9 @@ Camera::Camera()
|
|||
mObservingClientObject = false;
|
||||
mMode = FlyMode;
|
||||
|
||||
mLastAbsoluteYaw = 0.0f;
|
||||
mLastAbsolutePitch = 0.0f;
|
||||
|
||||
// For NewtonFlyMode
|
||||
mNewtonRotation = false;
|
||||
mAngularVelocity.set(0.0f, 0.0f, 0.0f);
|
||||
|
|
@ -301,7 +311,7 @@ Camera::~Camera()
|
|||
|
||||
bool Camera::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
if(!Parent::onAdd() || !mDataBlock)
|
||||
return false;
|
||||
|
||||
mObjBox.maxExtents = mObjScale;
|
||||
|
|
@ -310,6 +320,31 @@ bool Camera::onAdd()
|
|||
resetWorldBox();
|
||||
|
||||
addToScene();
|
||||
|
||||
scriptOnAdd();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Camera::onRemove()
|
||||
{
|
||||
scriptOnRemove();
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool Camera::onNewDataBlock( GameBaseData *dptr, bool reload )
|
||||
{
|
||||
mDataBlock = dynamic_cast<CameraData*>(dptr);
|
||||
if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
|
||||
return false;
|
||||
|
||||
scriptOnNewDataBlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -329,14 +364,6 @@ void Camera::onEditorDisable()
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Camera::onRemove()
|
||||
{
|
||||
removeFromScene();
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// check if the object needs to be observed through its own camera...
|
||||
void Camera::getCameraTransform(F32* pos, MatrixF* mat)
|
||||
{
|
||||
|
|
@ -460,79 +487,154 @@ void Camera::processTick(const Move* move)
|
|||
|
||||
VectorF rotVec(0, 0, 0);
|
||||
|
||||
// process input/determine rotation vector
|
||||
if(virtualMode != StationaryMode &&
|
||||
virtualMode != TrackObjectMode &&
|
||||
(!mLocked || virtualMode != OrbitObjectMode && virtualMode != OrbitPointMode))
|
||||
bool doStandardMove = true;
|
||||
|
||||
#ifdef TORQUE_EXTENDED_MOVE
|
||||
GameConnection* con = getControllingClient();
|
||||
|
||||
// Work with an absolute rotation from the ExtendedMove class?
|
||||
if(con && con->getControlSchemeAbsoluteRotation())
|
||||
{
|
||||
if(!strafeMode)
|
||||
doStandardMove = false;
|
||||
const ExtendedMove* emove = dynamic_cast<const ExtendedMove*>(move);
|
||||
U32 emoveIndex = smExtendedMovePosRotIndex;
|
||||
if(emoveIndex >= ExtendedMove::MaxPositionsRotations)
|
||||
emoveIndex = 0;
|
||||
|
||||
if(emove->EulerBasedRotation[emoveIndex])
|
||||
{
|
||||
rotVec.x = move->pitch;
|
||||
rotVec.z = move->yaw;
|
||||
if(virtualMode != StationaryMode &&
|
||||
virtualMode != TrackObjectMode &&
|
||||
(!mLocked || virtualMode != OrbitObjectMode && virtualMode != OrbitPointMode))
|
||||
{
|
||||
// Pitch
|
||||
mRot.x += (emove->rotX[emoveIndex] - mLastAbsolutePitch);
|
||||
|
||||
// Do we also include the relative pitch value?
|
||||
if(con->getControlSchemeAddPitchToAbsRot() && !strafeMode)
|
||||
{
|
||||
F32 x = move->pitch;
|
||||
if (x > M_PI_F)
|
||||
x -= M_2PI_F;
|
||||
|
||||
mRot.x += x;
|
||||
}
|
||||
|
||||
// Constrain the range of mRot.x
|
||||
while (mRot.x < -M_PI_F)
|
||||
mRot.x += M_2PI_F;
|
||||
while (mRot.x > M_PI_F)
|
||||
mRot.x -= M_2PI_F;
|
||||
|
||||
// Yaw
|
||||
mRot.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if(con->getControlSchemeAddYawToAbsRot() && !strafeMode)
|
||||
{
|
||||
F32 z = move->yaw;
|
||||
if (z > M_PI_F)
|
||||
z -= M_2PI_F;
|
||||
|
||||
mRot.z += z;
|
||||
}
|
||||
|
||||
// Constrain the range of mRot.z
|
||||
while (mRot.z < -M_PI_F)
|
||||
mRot.z += M_2PI_F;
|
||||
while (mRot.z > M_PI_F)
|
||||
mRot.z -= M_2PI_F;
|
||||
|
||||
mLastAbsoluteYaw = emove->rotZ[emoveIndex];
|
||||
mLastAbsolutePitch = emove->rotX[emoveIndex];
|
||||
|
||||
// Bank
|
||||
mRot.y = emove->rotY[emoveIndex];
|
||||
|
||||
// Constrain the range of mRot.y
|
||||
while (mRot.y > M_PI_F)
|
||||
mRot.y -= M_2PI_F;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(virtualMode == TrackObjectMode && bool(mOrbitObject))
|
||||
#endif
|
||||
|
||||
if(doStandardMove)
|
||||
{
|
||||
// orient the camera to face the object
|
||||
Point3F objPos;
|
||||
// If this is a shapebase, use its render eye transform
|
||||
// to avoid jittering.
|
||||
ShapeBase *shape = dynamic_cast<ShapeBase*>((GameBase*)mOrbitObject);
|
||||
if( shape != NULL )
|
||||
// process input/determine rotation vector
|
||||
if(virtualMode != StationaryMode &&
|
||||
virtualMode != TrackObjectMode &&
|
||||
(!mLocked || virtualMode != OrbitObjectMode && virtualMode != OrbitPointMode))
|
||||
{
|
||||
MatrixF ret;
|
||||
shape->getRenderEyeTransform( &ret );
|
||||
objPos = ret.getPosition();
|
||||
if(!strafeMode)
|
||||
{
|
||||
rotVec.x = move->pitch;
|
||||
rotVec.z = move->yaw;
|
||||
}
|
||||
}
|
||||
else if(virtualMode == TrackObjectMode && bool(mOrbitObject))
|
||||
{
|
||||
// orient the camera to face the object
|
||||
Point3F objPos;
|
||||
// If this is a shapebase, use its render eye transform
|
||||
// to avoid jittering.
|
||||
ShapeBase *shape = dynamic_cast<ShapeBase*>((GameBase*)mOrbitObject);
|
||||
if( shape != NULL )
|
||||
{
|
||||
MatrixF ret;
|
||||
shape->getRenderEyeTransform( &ret );
|
||||
objPos = ret.getPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
mOrbitObject->getWorldBox().getCenter(&objPos);
|
||||
}
|
||||
mObjToWorld.getColumn(3,&pos);
|
||||
vec = objPos - pos;
|
||||
vec.normalizeSafe();
|
||||
F32 pitch, yaw;
|
||||
MathUtils::getAnglesFromVector(vec, yaw, pitch);
|
||||
rotVec.x = -pitch - mRot.x;
|
||||
rotVec.z = yaw - mRot.z;
|
||||
if(rotVec.z > M_PI_F)
|
||||
rotVec.z -= M_2PI_F;
|
||||
else if(rotVec.z < -M_PI_F)
|
||||
rotVec.z += M_2PI_F;
|
||||
}
|
||||
|
||||
// apply rotation vector according to physics rules
|
||||
if(mNewtonRotation)
|
||||
{
|
||||
const F32 force = mAngularForce;
|
||||
const F32 drag = mAngularDrag;
|
||||
|
||||
VectorF acc(0.0f, 0.0f, 0.0f);
|
||||
|
||||
rotVec.x *= 2.0f; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
|
||||
rotVec.z *= 2.0f; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
|
||||
|
||||
F32 rotVecL = rotVec.len();
|
||||
if(rotVecL > 0)
|
||||
{
|
||||
acc = (rotVec * force / mMass) * TickSec;
|
||||
}
|
||||
|
||||
// Accelerate
|
||||
mAngularVelocity += acc;
|
||||
|
||||
// Drag
|
||||
mAngularVelocity -= mAngularVelocity * drag * TickSec;
|
||||
|
||||
// Rotate
|
||||
mRot += mAngularVelocity * TickSec;
|
||||
clampPitchAngle(mRot.x);
|
||||
}
|
||||
else
|
||||
{
|
||||
mOrbitObject->getWorldBox().getCenter(&objPos);
|
||||
mRot.x += rotVec.x;
|
||||
mRot.z += rotVec.z;
|
||||
clampPitchAngle(mRot.x);
|
||||
}
|
||||
mObjToWorld.getColumn(3,&pos);
|
||||
vec = objPos - pos;
|
||||
vec.normalizeSafe();
|
||||
F32 pitch, yaw;
|
||||
MathUtils::getAnglesFromVector(vec, yaw, pitch);
|
||||
rotVec.x = -pitch - mRot.x;
|
||||
rotVec.z = yaw - mRot.z;
|
||||
if(rotVec.z > M_PI_F)
|
||||
rotVec.z -= M_2PI_F;
|
||||
else if(rotVec.z < -M_PI_F)
|
||||
rotVec.z += M_2PI_F;
|
||||
}
|
||||
|
||||
// apply rotation vector according to physics rules
|
||||
if(mNewtonRotation)
|
||||
{
|
||||
const F32 force = mAngularForce;
|
||||
const F32 drag = mAngularDrag;
|
||||
|
||||
VectorF acc(0.0f, 0.0f, 0.0f);
|
||||
|
||||
rotVec.x *= 2.0f; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
|
||||
rotVec.z *= 2.0f; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
|
||||
|
||||
F32 rotVecL = rotVec.len();
|
||||
if(rotVecL > 0)
|
||||
{
|
||||
acc = (rotVec * force / mMass) * TickSec;
|
||||
}
|
||||
|
||||
// Accelerate
|
||||
mAngularVelocity += acc;
|
||||
|
||||
// Drag
|
||||
mAngularVelocity -= mAngularVelocity * drag * TickSec;
|
||||
|
||||
// Rotate
|
||||
mRot += mAngularVelocity * TickSec;
|
||||
clampPitchAngle(mRot.x);
|
||||
}
|
||||
else
|
||||
{
|
||||
mRot.x += rotVec.x;
|
||||
mRot.z += rotVec.z;
|
||||
clampPitchAngle(mRot.x);
|
||||
}
|
||||
|
||||
// Update position
|
||||
|
|
@ -667,6 +769,13 @@ void Camera::processTick(const Move* move)
|
|||
mDelta.rot = mRot;
|
||||
mDelta.posVec = mDelta.posVec - mDelta.pos;
|
||||
mDelta.rotVec = mDelta.rotVec - mDelta.rot;
|
||||
for(U32 i=0; i<3; ++i)
|
||||
{
|
||||
if (mDelta.rotVec[i] > M_PI_F)
|
||||
mDelta.rotVec[i] -= M_2PI_F;
|
||||
else if (mDelta.rotVec[i] < -M_PI_F)
|
||||
mDelta.rotVec[i] += M_2PI_F;
|
||||
}
|
||||
}
|
||||
|
||||
if(mustValidateEyePoint)
|
||||
|
|
@ -793,7 +902,21 @@ void Camera::_setPosition(const Point3F& pos, const Point3F& rot)
|
|||
zRot.set(EulerF(0.0f, 0.0f, rot.z));
|
||||
|
||||
MatrixF temp;
|
||||
temp.mul(zRot, xRot);
|
||||
|
||||
if(mDataBlock && mDataBlock->cameraCanBank)
|
||||
{
|
||||
// Take rot.y into account to bank the camera
|
||||
MatrixF imat;
|
||||
imat.mul(zRot, xRot);
|
||||
MatrixF ymat;
|
||||
ymat.set(EulerF(0.0f, rot.y, 0.0f));
|
||||
temp.mul(imat, ymat);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.mul(zRot, xRot);
|
||||
}
|
||||
|
||||
temp.setColumn(3, pos);
|
||||
Parent::setTransform(temp);
|
||||
mRot = rot;
|
||||
|
|
@ -808,7 +931,21 @@ void Camera::setRotation(const Point3F& rot)
|
|||
zRot.set(EulerF(0.0f, 0.0f, rot.z));
|
||||
|
||||
MatrixF temp;
|
||||
temp.mul(zRot, xRot);
|
||||
|
||||
if(mDataBlock && mDataBlock->cameraCanBank)
|
||||
{
|
||||
// Take rot.y into account to bank the camera
|
||||
MatrixF imat;
|
||||
imat.mul(zRot, xRot);
|
||||
MatrixF ymat;
|
||||
ymat.set(EulerF(0.0f, rot.y, 0.0f));
|
||||
temp.mul(imat, ymat);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.mul(zRot, xRot);
|
||||
}
|
||||
|
||||
temp.setColumn(3, getPosition());
|
||||
Parent::setTransform(temp);
|
||||
mRot = rot;
|
||||
|
|
@ -821,8 +958,25 @@ void Camera::_setRenderPosition(const Point3F& pos,const Point3F& rot)
|
|||
MatrixF xRot, zRot;
|
||||
xRot.set(EulerF(rot.x, 0, 0));
|
||||
zRot.set(EulerF(0, 0, rot.z));
|
||||
|
||||
MatrixF temp;
|
||||
temp.mul(zRot, xRot);
|
||||
|
||||
// mDataBlock may not be defined yet as this method is called during
|
||||
// SceneObject::onAdd().
|
||||
if(mDataBlock && mDataBlock->cameraCanBank)
|
||||
{
|
||||
// Take rot.y into account to bank the camera
|
||||
MatrixF imat;
|
||||
imat.mul(zRot, xRot);
|
||||
MatrixF ymat;
|
||||
ymat.set(EulerF(0.0f, rot.y, 0.0f));
|
||||
temp.mul(imat, ymat);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp.mul(zRot, xRot);
|
||||
}
|
||||
|
||||
temp.setColumn(3, pos);
|
||||
Parent::setRenderTransform(temp);
|
||||
}
|
||||
|
|
@ -839,6 +993,11 @@ void Camera::writePacketData(GameConnection *connection, BitStream *bstream)
|
|||
bstream->setCompressionPoint(pos);
|
||||
mathWrite(*bstream, pos);
|
||||
bstream->write(mRot.x);
|
||||
if(mDataBlock && bstream->writeFlag(mDataBlock->cameraCanBank))
|
||||
{
|
||||
// Include mRot.y to allow for camera banking
|
||||
bstream->write(mRot.y);
|
||||
}
|
||||
bstream->write(mRot.z);
|
||||
|
||||
U32 writeMode = mMode;
|
||||
|
|
@ -912,6 +1071,11 @@ void Camera::readPacketData(GameConnection *connection, BitStream *bstream)
|
|||
mathRead(*bstream, &pos);
|
||||
bstream->setCompressionPoint(pos);
|
||||
bstream->read(&rot.x);
|
||||
if(bstream->readFlag())
|
||||
{
|
||||
// Include rot.y to allow for camera banking
|
||||
bstream->read(&rot.y);
|
||||
}
|
||||
bstream->read(&rot.z);
|
||||
|
||||
GameBase* obj = 0;
|
||||
|
|
@ -1184,6 +1348,11 @@ void Camera::consoleInit()
|
|||
"- Fly Mode\n"
|
||||
"- Overhead Mode\n"
|
||||
"@ingroup BaseCamera\n");
|
||||
|
||||
// ExtendedMove support
|
||||
Con::addVariable("$camera::extendedMovePosRotIndex", TypeS32, &smExtendedMovePosRotIndex,
|
||||
"@brief The ExtendedMove position/rotation index used for camera movements.\n\n"
|
||||
"@ingroup BaseCamera\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1363,7 +1532,6 @@ void Camera::_validateEyePoint(F32 pos, MatrixF *mat)
|
|||
disableCollision();
|
||||
RayInfo collision;
|
||||
U32 mask = TerrainObjectType |
|
||||
InteriorObjectType |
|
||||
WaterObjectType |
|
||||
StaticShapeObjectType |
|
||||
PlayerObjectType |
|
||||
|
|
@ -1378,7 +1546,7 @@ void Camera::_validateEyePoint(F32 pos, MatrixF *mat)
|
|||
float dot = mDot(dir, collision.normal);
|
||||
if (dot > 0.01f)
|
||||
{
|
||||
float colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius;
|
||||
F32 colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius;
|
||||
if (colDist > pos)
|
||||
colDist = pos;
|
||||
if (colDist < 0.0f)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,9 @@ class Camera: public ShapeBase
|
|||
CameraLastMode = EditOrbitMode
|
||||
};
|
||||
|
||||
/// The ExtendedMove position/rotation index used for camera movements
|
||||
static S32 smExtendedMovePosRotIndex;
|
||||
|
||||
protected:
|
||||
|
||||
enum MaskBits
|
||||
|
|
@ -92,6 +95,8 @@ class Camera: public ShapeBase
|
|||
VectorF rotVec;
|
||||
};
|
||||
|
||||
CameraData* mDataBlock;
|
||||
|
||||
Point3F mRot;
|
||||
StateDelta mDelta;
|
||||
|
||||
|
|
@ -106,6 +111,9 @@ class Camera: public ShapeBase
|
|||
Point3F mPosition;
|
||||
bool mObservingClientObject;
|
||||
|
||||
F32 mLastAbsoluteYaw; ///< Stores that last absolute yaw value as passed in by ExtendedMove
|
||||
F32 mLastAbsolutePitch; ///< Stores that last absolute pitch value as passed in by ExtendedMove
|
||||
|
||||
/// @name NewtonFlyMode
|
||||
/// @{
|
||||
|
||||
|
|
@ -223,6 +231,7 @@ class Camera: public ShapeBase
|
|||
|
||||
virtual bool onAdd();
|
||||
virtual void onRemove();
|
||||
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
||||
virtual void processTick( const Move* move );
|
||||
virtual void interpolateTick( F32 delta);
|
||||
virtual void getCameraTransform( F32* pos,MatrixF* mat );
|
||||
|
|
|
|||
|
|
@ -190,10 +190,11 @@ void CameraSpline::renderTimeMap()
|
|||
// Build vertex buffer
|
||||
GFXVertexBufferHandle<GFXVertexPC> vb;
|
||||
vb.set(GFX, mTimeMap.size(), GFXBufferTypeVolatile);
|
||||
vb.lock();
|
||||
void *ptr = vb.lock();
|
||||
if(!ptr) return;
|
||||
|
||||
MRandomLCG random(1376312589 * (U32)this);
|
||||
int index = 0;
|
||||
S32 index = 0;
|
||||
for(Vector<TimeMap>::iterator itr=mTimeMap.begin(); itr != mTimeMap.end(); itr++)
|
||||
{
|
||||
Knot a;
|
||||
|
|
|
|||
|
|
@ -653,6 +653,29 @@ bool ConvexShape::buildPolyList( PolyListContext context, AbstractPolyList *plis
|
|||
|
||||
const Vector< ConvexShape::Face > faceList = mGeometry.faces;
|
||||
|
||||
if(context == PLC_Navigation)
|
||||
{
|
||||
for(S32 i = 0; i < faceList.size(); i++)
|
||||
{
|
||||
const ConvexShape::Face &face = faceList[i];
|
||||
|
||||
S32 s = face.triangles.size();
|
||||
for(S32 j = 0; j < s; j++)
|
||||
{
|
||||
plist->begin(0, s*i + j);
|
||||
|
||||
plist->plane(PlaneF(face.centroid, face.normal));
|
||||
|
||||
plist->vertex(base + face.points[face.triangles[j].p0]);
|
||||
plist->vertex(base + face.points[face.triangles[j].p1]);
|
||||
plist->vertex(base + face.points[face.triangles[j].p2]);
|
||||
|
||||
plist->end();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( S32 i = 0; i < faceList.size(); i++ )
|
||||
{
|
||||
const ConvexShape::Face &face = faceList[i];
|
||||
|
|
@ -924,68 +947,6 @@ void ConvexShape::exportToCollada()
|
|||
Con::errorf( "ConvexShape::exportToCollada() - has no surfaces to export!" );
|
||||
return;
|
||||
}
|
||||
/*
|
||||
// Get an optimized version of our mesh
|
||||
OptimizedPolyList polyList;
|
||||
|
||||
if (bakeTransform)
|
||||
{
|
||||
MatrixF mat = getTransform();
|
||||
Point3F scale = getScale();
|
||||
|
||||
pInterior->buildExportPolyList(interiorMesh, &mat, &scale);
|
||||
}
|
||||
else
|
||||
pInterior->buildExportPolyList(interiorMesh);
|
||||
|
||||
// Get our export path
|
||||
Torque::Path colladaFile = mInteriorRes.getPath();
|
||||
|
||||
// Make sure to set our Collada extension
|
||||
colladaFile.setExtension("dae");
|
||||
|
||||
// Use the InteriorInstance name if possible
|
||||
String meshName = getName();
|
||||
|
||||
// Otherwise use the DIF's file name
|
||||
if (meshName.isEmpty())
|
||||
meshName = colladaFile.getFileName();
|
||||
|
||||
// If we are baking the transform then append
|
||||
// a CRC version of the transform to the mesh/file name
|
||||
if (bakeTransform)
|
||||
{
|
||||
F32 trans[19];
|
||||
|
||||
const MatrixF& mat = getTransform();
|
||||
const Point3F& scale = getScale();
|
||||
|
||||
// Copy in the transform
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
for (U32 j = 0; j < 4; j++)
|
||||
{
|
||||
trans[i * 4 + j] = mat(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy in the scale
|
||||
trans[16] = scale.x;
|
||||
trans[17] = scale.y;
|
||||
trans[18] = scale.z;
|
||||
|
||||
U32 crc = CRC::calculateCRC(trans, sizeof(F32) * 19);
|
||||
|
||||
meshName += String::ToString("_%x", crc);
|
||||
}
|
||||
|
||||
// Set the file name as the meshName
|
||||
colladaFile.setFileName(meshName);
|
||||
|
||||
// Use a ColladaUtils function to do the actual export to a Collada file
|
||||
ColladaUtils::exportToCollada(colladaFile, interiorMesh, meshName);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void ConvexShape::resizePlanes( const Point3F &size )
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@
|
|||
#include "lighting/lightQuery.h"
|
||||
|
||||
|
||||
const U32 csmStaticCollisionMask = TerrainObjectType |
|
||||
InteriorObjectType;
|
||||
const U32 csmStaticCollisionMask = TerrainObjectType | StaticShapeObjectType | StaticObjectType;
|
||||
|
||||
const U32 csmDynamicCollisionMask = StaticShapeObjectType;
|
||||
|
||||
|
|
@ -123,7 +122,7 @@ bool DebrisData::onAdd()
|
|||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
for( int i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( !emitterList[i] && emitterIDList[i] != 0 )
|
||||
{
|
||||
|
|
@ -304,7 +303,7 @@ void DebrisData::packData(BitStream* stream)
|
|||
stream->writeString( textureName );
|
||||
stream->writeString( shapeName );
|
||||
|
||||
for( int i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( stream->writeFlag( emitterList[i] != NULL ) )
|
||||
{
|
||||
|
|
@ -347,7 +346,7 @@ void DebrisData::unpackData(BitStream* stream)
|
|||
textureName = stream->readSTString();
|
||||
shapeName = stream->readSTString();
|
||||
|
||||
for( int i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( stream->readFlag() )
|
||||
{
|
||||
|
|
@ -512,8 +511,14 @@ bool Debris::onAdd()
|
|||
return false;
|
||||
}
|
||||
|
||||
if( !mDataBlock )
|
||||
{
|
||||
Con::errorf("Debris::onAdd - Fail - No datablock");
|
||||
return false;
|
||||
}
|
||||
|
||||
// create emitters
|
||||
for( int i=0; i<DebrisData::DDC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<DebrisData::DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mDataBlock->emitterList[i] != NULL )
|
||||
{
|
||||
|
|
@ -632,7 +637,7 @@ bool Debris::onAdd()
|
|||
|
||||
void Debris::onRemove()
|
||||
{
|
||||
for( int i=0; i<DebrisData::DDC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<DebrisData::DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mEmitterList[i] )
|
||||
{
|
||||
|
|
@ -654,8 +659,11 @@ void Debris::onRemove()
|
|||
}
|
||||
}
|
||||
|
||||
getSceneManager()->removeObjectFromScene(this);
|
||||
getContainer()->removeObject(this);
|
||||
if( getSceneManager() )
|
||||
getSceneManager()->removeObjectFromScene(this);
|
||||
|
||||
if( getContainer() )
|
||||
getContainer()->removeObject(this);
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
@ -849,7 +857,7 @@ void Debris::updateEmitters( Point3F &pos, Point3F &vel, U32 ms )
|
|||
|
||||
Point3F lastPos = mLastPos;
|
||||
|
||||
for( int i=0; i<DebrisData::DDC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<DebrisData::DDC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mEmitterList[i] )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ ConsoleDocClass( DecalManager,
|
|||
|
||||
namespace {
|
||||
|
||||
int QSORT_CALLBACK cmpDecalInstance(const void* p1, const void* p2)
|
||||
S32 QSORT_CALLBACK cmpDecalInstance(const void* p1, const void* p2)
|
||||
{
|
||||
const DecalInstance** pd1 = (const DecalInstance**)p1;
|
||||
const DecalInstance** pd2 = (const DecalInstance**)p2;
|
||||
|
|
@ -125,7 +125,7 @@ int QSORT_CALLBACK cmpDecalInstance(const void* p1, const void* p2)
|
|||
return int(((char *)(*pd1)->mDataBlock) - ((char *)(*pd2)->mDataBlock));
|
||||
}
|
||||
|
||||
int QSORT_CALLBACK cmpPointsXY( const void *p1, const void *p2 )
|
||||
S32 QSORT_CALLBACK cmpPointsXY( const void *p1, const void *p2 )
|
||||
{
|
||||
const Point3F *pnt1 = (const Point3F*)p1;
|
||||
const Point3F *pnt2 = (const Point3F*)p2;
|
||||
|
|
@ -142,7 +142,7 @@ int QSORT_CALLBACK cmpPointsXY( const void *p1, const void *p2 )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int QSORT_CALLBACK cmpQuadPointTheta( const void *p1, const void *p2 )
|
||||
S32 QSORT_CALLBACK cmpQuadPointTheta( const void *p1, const void *p2 )
|
||||
{
|
||||
const Point4F *pnt1 = (const Point4F*)p1;
|
||||
const Point4F *pnt2 = (const Point4F*)p2;
|
||||
|
|
@ -157,7 +157,7 @@ int QSORT_CALLBACK cmpQuadPointTheta( const void *p1, const void *p2 )
|
|||
|
||||
static Point3F gSortPoint;
|
||||
|
||||
int QSORT_CALLBACK cmpDecalDistance( const void *p1, const void *p2 )
|
||||
S32 QSORT_CALLBACK cmpDecalDistance( const void *p1, const void *p2 )
|
||||
{
|
||||
const DecalInstance** pd1 = (const DecalInstance**)p1;
|
||||
const DecalInstance** pd2 = (const DecalInstance**)p2;
|
||||
|
|
@ -168,7 +168,7 @@ int QSORT_CALLBACK cmpDecalDistance( const void *p1, const void *p2 )
|
|||
return mSign( dist1 - dist2 );
|
||||
}
|
||||
|
||||
int QSORT_CALLBACK cmpDecalRenderOrder( const void *p1, const void *p2 )
|
||||
S32 QSORT_CALLBACK cmpDecalRenderOrder( const void *p1, const void *p2 )
|
||||
{
|
||||
const DecalInstance** pd1 = (const DecalInstance**)p1;
|
||||
const DecalInstance** pd2 = (const DecalInstance**)p2;
|
||||
|
|
@ -179,14 +179,14 @@ int QSORT_CALLBACK cmpDecalRenderOrder( const void *p1, const void *p2 )
|
|||
return 1;
|
||||
else
|
||||
{
|
||||
int priority = (*pd1)->getRenderPriority() - (*pd2)->getRenderPriority();
|
||||
S32 priority = (*pd1)->getRenderPriority() - (*pd2)->getRenderPriority();
|
||||
|
||||
if ( priority != 0 )
|
||||
return priority;
|
||||
|
||||
if ( (*pd2)->mFlags & SaveDecal )
|
||||
{
|
||||
int id = ( (*pd1)->mDataBlock->getMaterial()->getId() - (*pd2)->mDataBlock->getMaterial()->getId() );
|
||||
S32 id = ( (*pd1)->mDataBlock->getMaterial()->getId() - (*pd2)->mDataBlock->getMaterial()->getId() );
|
||||
if ( id != 0 )
|
||||
return id;
|
||||
|
||||
|
|
@ -1004,7 +1004,7 @@ void DecalManager::prepRenderImage( SceneRenderState* state )
|
|||
|
||||
PROFILE_START( DecalManager_RenderDecals_SphereTreeCull );
|
||||
|
||||
const Frustum& rootFrustum = state->getFrustum();
|
||||
const Frustum& rootFrustum = state->getCameraFrustum();
|
||||
|
||||
// Populate vector of decal instances to be rendered with all
|
||||
// decals from visible decal spheres.
|
||||
|
|
@ -1448,7 +1448,7 @@ void DecalManager::_renderDecalSpheres( ObjectRenderInst* ri, SceneRenderState*
|
|||
DecalSphere *decalSphere = grid[i];
|
||||
const SphereF &worldSphere = decalSphere->mWorldSphere;
|
||||
|
||||
if( state->getFrustum().isCulled( worldSphere ) )
|
||||
if( state->getCullingFrustum().isCulled( worldSphere ) )
|
||||
continue;
|
||||
|
||||
drawUtil->drawSphere( desc, worldSphere.radius, worldSphere.center, sphereColor );
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ bool RenderMeshExample::onAdd()
|
|||
// Add this object to the scene
|
||||
addToScene();
|
||||
|
||||
// Refresh this object's material (if any)
|
||||
updateMaterial();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +287,13 @@ void RenderMeshExample::prepRenderImage( SceneRenderState *state )
|
|||
// Set our RenderInst as a standard mesh render
|
||||
ri->type = RenderPassManager::RIT_Mesh;
|
||||
|
||||
//If our material has transparency set on this will redirect it to proper render bin
|
||||
if ( matInst->getMaterial()->isTranslucent() )
|
||||
{
|
||||
ri->type = RenderPassManager::RIT_Translucent;
|
||||
ri->translucentSort = true;
|
||||
}
|
||||
|
||||
// Calculate our sorting point
|
||||
if ( state )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect)
|
|||
|
||||
// Collision info. We're going to be running LOS tests and we
|
||||
// don't want to collide with the control object.
|
||||
static U32 losMask = TerrainObjectType | InteriorObjectType | ShapeBaseObjectType;
|
||||
static U32 losMask = TerrainObjectType | ShapeBaseObjectType;
|
||||
control->disableCollision();
|
||||
|
||||
RayInfo info;
|
||||
|
|
|
|||
|
|
@ -50,11 +50,17 @@ class GuiShapeNameHud : public GuiControl {
|
|||
ColorF mFillColor;
|
||||
ColorF mFrameColor;
|
||||
ColorF mTextColor;
|
||||
ColorF mLabelFillColor;
|
||||
ColorF mLabelFrameColor;
|
||||
|
||||
F32 mVerticalOffset;
|
||||
F32 mDistanceFade;
|
||||
bool mShowFrame;
|
||||
bool mShowFill;
|
||||
bool mShowLabelFrame;
|
||||
bool mShowLabelFill;
|
||||
|
||||
Point2I mLabelPadding;
|
||||
|
||||
protected:
|
||||
void drawName( Point2I offset, const char *buf, F32 opacity);
|
||||
|
|
@ -92,6 +98,10 @@ ConsoleDocClass( GuiShapeNameHud,
|
|||
" textColor = \"1.0 1.0 1.0 1.0\"; // Solid white text Color\n"
|
||||
" showFill = \"true\";\n"
|
||||
" showFrame = \"true\";\n"
|
||||
" labelFillColor = \"0.0 1.0 0.0 1.0\"; // Fills with a solid green color\n"
|
||||
" labelFrameColor = \"1.0 1.0 1.0 1.0\"; // Solid white frame color\n"
|
||||
" showLabelFill = \"true\";\n"
|
||||
" showLabelFrame = \"true\";\n"
|
||||
" verticalOffset = \"0.15\";\n"
|
||||
" distanceFade = \"15.0\";\n"
|
||||
"};\n"
|
||||
|
|
@ -111,6 +121,7 @@ GuiShapeNameHud::GuiShapeNameHud()
|
|||
mShowFrame = mShowFill = true;
|
||||
mVerticalOffset = 0.5f;
|
||||
mDistanceFade = 0.1f;
|
||||
mLabelPadding.set(0, 0);
|
||||
}
|
||||
|
||||
void GuiShapeNameHud::initPersistFields()
|
||||
|
|
@ -119,11 +130,16 @@ void GuiShapeNameHud::initPersistFields()
|
|||
addField( "fillColor", TypeColorF, Offset( mFillColor, GuiShapeNameHud ), "Standard color for the background of the control." );
|
||||
addField( "frameColor", TypeColorF, Offset( mFrameColor, GuiShapeNameHud ), "Color for the control's frame." );
|
||||
addField( "textColor", TypeColorF, Offset( mTextColor, GuiShapeNameHud ), "Color for the text on this control." );
|
||||
addField( "labelFillColor", TypeColorF, Offset( mLabelFillColor, GuiShapeNameHud ), "Color for the background of each shape name label." );
|
||||
addField( "labelFrameColor", TypeColorF, Offset( mLabelFrameColor, GuiShapeNameHud ), "Color for the frames around each shape name label." );
|
||||
endGroup("Colors");
|
||||
|
||||
addGroup("Misc");
|
||||
addField( "showFill", TypeBool, Offset( mShowFill, GuiShapeNameHud ), "If true, we draw the background color of the control." );
|
||||
addField( "showFrame", TypeBool, Offset( mShowFrame, GuiShapeNameHud ), "If true, we draw the frame of the control." );
|
||||
addField( "showLabelFill", TypeBool, Offset( mShowLabelFill, GuiShapeNameHud ), "If true, we draw a background for each shape name label." );
|
||||
addField( "showLabelFrame", TypeBool, Offset( mShowLabelFrame, GuiShapeNameHud ), "If true, we draw a frame around each shape name label." );
|
||||
addField( "labelPadding", TypePoint2I, Offset( mLabelPadding, GuiShapeNameHud ), "The padding (in pixels) between the label text and the frame." );
|
||||
addField( "verticalOffset", TypeF32, Offset( mVerticalOffset, GuiShapeNameHud ), "Amount to vertically offset the control in relation to the ShapeBase object in focus." );
|
||||
addField( "distanceFade", TypeF32, Offset( mDistanceFade, GuiShapeNameHud ), "Visibility distance (how far the player must be from the ShapeBase object in focus) for this control to render." );
|
||||
endGroup("Misc");
|
||||
|
|
@ -177,7 +193,7 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
|
|||
|
||||
// Collision info. We're going to be running LOS tests and we
|
||||
// don't want to collide with the control object.
|
||||
static U32 losMask = TerrainObjectType | InteriorObjectType | ShapeBaseObjectType;
|
||||
static U32 losMask = TerrainObjectType | ShapeBaseObjectType;
|
||||
control->disableCollision();
|
||||
|
||||
// All ghosted objects are added to the server connection group,
|
||||
|
|
@ -274,14 +290,26 @@ void GuiShapeNameHud::onRender( Point2I, const RectI &updateRect)
|
|||
/// @param opacity Opacity of name (a fraction).
|
||||
void GuiShapeNameHud::drawName(Point2I offset, const char *name, F32 opacity)
|
||||
{
|
||||
F32 width = mProfile->mFont->getStrWidth((const UTF8 *)name) + mLabelPadding.x * 2;
|
||||
F32 height = mProfile->mFont->getHeight() + mLabelPadding.y * 2;
|
||||
Point2I extent = Point2I(width, height);
|
||||
|
||||
// Center the name
|
||||
offset.x -= mProfile->mFont->getStrWidth((const UTF8 *)name) / 2;
|
||||
offset.y -= mProfile->mFont->getHeight();
|
||||
offset.x -= width / 2;
|
||||
offset.y -= height / 2;
|
||||
|
||||
// Background fill first
|
||||
if (mShowLabelFill)
|
||||
GFX->getDrawUtil()->drawRectFill(RectI(offset, extent), mLabelFillColor);
|
||||
|
||||
// Deal with opacity and draw.
|
||||
mTextColor.alpha = opacity;
|
||||
GFX->getDrawUtil()->setBitmapModulation(mTextColor);
|
||||
GFX->getDrawUtil()->drawText(mProfile->mFont, offset, name);
|
||||
GFX->getDrawUtil()->drawText(mProfile->mFont, offset + mLabelPadding, name);
|
||||
GFX->getDrawUtil()->clearBitmapModulation();
|
||||
|
||||
// Border last
|
||||
if (mShowLabelFrame)
|
||||
GFX->getDrawUtil()->drawRect(RectI(offset, extent), mLabelFrameColor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ protected:
|
|||
|
||||
public:
|
||||
CameraFX();
|
||||
virtual ~CameraFX() { }
|
||||
|
||||
MatrixF & getTrans(){ return mCamFXTrans; }
|
||||
virtual bool isExpired(){ return mElapsedTime >= mDuration; }
|
||||
|
|
|
|||
|
|
@ -106,18 +106,31 @@ ConsoleDocClass( Explosion,
|
|||
" lightEndBrightness = 0.0;\n"
|
||||
" lightNormalOffset = 2.0;\n"
|
||||
"};\n\n"
|
||||
"function createExplosion()\n"
|
||||
"function ServerPlayExplosion(%position, %datablock)\n"
|
||||
"{\n"
|
||||
" // Create a new explosion - it will explode automatically\n"
|
||||
" %pos = \"0 0 100\";\n"
|
||||
" %obj = new Explosion()\n"
|
||||
" // Play the given explosion on every client.\n"
|
||||
" // The explosion will be transmitted as an event, not attached to any object.\n"
|
||||
" for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)\n"
|
||||
" {\n"
|
||||
" position = %pos;\n"
|
||||
" dataBlock = GrenadeLauncherExplosion;\n"
|
||||
" };\n"
|
||||
" %client = ClientGroup.getObject(%idx);\n"
|
||||
" commandToClient(%client, 'PlayExplosion', %position, %datablock.getId());\n"
|
||||
" }\n"
|
||||
"}\n\n"
|
||||
"function clientCmdPlayExplosion(%position, %effectDataBlock)\n"
|
||||
"{\n"
|
||||
" // Play an explosion sent by the server. Make sure this function is defined\n"
|
||||
" // on the client.\n"
|
||||
" if (isObject(%effectDataBlock))\n"
|
||||
" {\n"
|
||||
" new Explosion()\n"
|
||||
" {\n"
|
||||
" position = %position;\n"
|
||||
" dataBlock = %effectDataBlock;\n"
|
||||
" };\n"
|
||||
" }\n"
|
||||
"}\n\n"
|
||||
"// schedule an explosion\n"
|
||||
"schedule(1000, 0, createExplosion);\n"
|
||||
"schedule(1000, 0, ServerPlayExplosion, \"0 0 0\", GrenadeLauncherExplosion);\n"
|
||||
"@endtsexample"
|
||||
);
|
||||
|
||||
|
|
@ -151,7 +164,7 @@ DefineEngineFunction(calcExplosionCoverage, F32, (Point3F pos, S32 id, U32 covMa
|
|||
|
||||
SceneObject* sceneObject = NULL;
|
||||
if (Sim::findObject(id, sceneObject) == false) {
|
||||
Con::warnf(ConsoleLogEntry::General, "calcExplosionCoverage: couldn't find object: %s", id);
|
||||
Con::warnf(ConsoleLogEntry::General, "calcExplosionCoverage: couldn't find object: %d", id);
|
||||
return 1.0f;
|
||||
}
|
||||
if (sceneObject->isClientObject() || sceneObject->getContainer() == NULL) {
|
||||
|
|
@ -736,9 +749,9 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
|||
|
||||
if( !server )
|
||||
{
|
||||
String errorStr;
|
||||
if( !sfxResolve( &soundProfile, errorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for explosion datablock: %s", errorStr.c_str());
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &soundProfile, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load sound profile for explosion datablock: %s", sfxErrorStr.c_str());
|
||||
if (!particleEmitter && particleEmitterId != 0)
|
||||
if (Sim::findObject(particleEmitterId, particleEmitter) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "Error, unable to load particle emitter for explosion datablock");
|
||||
|
|
@ -771,6 +784,7 @@ bool ExplosionData::preload(bool server, String &errorStr)
|
|||
//--------------------------------------
|
||||
//
|
||||
Explosion::Explosion()
|
||||
: mDataBlock( NULL )
|
||||
{
|
||||
mTypeMask |= ExplosionObjectType | LightObjectType;
|
||||
|
||||
|
|
@ -831,6 +845,12 @@ bool Explosion::onAdd()
|
|||
if ( !conn || !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
if( !mDataBlock )
|
||||
{
|
||||
Con::errorf("Explosion::onAdd - Fail - No datablok");
|
||||
return false;
|
||||
}
|
||||
|
||||
mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance );
|
||||
mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance );
|
||||
|
||||
|
|
@ -929,7 +949,7 @@ bool Explosion::onAdd()
|
|||
|
||||
void Explosion::onRemove()
|
||||
{
|
||||
for( int i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mEmitterList[i] )
|
||||
{
|
||||
|
|
@ -1114,7 +1134,7 @@ void Explosion::updateEmitters( F32 dt )
|
|||
{
|
||||
Point3F pos = getPosition();
|
||||
|
||||
for( int i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mEmitterList[i] )
|
||||
{
|
||||
|
|
@ -1134,7 +1154,7 @@ void Explosion::launchDebris( Point3F &axis )
|
|||
return;
|
||||
|
||||
bool hasDebris = false;
|
||||
for( int j=0; j<ExplosionData::EC_NUM_DEBRIS_TYPES; j++ )
|
||||
for( S32 j=0; j<ExplosionData::EC_NUM_DEBRIS_TYPES; j++ )
|
||||
{
|
||||
if( mDataBlock->debrisList[j] )
|
||||
{
|
||||
|
|
@ -1160,7 +1180,7 @@ void Explosion::launchDebris( Point3F &axis )
|
|||
|
||||
U32 numDebris = mDataBlock->debrisNum + sgRandom.randI( -mDataBlock->debrisNumVariance, mDataBlock->debrisNumVariance );
|
||||
|
||||
for( int i=0; i<numDebris; i++ )
|
||||
for( S32 i=0; i<numDebris; i++ )
|
||||
{
|
||||
|
||||
Point3F launchDir = MathUtils::randomDir( axis, mDataBlock->debrisThetaMin, mDataBlock->debrisThetaMax,
|
||||
|
|
@ -1249,7 +1269,7 @@ bool Explosion::explode()
|
|||
Point3F::Zero, U32(mDataBlock->particleDensity * mFade));
|
||||
}
|
||||
|
||||
for( int i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
|
||||
for( S32 i=0; i<ExplosionData::EC_NUM_EMITTERS; i++ )
|
||||
{
|
||||
if( mDataBlock->emitterList[i] != NULL )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ void fxFoliageRenderList::SetupClipPlanes( SceneRenderState* state, const F32 fa
|
|||
const F32 nearPlane = state->getNearPlane();
|
||||
const F32 farPlane = farClipPlane;
|
||||
|
||||
const Frustum& frustum = state->getFrustum();
|
||||
const Frustum& frustum = state->getCullingFrustum();
|
||||
|
||||
// [rene, 23-Feb-11] Why isn't this preserving the ortho state of the original frustum?
|
||||
|
||||
|
|
@ -397,7 +397,6 @@ void fxFoliageReplicator::initPersistFields()
|
|||
|
||||
addGroup( "Restrictions" ); // MM: Added Group Header.
|
||||
addField( "AllowOnTerrain", TypeBool, Offset( mFieldData.mAllowOnTerrain, fxFoliageReplicator ), "Foliage will be placed on terrain when set." );
|
||||
addField( "AllowOnInteriors", TypeBool, Offset( mFieldData.mAllowOnInteriors, fxFoliageReplicator ), "Foliage will be placed on InteriorInstances when set." );
|
||||
addField( "AllowOnStatics", TypeBool, Offset( mFieldData.mAllowStatics, fxFoliageReplicator ), "Foliage will be placed on Static shapes when set." );
|
||||
addField( "AllowOnWater", TypeBool, Offset( mFieldData.mAllowOnWater, fxFoliageReplicator ), "Foliage will be placed on/under water when set." );
|
||||
addField( "AllowWaterSurface", TypeBool, Offset( mFieldData.mAllowWaterSurface, fxFoliageReplicator ), "Foliage will be placed on water when set. Requires AllowOnWater." );
|
||||
|
|
@ -435,7 +434,6 @@ void fxFoliageReplicator::CreateFoliage(void)
|
|||
|
||||
// Check that we can position somewhere!
|
||||
if (!( mFieldData.mAllowOnTerrain ||
|
||||
mFieldData.mAllowOnInteriors ||
|
||||
mFieldData.mAllowStatics ||
|
||||
mFieldData.mAllowOnWater))
|
||||
{
|
||||
|
|
@ -633,7 +631,6 @@ void fxFoliageReplicator::CreateFoliage(void)
|
|||
|
||||
// Check Illegal Placements, fail if we hit a disallowed type.
|
||||
if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain) ||
|
||||
((CollisionType & InteriorObjectType) && !mFieldData.mAllowOnInteriors) ||
|
||||
((CollisionType & StaticShapeObjectType ) && !mFieldData.mAllowStatics) ||
|
||||
((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue;
|
||||
|
||||
|
|
@ -1700,7 +1697,6 @@ U32 fxFoliageReplicator::packUpdate(NetConnection * con, U32 mask, BitStream * s
|
|||
stream->write(mFieldData.mLightTime); // Foliage Light Time.
|
||||
|
||||
stream->writeFlag(mFieldData.mAllowOnTerrain); // Allow on Terrain.
|
||||
stream->writeFlag(mFieldData.mAllowOnInteriors); // Allow on Interiors.
|
||||
stream->writeFlag(mFieldData.mAllowStatics); // Allow on Statics.
|
||||
stream->writeFlag(mFieldData.mAllowOnWater); // Allow on Water.
|
||||
stream->writeFlag(mFieldData.mAllowWaterSurface); // Allow on Water Surface.
|
||||
|
|
@ -1777,7 +1773,6 @@ void fxFoliageReplicator::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
stream->read(&mFieldData.mLightTime); // Foliage Light Time.
|
||||
|
||||
mFieldData.mAllowOnTerrain = stream->readFlag(); // Allow on Terrain.
|
||||
mFieldData.mAllowOnInteriors = stream->readFlag(); // Allow on Interiors.
|
||||
mFieldData.mAllowStatics = stream->readFlag(); // Allow on Statics.
|
||||
mFieldData.mAllowOnWater = stream->readFlag(); // Allow on Water.
|
||||
mFieldData.mAllowWaterSurface = stream->readFlag(); // Allow on Water Surface.
|
||||
|
|
|
|||
|
|
@ -47,12 +47,10 @@
|
|||
#define AREA_ANIMATION_ARC (1.0f / 360.0f)
|
||||
|
||||
#define FXFOLIAGEREPLICATOR_COLLISION_MASK ( TerrainObjectType | \
|
||||
InteriorObjectType | \
|
||||
StaticShapeObjectType | \
|
||||
WaterObjectType )
|
||||
|
||||
#define FXFOLIAGEREPLICATOR_NOWATER_COLLISION_MASK ( TerrainObjectType | \
|
||||
InteriorObjectType | \
|
||||
StaticShapeObjectType )
|
||||
|
||||
|
||||
|
|
@ -311,7 +309,6 @@ public:
|
|||
F32 mLightTime;
|
||||
|
||||
bool mAllowOnTerrain;
|
||||
bool mAllowOnInteriors;
|
||||
bool mAllowStatics;
|
||||
bool mAllowOnWater;
|
||||
bool mAllowWaterSurface;
|
||||
|
|
@ -371,7 +368,6 @@ public:
|
|||
mLightTime = 5.0f;
|
||||
|
||||
mAllowOnTerrain = true;
|
||||
mAllowOnInteriors = true;
|
||||
mAllowStatics = true;
|
||||
mAllowOnWater = false;
|
||||
mAllowWaterSurface = false;
|
||||
|
|
|
|||
|
|
@ -166,7 +166,6 @@ void fxShapeReplicator::initPersistFields()
|
|||
|
||||
addGroup( "Restraints" ); // MM: Added Group Header.
|
||||
addField( "AllowOnTerrain", TypeBool, Offset( mFieldData.mAllowOnTerrain, fxShapeReplicator ), "Shapes will be placed on terrain when set." );
|
||||
addField( "AllowOnInteriors", TypeBool, Offset( mFieldData.mAllowOnInteriors, fxShapeReplicator ), "Shapes will be placed on InteriorInstances when set." );
|
||||
addField( "AllowOnStatics", TypeBool, Offset( mFieldData.mAllowStatics, fxShapeReplicator ), "Shapes will be placed on Static shapes when set." );
|
||||
addField( "AllowOnWater", TypeBool, Offset( mFieldData.mAllowOnWater, fxShapeReplicator ), "Shapes will be placed on/under water when set." );
|
||||
addField( "AllowWaterSurface", TypeBool, Offset( mFieldData.mAllowWaterSurface, fxShapeReplicator ), "Shapes will be placed on water when set. Requires AllowOnWater." );
|
||||
|
|
@ -214,7 +213,6 @@ void fxShapeReplicator::CreateShapes(void)
|
|||
|
||||
// Check that we can position somewhere!
|
||||
if (!( mFieldData.mAllowOnTerrain ||
|
||||
mFieldData.mAllowOnInteriors ||
|
||||
mFieldData.mAllowStatics ||
|
||||
mFieldData.mAllowOnWater))
|
||||
{
|
||||
|
|
@ -318,7 +316,6 @@ void fxShapeReplicator::CreateShapes(void)
|
|||
|
||||
// Check Illegal Placements.
|
||||
if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain) ||
|
||||
((CollisionType & InteriorObjectType) && !mFieldData.mAllowOnInteriors) ||
|
||||
((CollisionType & StaticShapeObjectType) && !mFieldData.mAllowStatics) ||
|
||||
((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue;
|
||||
|
||||
|
|
@ -696,7 +693,6 @@ U32 fxShapeReplicator::packUpdate(NetConnection * con, U32 mask, BitStream * str
|
|||
mathWrite(*stream, mFieldData.mShapeRotateMax); // Shapes Rotate Max.
|
||||
stream->writeSignedInt(mFieldData.mOffsetZ, 32); // Shapes Offset Z.
|
||||
stream->writeFlag(mFieldData.mAllowOnTerrain); // Allow on Terrain.
|
||||
stream->writeFlag(mFieldData.mAllowOnInteriors); // Allow on Interiors.
|
||||
stream->writeFlag(mFieldData.mAllowStatics); // Allow on Statics.
|
||||
stream->writeFlag(mFieldData.mAllowOnWater); // Allow on Water.
|
||||
stream->writeFlag(mFieldData.mAllowWaterSurface); // Allow on Water Surface.
|
||||
|
|
@ -742,7 +738,6 @@ void fxShapeReplicator::unpackUpdate(NetConnection * con, BitStream * stream)
|
|||
mathRead(*stream, &mFieldData.mShapeRotateMax); // Shapes Rotate Max.
|
||||
mFieldData.mOffsetZ = stream->readSignedInt(32); // Shapes Offset Z.
|
||||
mFieldData.mAllowOnTerrain = stream->readFlag(); // Allow on Terrain.
|
||||
mFieldData.mAllowOnInteriors = stream->readFlag(); // Allow on Interiors.
|
||||
mFieldData.mAllowStatics = stream->readFlag(); // Allow on Statics.
|
||||
mFieldData.mAllowOnWater = stream->readFlag(); // Allow on Water.
|
||||
mFieldData.mAllowWaterSurface = stream->readFlag(); // Allow on Water Surface.
|
||||
|
|
|
|||
|
|
@ -36,12 +36,10 @@
|
|||
#define AREA_ANIMATION_ARC (1.0f / 360.0f)
|
||||
|
||||
#define FXREPLICATOR_COLLISION_MASK ( TerrainObjectType | \
|
||||
InteriorObjectType | \
|
||||
StaticShapeObjectType | \
|
||||
WaterObjectType )
|
||||
|
||||
#define FXREPLICATOR_NOWATER_COLLISION_MASK ( TerrainObjectType | \
|
||||
InteriorObjectType | \
|
||||
StaticShapeObjectType )
|
||||
|
||||
|
||||
|
|
@ -139,7 +137,6 @@ public:
|
|||
U32 mOuterRadiusY;
|
||||
S32 mOffsetZ;
|
||||
bool mAllowOnTerrain;
|
||||
bool mAllowOnInteriors;
|
||||
bool mAllowStatics;
|
||||
bool mAllowOnWater;
|
||||
S32 mAllowedTerrainSlope;
|
||||
|
|
@ -166,7 +163,6 @@ public:
|
|||
mOffsetZ = 0;
|
||||
|
||||
mAllowOnTerrain = true;
|
||||
mAllowOnInteriors = true;
|
||||
mAllowStatics = true;
|
||||
mAllowOnWater = false;
|
||||
mAllowWaterSurface = false;
|
||||
|
|
|
|||
|
|
@ -1225,14 +1225,17 @@ GroundCoverCell* GroundCover::_generateCell( const Point2I& index,
|
|||
flipBB *= -1.0f;
|
||||
|
||||
PROFILE_START( GroundCover_TerrainRayCast );
|
||||
hit = terrainBlock->getNormalHeightMaterial( Point2F( cp.x - pos.x, cp.y - pos.y ),
|
||||
// Transform billboard point into terrain's frame of reference.
|
||||
Point3F pp = Point3F(cp.x, cp.y, 0);
|
||||
terrainBlock->getWorldTransform().mulP(pp);
|
||||
hit = terrainBlock->getNormalHeightMaterial( Point2F ( pp.x, pp.y ),
|
||||
&normal, &h, matName );
|
||||
PROFILE_END(); // GroundCover_TerrainRayCast
|
||||
|
||||
// TODO: When did we loose the world space elevation when
|
||||
// getting the terrain height?
|
||||
h += pos.z + mZOffset;
|
||||
|
||||
PROFILE_END(); // GroundCover_TerrainRayCast
|
||||
if ( !hit || h > typeMaxElevation || h < typeMinElevation ||
|
||||
( typeLayer[0] && !typeInvertLayer && matName != typeLayer ) ||
|
||||
( typeLayer[0] && typeInvertLayer && matName == typeLayer ) )
|
||||
|
|
@ -1536,7 +1539,7 @@ void GroundCover::prepRenderImage( SceneRenderState *state )
|
|||
|
||||
// Setup the frustum culler.
|
||||
if ( ( mCuller.getPosition().isZero() || !mDebugLockFrustum ) && !state->isShadowPass() )
|
||||
mCuller = state->getFrustum();
|
||||
mCuller = state->getCullingFrustum();
|
||||
|
||||
// Update the cells, but only during the diffuse pass.
|
||||
// We don't want cell generation to thrash when the reflection camera
|
||||
|
|
@ -1550,8 +1553,11 @@ void GroundCover::prepRenderImage( SceneRenderState *state )
|
|||
{
|
||||
PROFILE_SCOPE( GroundCover_RenderBillboards );
|
||||
|
||||
// Take zoom into account.
|
||||
F32 screenScale = state->getWorldToScreenScale().y / state->getViewport().extent.y;
|
||||
|
||||
// Set the far distance for billboards.
|
||||
mCuller.setFarDist( mRadius );
|
||||
mCuller.setFarDist( mRadius * screenScale );
|
||||
|
||||
F32 cullScale = 1.0f;
|
||||
if ( state->isReflectPass() )
|
||||
|
|
@ -1560,18 +1566,26 @@ void GroundCover::prepRenderImage( SceneRenderState *state )
|
|||
// Setup our shader const data.
|
||||
// Must be done prior to submitting our render instance.
|
||||
|
||||
mShaderConstData.fadeInfo.set( mFadeRadius * cullScale, mRadius * cullScale );
|
||||
mShaderConstData.fadeInfo.set( mFadeRadius * cullScale * screenScale, mRadius * cullScale * screenScale );
|
||||
|
||||
const F32 simTime = Sim::getCurrentTime() * 0.001f;
|
||||
|
||||
mShaderConstData.gustInfo.set( mWindGustLength, mWindGustFrequency * simTime, mWindGustStrength );
|
||||
mShaderConstData.turbInfo.set( mWindTurbulenceFrequency * simTime, mWindTurbulenceStrength );
|
||||
|
||||
|
||||
// Use the camera's forward vector to calculate the camera's right
|
||||
// and up vectors. This removes any camera banking from affecting
|
||||
// the ground cover.
|
||||
const MatrixF &camMat = state->getDiffuseCameraTransform();
|
||||
Point3F camDir, camUp, camRight;
|
||||
camMat.getColumn( 1, &camDir );
|
||||
camMat.getColumn( 2, &camUp );
|
||||
camMat.getColumn( 0, &camRight );
|
||||
mCross( camDir, Point3F::UnitZ, &camRight );
|
||||
if ( camRight.magnitudeSafe() == 0.0f )
|
||||
{
|
||||
camRight.set( 0.0f, -1.0f, 0.0f );
|
||||
}
|
||||
camRight.normalizeSafe();
|
||||
mCross( camRight, camDir, &camUp );
|
||||
|
||||
// Limit the camera up vector to keep the billboards
|
||||
// from leaning too far down into the terrain.
|
||||
|
|
|
|||
|
|
@ -287,14 +287,14 @@ bool LightningData::preload(bool server, String &errorStr)
|
|||
|
||||
if (server == false)
|
||||
{
|
||||
String errorStr;
|
||||
String sfxErrorStr;
|
||||
for (U32 i = 0; i < MaxThunders; i++) {
|
||||
if( !sfxResolve( &thunderSounds[ i ], errorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", errorStr.c_str());
|
||||
if( !sfxResolve( &thunderSounds[ i ], sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
}
|
||||
|
||||
if( !sfxResolve( &strikeSound, errorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", errorStr.c_str());
|
||||
if( !sfxResolve( &strikeSound, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
|
||||
for (U32 i = 0; i < MaxTextures; i++)
|
||||
{
|
||||
|
|
@ -1139,7 +1139,7 @@ void LightningBolt::generateMinorNodes()
|
|||
{
|
||||
mMinorNodes.clear();
|
||||
|
||||
for( int i=0; i<mMajorNodes.numNodes - 1; i++ )
|
||||
for( S32 i=0; i<mMajorNodes.numNodes - 1; i++ )
|
||||
{
|
||||
NodeManager segment;
|
||||
segment.startPoint = mMajorNodes.nodeList[i].point;
|
||||
|
|
|
|||
|
|
@ -66,11 +66,11 @@ ConsoleDocClass( ParticleData,
|
|||
"@see ParticleEmitterNode\n"
|
||||
);
|
||||
|
||||
static const float sgDefaultWindCoefficient = 0.0f;
|
||||
static const float sgDefaultConstantAcceleration = 0.f;
|
||||
static const float sgDefaultSpinSpeed = 1.f;
|
||||
static const float sgDefaultSpinRandomMin = 0.f;
|
||||
static const float sgDefaultSpinRandomMax = 0.f;
|
||||
static const F32 sgDefaultWindCoefficient = 0.0f;
|
||||
static const F32 sgDefaultConstantAcceleration = 0.f;
|
||||
static const F32 sgDefaultSpinSpeed = 1.f;
|
||||
static const F32 sgDefaultSpinRandomMin = 0.f;
|
||||
static const F32 sgDefaultSpinRandomMax = 0.f;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -128,16 +128,20 @@ ParticleData::~ParticleData()
|
|||
}
|
||||
}
|
||||
|
||||
FRangeValidator dragCoefFValidator(0.f, 5.f);
|
||||
FRangeValidator gravCoefFValidator(-10.f, 10.f);
|
||||
FRangeValidator spinRandFValidator(-1000.f, 1000.f);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// initPersistFields
|
||||
//-----------------------------------------------------------------------------
|
||||
void ParticleData::initPersistFields()
|
||||
{
|
||||
addFieldV( "dragCoefficient", TYPEID< F32 >(), Offset(dragCoefficient, ParticleData), new FRangeValidator(0, 5),
|
||||
addFieldV( "dragCoefficient", TYPEID< F32 >(), Offset(dragCoefficient, ParticleData), &dragCoefFValidator,
|
||||
"Particle physics drag amount." );
|
||||
addField( "windCoefficient", TYPEID< F32 >(), Offset(windCoefficient, ParticleData),
|
||||
"Strength of wind on the particles." );
|
||||
addFieldV( "gravityCoefficient", TYPEID< F32 >(), Offset(gravityCoefficient, ParticleData), new FRangeValidator(-10, 10),
|
||||
addFieldV( "gravityCoefficient", TYPEID< F32 >(), Offset(gravityCoefficient, ParticleData), &gravCoefFValidator,
|
||||
"Strength of gravity on the particles." );
|
||||
addFieldV( "inheritedVelFactor", TYPEID< F32 >(), Offset(inheritedVelFactor, ParticleData), &CommonValidators::NormalizedFloat,
|
||||
"Amount of emitter velocity to add to particle initial velocity." );
|
||||
|
|
@ -149,10 +153,10 @@ void ParticleData::initPersistFields()
|
|||
"Variance in lifetime of particle, from 0 - lifetimeMS." );
|
||||
addField( "spinSpeed", TYPEID< F32 >(), Offset(spinSpeed, ParticleData),
|
||||
"Speed at which to spin the particle." );
|
||||
addField( "spinRandomMin", TYPEID< F32 >(), Offset(spinRandomMin, ParticleData),
|
||||
"Minimum allowed spin speed of this particle, between -10000 and spinRandomMax." );
|
||||
addField( "spinRandomMax", TYPEID< F32 >(), Offset(spinRandomMax, ParticleData),
|
||||
"Maximum allowed spin speed of this particle, between spinRandomMin and 10000." );
|
||||
addFieldV( "spinRandomMin", TYPEID< F32 >(), Offset(spinRandomMin, ParticleData), &spinRandFValidator,
|
||||
"Minimum allowed spin speed of this particle, between -1000 and spinRandomMax." );
|
||||
addFieldV( "spinRandomMax", TYPEID< F32 >(), Offset(spinRandomMax, ParticleData), &spinRandFValidator,
|
||||
"Maximum allowed spin speed of this particle, between spinRandomMin and 1000." );
|
||||
addField( "useInvAlpha", TYPEID< bool >(), Offset(useInvAlpha, ParticleData),
|
||||
"@brief Controls how particles blend with the scene.\n\n"
|
||||
"If true, particles blend like ParticleBlendStyle NORMAL, if false, "
|
||||
|
|
@ -200,7 +204,8 @@ void ParticleData::initPersistFields()
|
|||
"@brief Particle RGBA color keyframe values.\n\n"
|
||||
"The particle color will linearly interpolate between the color/time keys "
|
||||
"over the lifetime of the particle." );
|
||||
addField( "sizes", TYPEID< F32 >(), Offset(sizes, ParticleData), PDC_NUM_KEYS,
|
||||
addProtectedField( "sizes", TYPEID< F32 >(), Offset(sizes, ParticleData), &protectedSetSizes,
|
||||
&defaultProtectedGetFn, PDC_NUM_KEYS,
|
||||
"@brief Particle size keyframe values.\n\n"
|
||||
"The particle size will linearly interpolate between the size/time keys "
|
||||
"over the lifetime of the particle." );
|
||||
|
|
@ -343,6 +348,22 @@ void ParticleData::unpackData(BitStream* stream)
|
|||
}
|
||||
}
|
||||
|
||||
bool ParticleData::protectedSetSizes( void *object, const char *index, const char *data)
|
||||
{
|
||||
ParticleData *pData = static_cast<ParticleData*>( object );
|
||||
F32 val = dAtof(data);
|
||||
U32 i;
|
||||
|
||||
if (!index)
|
||||
i = 0;
|
||||
else
|
||||
i = dAtoui(index);
|
||||
|
||||
pData->sizes[i] = mClampF( val, 0.f, MaxParticleSize );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParticleData::protectedSetTimes( void *object, const char *index, const char *data)
|
||||
{
|
||||
ParticleData *pData = static_cast<ParticleData*>( object );
|
||||
|
|
@ -356,7 +377,7 @@ bool ParticleData::protectedSetTimes( void *object, const char *index, const cha
|
|||
|
||||
pData->times[i] = mClampF( val, 0.f, 1.f );
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -379,11 +400,11 @@ bool ParticleData::onAdd()
|
|||
Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) lifetimeVariance >= lifetime", getName());
|
||||
lifetimeVarianceMS = lifetimeMS - 1;
|
||||
}
|
||||
if (spinSpeed > 10000.0 || spinSpeed < -10000.0) {
|
||||
if (spinSpeed > 1000.f || spinSpeed < -1000.f) {
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) spinSpeed invalid", getName());
|
||||
return false;
|
||||
}
|
||||
if (spinRandomMin > 10000.0 || spinRandomMin < -10000.0) {
|
||||
if (spinRandomMin > 1000.f || spinRandomMin < -1000.f) {
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) spinRandomMin invalid", getName());
|
||||
spinRandomMin = -360.0;
|
||||
return false;
|
||||
|
|
@ -393,7 +414,7 @@ bool ParticleData::onAdd()
|
|||
spinRandomMin = spinRandomMax - (spinRandomMin - spinRandomMax );
|
||||
return false;
|
||||
}
|
||||
if (spinRandomMax > 10000.0 || spinRandomMax < -10000.0) {
|
||||
if (spinRandomMax > 1000.f || spinRandomMax < -1000.f) {
|
||||
Con::warnf(ConsoleLogEntry::General, "ParticleData(%s) spinRandomMax invalid", getName());
|
||||
spinRandomMax = 360.0;
|
||||
return false;
|
||||
|
|
@ -601,7 +622,7 @@ bool ParticleData::reload(char errorBuffer[256])
|
|||
}
|
||||
/*
|
||||
numFrames = 0;
|
||||
for( int i=0; i<PDC_MAX_TEX; i++ )
|
||||
for( S32 i=0; i<PDC_MAX_TEX; i++ )
|
||||
{
|
||||
if( textureNameList[i] && textureNameList[i][0] )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ class ParticleData : public SimDataBlock
|
|||
StringTableEntry textureName;
|
||||
GFXTexHandle textureHandle;
|
||||
|
||||
static bool protectedSetSizes( void *object, const char *index, const char *data );
|
||||
static bool protectedSetTimes( void *object, const char *index, const char *data );
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ ConsoleDocClass( ParticleEmitterData,
|
|||
"@see ParticleEmitterNode\n"
|
||||
);
|
||||
|
||||
static const float sgDefaultEjectionOffset = 0.f;
|
||||
static const float sgDefaultPhiReferenceVel = 0.f;
|
||||
static const float sgDefaultPhiVariance = 360.f;
|
||||
static const F32 sgDefaultEjectionOffset = 0.f;
|
||||
static const F32 sgDefaultPhiReferenceVel = 0.f;
|
||||
static const F32 sgDefaultPhiVariance = 360.f;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ParticleEmitterData
|
||||
|
|
@ -118,6 +118,7 @@ ParticleEmitterData::ParticleEmitterData()
|
|||
ejectionVelocity = 2.0f; // From 1.0 - 3.0 meters per sec
|
||||
velocityVariance = 1.0f;
|
||||
ejectionOffset = sgDefaultEjectionOffset; // ejection from the emitter point
|
||||
ejectionOffsetVariance = 0.0f;
|
||||
|
||||
thetaMin = 0.0f; // All heights
|
||||
thetaMax = 90.0f;
|
||||
|
|
@ -171,6 +172,13 @@ ImplementEnumType( ParticleBlendStyle,
|
|||
{ ParticleRenderInst::BlendPremultAlpha, "PREMULTALPHA", "Color blends with the colors of the imagemap rather than the alpha.\n" },
|
||||
EndImplementEnumType;
|
||||
|
||||
IRangeValidator ejectPeriodIValidator(1, 2047);
|
||||
IRangeValidator periodVarianceIValidator(0, 2047);
|
||||
FRangeValidator ejectionFValidator(0.f, 655.35f);
|
||||
FRangeValidator velVarianceFValidator(0.f, 163.83f);
|
||||
FRangeValidator thetaFValidator(0.f, 180.f);
|
||||
FRangeValidator phiFValidator(0.f, 360.f);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// initPersistFields
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -178,31 +186,34 @@ void ParticleEmitterData::initPersistFields()
|
|||
{
|
||||
addGroup( "ParticleEmitterData" );
|
||||
|
||||
addFieldV("ejectionPeriodMS", TYPEID< S32 >(), Offset(ejectionPeriodMS, ParticleEmitterData), new IRangeValidator(1, 2047),
|
||||
addFieldV("ejectionPeriodMS", TYPEID< S32 >(), Offset(ejectionPeriodMS, ParticleEmitterData), &ejectPeriodIValidator,
|
||||
"Time (in milliseconds) between each particle ejection." );
|
||||
|
||||
addFieldV("periodVarianceMS", TYPEID< S32 >(), Offset(periodVarianceMS, ParticleEmitterData), new IRangeValidator(0, 2047),
|
||||
addFieldV("periodVarianceMS", TYPEID< S32 >(), Offset(periodVarianceMS, ParticleEmitterData), &periodVarianceIValidator,
|
||||
"Variance in ejection period, from 1 - ejectionPeriodMS." );
|
||||
|
||||
addFieldV( "ejectionVelocity", TYPEID< F32 >(), Offset(ejectionVelocity, ParticleEmitterData), new FRangeValidator(0, 655.35f),
|
||||
addFieldV( "ejectionVelocity", TYPEID< F32 >(), Offset(ejectionVelocity, ParticleEmitterData), &ejectionFValidator,
|
||||
"Particle ejection velocity." );
|
||||
|
||||
addFieldV( "velocityVariance", TYPEID< F32 >(), Offset(velocityVariance, ParticleEmitterData), new FRangeValidator(0, 163.83f),
|
||||
addFieldV( "velocityVariance", TYPEID< F32 >(), Offset(velocityVariance, ParticleEmitterData), &velVarianceFValidator,
|
||||
"Variance for ejection velocity, from 0 - ejectionVelocity." );
|
||||
|
||||
addFieldV( "ejectionOffset", TYPEID< F32 >(), Offset(ejectionOffset, ParticleEmitterData), new FRangeValidator(0, 655.35f),
|
||||
addFieldV( "ejectionOffset", TYPEID< F32 >(), Offset(ejectionOffset, ParticleEmitterData), &ejectionFValidator,
|
||||
"Distance along ejection Z axis from which to eject particles." );
|
||||
|
||||
addFieldV( "ejectionOffsetVariance", TYPEID< F32 >(), Offset(ejectionOffsetVariance, ParticleEmitterData), &ejectionFValidator,
|
||||
"Distance Padding along ejection Z axis from which to eject particles." );
|
||||
|
||||
addFieldV( "thetaMin", TYPEID< F32 >(), Offset(thetaMin, ParticleEmitterData), new FRangeValidator(0, 180.0f),
|
||||
addFieldV( "thetaMin", TYPEID< F32 >(), Offset(thetaMin, ParticleEmitterData), &thetaFValidator,
|
||||
"Minimum angle, from the horizontal plane, to eject from." );
|
||||
|
||||
addFieldV( "thetaMax", TYPEID< F32 >(), Offset(thetaMax, ParticleEmitterData), new FRangeValidator(0, 180.0f),
|
||||
addFieldV( "thetaMax", TYPEID< F32 >(), Offset(thetaMax, ParticleEmitterData), &thetaFValidator,
|
||||
"Maximum angle, from the horizontal plane, to eject particles from." );
|
||||
|
||||
addFieldV( "phiReferenceVel", TYPEID< F32 >(), Offset(phiReferenceVel, ParticleEmitterData), new FRangeValidator(0, 360.0f),
|
||||
addFieldV( "phiReferenceVel", TYPEID< F32 >(), Offset(phiReferenceVel, ParticleEmitterData), &phiFValidator,
|
||||
"Reference angle, from the vertical plane, to eject particles from." );
|
||||
|
||||
addFieldV( "phiVariance", TYPEID< F32 >(), Offset(phiVariance, ParticleEmitterData), new FRangeValidator(0, 360.0f),
|
||||
addFieldV( "phiVariance", TYPEID< F32 >(), Offset(phiVariance, ParticleEmitterData), &phiFValidator,
|
||||
"Variance from the reference angle, from 0 - 360." );
|
||||
|
||||
addField( "softnessDistance", TYPEID< F32 >(), Offset(softnessDistance, ParticleEmitterData),
|
||||
|
|
@ -309,6 +320,8 @@ void ParticleEmitterData::packData(BitStream* stream)
|
|||
stream->writeInt((S32)(velocityVariance * 100), 14);
|
||||
if( stream->writeFlag( ejectionOffset != sgDefaultEjectionOffset ) )
|
||||
stream->writeInt((S32)(ejectionOffset * 100), 16);
|
||||
if( stream->writeFlag( ejectionOffsetVariance != 0.0f ) )
|
||||
stream->writeInt((S32)(ejectionOffsetVariance * 100), 16);
|
||||
stream->writeRangedU32((U32)thetaMin, 0, 180);
|
||||
stream->writeRangedU32((U32)thetaMax, 0, 180);
|
||||
if( stream->writeFlag( phiReferenceVel != sgDefaultPhiReferenceVel ) )
|
||||
|
|
@ -361,7 +374,10 @@ void ParticleEmitterData::unpackData(BitStream* stream)
|
|||
ejectionOffset = stream->readInt(16) / 100.0f;
|
||||
else
|
||||
ejectionOffset = sgDefaultEjectionOffset;
|
||||
|
||||
if( stream->readFlag() )
|
||||
ejectionOffsetVariance = stream->readInt(16) / 100.0f;
|
||||
else
|
||||
ejectionOffsetVariance = 0.0f;
|
||||
thetaMin = (F32)stream->readRangedU32(0, 180);
|
||||
thetaMax = (F32)stream->readRangedU32(0, 180);
|
||||
if( stream->readFlag() )
|
||||
|
|
@ -719,6 +735,7 @@ ParticleEmitter::ParticleEmitter()
|
|||
mCurBuffSize = 0;
|
||||
|
||||
mDead = false;
|
||||
mDataBlock = NULL;
|
||||
|
||||
// ParticleEmitter should be allocated on the client only.
|
||||
mNetFlags.set( IsGhost );
|
||||
|
|
@ -749,11 +766,6 @@ bool ParticleEmitter::onAdd()
|
|||
{
|
||||
cleanup->addObject( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertFatal( false, "Error, could not find ClientMissionCleanup group" );
|
||||
return false;
|
||||
}
|
||||
|
||||
removeFromProcessList();
|
||||
|
||||
|
|
@ -917,7 +929,7 @@ void ParticleEmitter::prepRenderImage(SceneRenderState* state)
|
|||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::setSizes( F32 *sizeList )
|
||||
{
|
||||
for( int i=0; i<ParticleData::PDC_NUM_KEYS; i++ )
|
||||
for( S32 i=0; i<ParticleData::PDC_NUM_KEYS; i++ )
|
||||
{
|
||||
sizes[i] = sizeList[i];
|
||||
}
|
||||
|
|
@ -928,7 +940,7 @@ void ParticleEmitter::setSizes( F32 *sizeList )
|
|||
//-----------------------------------------------------------------------------
|
||||
void ParticleEmitter::setColors( ColorF *colorList )
|
||||
{
|
||||
for( int i=0; i<ParticleData::PDC_NUM_KEYS; i++ )
|
||||
for( S32 i=0; i<ParticleData::PDC_NUM_KEYS; i++ )
|
||||
{
|
||||
colors[i] = colorList[i];
|
||||
}
|
||||
|
|
@ -1279,7 +1291,7 @@ void ParticleEmitter::addParticle(const Point3F& pos,
|
|||
F32 initialVel = mDataBlock->ejectionVelocity;
|
||||
initialVel += (mDataBlock->velocityVariance * 2.0f * gRandGen.randF()) - mDataBlock->velocityVariance;
|
||||
|
||||
pNew->pos = pos + (ejectionAxis * mDataBlock->ejectionOffset);
|
||||
pNew->pos = pos + (ejectionAxis * (mDataBlock->ejectionOffset + mDataBlock->ejectionOffsetVariance* gRandGen.randF()) );
|
||||
pNew->vel = ejectionAxis * initialVel;
|
||||
pNew->orientDir = ejectionAxis;
|
||||
pNew->acc.set(0, 0, 0);
|
||||
|
|
@ -1443,7 +1455,7 @@ struct SortParticle
|
|||
};
|
||||
|
||||
// qsort callback function for particle sorting
|
||||
int QSORT_CALLBACK cmpSortParticles(const void* p1, const void* p2)
|
||||
S32 QSORT_CALLBACK cmpSortParticles(const void* p1, const void* p2)
|
||||
{
|
||||
const SortParticle* sp1 = (const SortParticle*)p1;
|
||||
const SortParticle* sp2 = (const SortParticle*)p2;
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class ParticleEmitterData : public GameBaseData
|
|||
F32 ejectionVelocity; ///< Ejection velocity
|
||||
F32 velocityVariance; ///< Variance for velocity between 0 and n
|
||||
F32 ejectionOffset; ///< Z offset from emitter point to eject from
|
||||
|
||||
F32 ejectionOffsetVariance; ///< Z offset Variance from emitter point to eject
|
||||
F32 thetaMin; ///< Minimum angle, from the horizontal plane, to eject from
|
||||
F32 thetaMax; ///< Maximum angle, from the horizontal plane, to eject from
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
|
||||
static const U32 dropHitMask =
|
||||
TerrainObjectType |
|
||||
InteriorObjectType |
|
||||
WaterObjectType |
|
||||
StaticShapeObjectType;
|
||||
|
||||
|
|
@ -1169,9 +1168,7 @@ void Precipitation::destroySplash(Raindrop *drop)
|
|||
PROFILE_START(PrecipDestroySplash);
|
||||
if (drop == mSplashHead)
|
||||
{
|
||||
mSplashHead = NULL;
|
||||
PROFILE_END();
|
||||
return;
|
||||
mSplashHead = mSplashHead->nextSplashDrop;
|
||||
}
|
||||
|
||||
if (drop->nextSplashDrop)
|
||||
|
|
@ -1728,6 +1725,7 @@ void Precipitation::renderObject(ObjectRenderInst *ri, SceneRenderState *state,
|
|||
// Do we need to relock the buffer?
|
||||
if ( !vertPtr )
|
||||
vertPtr = mRainVB.lock();
|
||||
if(!vertPtr) return;
|
||||
|
||||
// Set the proper texture coords... (it's fun!)
|
||||
tc = &mTexCoords[4*curr->texCoordIndex];
|
||||
|
|
@ -1818,6 +1816,7 @@ void Precipitation::renderObject(ObjectRenderInst *ri, SceneRenderState *state,
|
|||
// Do we need to relock the buffer?
|
||||
if ( !vertPtr )
|
||||
vertPtr = mRainVB.lock();
|
||||
if(!vertPtr) return;
|
||||
|
||||
vertPtr->point = pos + leftUp;
|
||||
vertPtr->texCoord = *tc;
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@ bool SplashData::preload(bool server, String &errorStr)
|
|||
// Splash
|
||||
//--------------------------------------------------------------------------
|
||||
Splash::Splash()
|
||||
: mDataBlock( NULL )
|
||||
{
|
||||
dMemset( mEmitterList, 0, sizeof( mEmitterList ) );
|
||||
|
||||
|
|
@ -353,6 +354,12 @@ bool Splash::onAdd()
|
|||
if(!conn || !Parent::onAdd())
|
||||
return false;
|
||||
|
||||
if( !mDataBlock )
|
||||
{
|
||||
Con::errorf("Splash::onAdd - Fail - No datablock");
|
||||
return false;
|
||||
}
|
||||
|
||||
mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance );
|
||||
mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance );
|
||||
|
||||
|
|
@ -408,8 +415,11 @@ void Splash::onRemove()
|
|||
|
||||
ringList.clear();
|
||||
|
||||
getSceneManager()->removeObjectFromScene(this);
|
||||
getContainer()->removeObject(this);
|
||||
if( getSceneManager() )
|
||||
getSceneManager()->removeObjectFromScene(this);
|
||||
|
||||
if( getContainer() )
|
||||
getContainer()->removeObject(this);
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
|
|
|||
379
Engine/source/T3D/gameBase/extended/extendedGameProcess.cpp
Normal file
379
Engine/source/T3D/gameBase/extended/extendedGameProcess.cpp
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
#include "platform/platform.h"
|
||||
#include "T3D/gameBase/extended/extendedGameProcess.h"
|
||||
#include "T3D/gameBase/extended/extendedMoveList.h"
|
||||
|
||||
#include "platform/profiler.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "core/dnet.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "core/frameAllocator.h"
|
||||
#include "core/util/refBase.h"
|
||||
#include "math/mPoint3.h"
|
||||
#include "math/mMatrix.h"
|
||||
#include "math/mathUtils.h"
|
||||
#include "T3D/gameBase/gameBase.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
#include "T3D/fx/cameraFXMgr.h"
|
||||
|
||||
MODULE_BEGIN( ProcessList )
|
||||
|
||||
MODULE_INIT
|
||||
{
|
||||
ExtendedServerProcessList::init();
|
||||
ExtendedClientProcessList::init();
|
||||
}
|
||||
|
||||
MODULE_SHUTDOWN
|
||||
{
|
||||
ExtendedServerProcessList::shutdown();
|
||||
ExtendedClientProcessList::shutdown();
|
||||
}
|
||||
|
||||
MODULE_END;
|
||||
|
||||
void ExtendedServerProcessList::init()
|
||||
{
|
||||
smServerProcessList = new ExtendedServerProcessList();
|
||||
}
|
||||
|
||||
void ExtendedServerProcessList::shutdown()
|
||||
{
|
||||
delete smServerProcessList;
|
||||
}
|
||||
|
||||
void ExtendedClientProcessList::init()
|
||||
{
|
||||
smClientProcessList = new ExtendedClientProcessList();
|
||||
}
|
||||
|
||||
void ExtendedClientProcessList::shutdown()
|
||||
{
|
||||
delete smClientProcessList;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// local work class
|
||||
struct GameBaseListNode
|
||||
{
|
||||
GameBaseListNode()
|
||||
{
|
||||
mPrev=this;
|
||||
mNext=this;
|
||||
mObject=NULL;
|
||||
}
|
||||
|
||||
GameBaseListNode * mPrev;
|
||||
GameBaseListNode * mNext;
|
||||
GameBase * mObject;
|
||||
|
||||
void linkBefore(GameBaseListNode * obj)
|
||||
{
|
||||
// Link this before obj
|
||||
mNext = obj;
|
||||
mPrev = obj->mPrev;
|
||||
obj->mPrev = this;
|
||||
mPrev->mNext = this;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// ExtendedClientProcessList
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
ExtendedClientProcessList::ExtendedClientProcessList()
|
||||
{
|
||||
}
|
||||
|
||||
bool ExtendedClientProcessList::advanceTime( SimTime timeDelta )
|
||||
{
|
||||
PROFILE_SCOPE( ExtendedClientProcessList_AdvanceTime );
|
||||
|
||||
if ( doBacklogged( timeDelta ) )
|
||||
return false;
|
||||
|
||||
bool ret = Parent::advanceTime( timeDelta );
|
||||
ProcessObject *obj = NULL;
|
||||
|
||||
AssertFatal( mLastDelta >= 0.0f && mLastDelta <= 1.0f, "mLastDelta is not zero to one.");
|
||||
|
||||
obj = mHead.mProcessLink.next;
|
||||
while ( obj != &mHead )
|
||||
{
|
||||
if ( obj->isTicking() )
|
||||
obj->interpolateTick( mLastDelta );
|
||||
|
||||
obj = obj->mProcessLink.next;
|
||||
}
|
||||
|
||||
// Inform objects of total elapsed delta so they can advance
|
||||
// client side animations.
|
||||
F32 dt = F32(timeDelta) / 1000;
|
||||
|
||||
// Update camera FX.
|
||||
gCamFXMgr.update( dt );
|
||||
|
||||
obj = mHead.mProcessLink.next;
|
||||
while ( obj != &mHead )
|
||||
{
|
||||
obj->advanceTime( dt );
|
||||
obj = obj->mProcessLink.next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void ExtendedClientProcessList::onAdvanceObjects()
|
||||
{
|
||||
PROFILE_SCOPE( ExtendedClientProcessList_OnAdvanceObjects );
|
||||
|
||||
GameConnection* connection = GameConnection::getConnectionToServer();
|
||||
if ( connection )
|
||||
{
|
||||
// process any demo blocks that are NOT moves, and exactly one move
|
||||
// we advance time in the demo stream by a move inserted on
|
||||
// each tick. So before doing the tick processing we advance
|
||||
// the demo stream until a move is ready
|
||||
if ( connection->isPlayingBack() )
|
||||
{
|
||||
U32 blockType;
|
||||
do
|
||||
{
|
||||
blockType = connection->getNextBlockType();
|
||||
bool res = connection->processNextBlock();
|
||||
// if there are no more blocks, exit out of this function,
|
||||
// as no more client time needs to process right now - we'll
|
||||
// get it all on the next advanceClientTime()
|
||||
if(!res)
|
||||
return;
|
||||
}
|
||||
while ( blockType != GameConnection::BlockTypeMove );
|
||||
}
|
||||
|
||||
connection->mMoveList->collectMove();
|
||||
advanceObjects();
|
||||
}
|
||||
else
|
||||
advanceObjects();
|
||||
}
|
||||
|
||||
void ExtendedClientProcessList::onTickObject( ProcessObject *obj )
|
||||
{
|
||||
PROFILE_SCOPE( ExtendedClientProcessList_OnTickObject );
|
||||
|
||||
// In case the object deletes itself during its processTick.
|
||||
SimObjectPtr<SceneObject> safePtr = static_cast<SceneObject*>( obj );
|
||||
|
||||
// Each object is either advanced a single tick, or if it's
|
||||
// being controlled by a client, ticked once for each pending move.
|
||||
ExtendedMove* extMovePtr;
|
||||
U32 numMoves;
|
||||
GameConnection* con = obj->getControllingClient();
|
||||
if ( con && con->getControlObject() == obj )
|
||||
{
|
||||
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList);
|
||||
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||||
if ( numMoves )
|
||||
{
|
||||
// Note: should only have a single move at this point
|
||||
AssertFatal(numMoves==1,"ClientProccessList::onTickObject: more than one move in queue");
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient());
|
||||
#endif
|
||||
|
||||
if ( obj->isTicking() )
|
||||
obj->processTick( extMovePtr );
|
||||
|
||||
if ( bool(safePtr) && obj->getControllingClient() )
|
||||
{
|
||||
U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() );
|
||||
|
||||
// set checksum if not set or check against stored value if set
|
||||
extMovePtr->checksum = newsum;
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("move checksum: %i, (start %i), (move %f %f %f)",
|
||||
movePtr->checksum,sum,movePtr->yaw,movePtr->y,movePtr->z);
|
||||
#endif
|
||||
}
|
||||
con->mMoveList->clearMoves( 1 );
|
||||
}
|
||||
}
|
||||
else if ( obj->isTicking() )
|
||||
obj->processTick( 0 );
|
||||
}
|
||||
|
||||
void ExtendedClientProcessList::advanceObjects()
|
||||
{
|
||||
PROFILE_SCOPE( ExtendedClientProcessList_AdvanceObjects );
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("Advance client time...");
|
||||
#endif
|
||||
|
||||
Parent::advanceObjects();
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("---------");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExtendedClientProcessList::clientCatchup( GameConnection * connection )
|
||||
{
|
||||
SimObjectPtr<GameBase> control = connection->getControlObject();
|
||||
if ( control )
|
||||
{
|
||||
ExtendedMove * extMovePtr;
|
||||
U32 numMoves;
|
||||
U32 m = 0;
|
||||
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(connection->mMoveList);
|
||||
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("client catching up... (%i)", numMoves);
|
||||
#endif
|
||||
|
||||
preTickSignal().trigger();
|
||||
|
||||
if ( control->isTicking() )
|
||||
for ( m = 0; m < numMoves; m++ )
|
||||
control->processTick( extMovePtr++ );
|
||||
|
||||
extMoveList->clearMoves( m );
|
||||
}
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("---------");
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// ServerProcessList
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
ExtendedServerProcessList::ExtendedServerProcessList()
|
||||
{
|
||||
}
|
||||
|
||||
void ExtendedServerProcessList::onPreTickObject( ProcessObject *pobj )
|
||||
{
|
||||
if ( pobj->mIsGameBase )
|
||||
{
|
||||
SimObjectPtr<GameBase> obj = getGameBase( pobj );
|
||||
|
||||
// Each object is either advanced a single tick, or if it's
|
||||
// being controlled by a client, ticked once for each pending move.
|
||||
GameConnection *con = obj->getControllingClient();
|
||||
|
||||
if ( con && con->getControlObject() == obj )
|
||||
{
|
||||
ExtendedMove* extMovePtr;
|
||||
U32 numMoves;
|
||||
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList);
|
||||
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||||
|
||||
if ( numMoves == 0 )
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("no moves on object %i, skip tick",obj->getId());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Parent::onPreTickObject (pobj );
|
||||
}
|
||||
|
||||
void ExtendedServerProcessList::onTickObject( ProcessObject *pobj )
|
||||
{
|
||||
PROFILE_SCOPE( ExtendedServerProcessList_OnTickObject );
|
||||
|
||||
// Each object is either advanced a single tick, or if it's
|
||||
// being controlled by a client, ticked once for each pending move.
|
||||
|
||||
GameConnection *con = pobj->getControllingClient();
|
||||
|
||||
if ( pobj->mIsGameBase && con && con->getControlObject() == pobj )
|
||||
{
|
||||
// In case the object is deleted during its own tick.
|
||||
SimObjectPtr<GameBase> obj = getGameBase( pobj );
|
||||
|
||||
ExtendedMove* extMovePtr;
|
||||
U32 m, numMoves;
|
||||
ExtendedMoveList* extMoveList = static_cast<ExtendedMoveList*>(con->mMoveList);
|
||||
extMoveList->getExtMoves( &extMovePtr, &numMoves );
|
||||
|
||||
// For debugging it can be useful to know when this happens.
|
||||
//if ( numMoves > 1 )
|
||||
// Con::printf( "numMoves: %i", numMoves );
|
||||
|
||||
// Do we really need to test the control object each iteration? Does it change?
|
||||
for ( m = 0; m < numMoves && con && con->getControlObject() == obj; m++, extMovePtr++ )
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient());
|
||||
#endif
|
||||
|
||||
if ( obj->isTicking() )
|
||||
obj->processTick( extMovePtr );
|
||||
|
||||
if ( con && con->getControlObject() == obj )
|
||||
{
|
||||
U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() );
|
||||
|
||||
// check move checksum
|
||||
if ( extMovePtr->checksum != newsum )
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
if( !obj->isAIControlled() )
|
||||
Con::printf("move %i checksum disagree: %i != %i, (start %i), (move %f %f %f)",
|
||||
extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z);
|
||||
#endif
|
||||
|
||||
extMovePtr->checksum = Move::ChecksumMismatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("move %i checksum agree: %i == %i, (start %i), (move %f %f %f)",
|
||||
extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extMoveList->clearMoves( m );
|
||||
}
|
||||
else if ( pobj->isTicking() )
|
||||
pobj->processTick( 0 );
|
||||
}
|
||||
|
||||
void ExtendedServerProcessList::advanceObjects()
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("Advance server time...");
|
||||
#endif
|
||||
|
||||
Parent::advanceObjects();
|
||||
|
||||
// Credit all connections with the elapsed tick
|
||||
SimGroup *clientGroup = Sim::getClientGroup();
|
||||
for(SimGroup::iterator i = clientGroup->begin(); i != clientGroup->end(); i++)
|
||||
{
|
||||
if (GameConnection *con = dynamic_cast<GameConnection *>(*i))
|
||||
{
|
||||
con->mMoveList->advanceMove();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("---------");
|
||||
#endif
|
||||
}
|
||||
60
Engine/source/T3D/gameBase/extended/extendedGameProcess.h
Normal file
60
Engine/source/T3D/gameBase/extended/extendedGameProcess.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef _GAMEPROCESS_EXTENDED_H_
|
||||
#define _GAMEPROCESS_EXTENDED_H_
|
||||
|
||||
//#include "T3D/gameBase/processList.h"
|
||||
#ifndef _GAMEPROCESS_H_
|
||||
#include "T3D/gameBase/gameProcess.h"
|
||||
#endif
|
||||
|
||||
class GameBase;
|
||||
class GameConnection;
|
||||
struct Move;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/// List to keep track of GameBases to process.
|
||||
class ExtendedClientProcessList : public ClientProcessList
|
||||
{
|
||||
typedef ClientProcessList Parent;
|
||||
|
||||
protected:
|
||||
|
||||
// ProcessList
|
||||
void onTickObject(ProcessObject *);
|
||||
void advanceObjects();
|
||||
void onAdvanceObjects();
|
||||
|
||||
public:
|
||||
|
||||
ExtendedClientProcessList();
|
||||
|
||||
// ProcessList
|
||||
bool advanceTime( SimTime timeDelta );
|
||||
|
||||
// ClientProcessList
|
||||
void clientCatchup( GameConnection *conn );
|
||||
|
||||
static void init();
|
||||
static void shutdown();
|
||||
};
|
||||
|
||||
class ExtendedServerProcessList : public ServerProcessList
|
||||
{
|
||||
typedef ServerProcessList Parent;
|
||||
|
||||
protected:
|
||||
|
||||
// ProcessList
|
||||
void onPreTickObject( ProcessObject *pobj );
|
||||
void onTickObject( ProcessObject *pobj );
|
||||
void advanceObjects();
|
||||
|
||||
public:
|
||||
|
||||
ExtendedServerProcessList();
|
||||
|
||||
static void init();
|
||||
static void shutdown();
|
||||
};
|
||||
|
||||
#endif // _GAMEPROCESS_EXTENDED_H_
|
||||
302
Engine/source/T3D/gameBase/extended/extendedMove.cpp
Normal file
302
Engine/source/T3D/gameBase/extended/extendedMove.cpp
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
#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, };
|
||||
bool ExtendedMoveManager::mRotIsEuler[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), "mvRotIsEuler%d", i);
|
||||
Con::addVariable(varName, TypeBool, &mRotIsEuler[i],
|
||||
"@brief Indicates that the given rotation is Euler angles.\n\n"
|
||||
"When false (the default) the given rotation is a four component angled axis "
|
||||
"(a vector and angle). When true, the given rotation is a three component "
|
||||
"Euler angle. When using Euler angles, the $mvRotA component of the ExtendedMove "
|
||||
"is ignored for this set of rotations.\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;
|
||||
|
||||
EulerBasedRotation[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
if(!EulerBasedRotation[i])
|
||||
{
|
||||
check = check || (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
|
||||
stream->writeFlag(EulerBasedRotation[i]);
|
||||
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(!EulerBasedRotation[i])
|
||||
{
|
||||
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
|
||||
EulerBasedRotation[i] = stream->readFlag();
|
||||
F32 scale = 1.0f;
|
||||
if(EulerBasedRotation[i])
|
||||
scale = M_2PI_F;
|
||||
if(stream->readFlag())
|
||||
{
|
||||
crotX[i] = stream->readInt(MaxRotationBits);
|
||||
rotX[i] = UNCLAMPROT(crotX[i]) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotX[i] = extBaseMove->rotX[i];
|
||||
}
|
||||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
crotY[i] = stream->readInt(MaxRotationBits);
|
||||
rotY[i] = UNCLAMPROT(crotY[i]) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotY[i] = extBaseMove->rotY[i];
|
||||
}
|
||||
|
||||
if(stream->readFlag())
|
||||
{
|
||||
crotZ[i] = stream->readInt(MaxRotationBits);
|
||||
rotZ[i] = UNCLAMPROT(crotZ[i]) * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
rotZ[i] = extBaseMove->rotZ[i];
|
||||
}
|
||||
|
||||
if(!EulerBasedRotation[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
|
||||
if(EulerBasedRotation[i])
|
||||
{
|
||||
crotX[i] = CLAMPROT(rotX[i] / M_2PI_F);
|
||||
crotY[i] = CLAMPROT(rotY[i] / M_2PI_F);
|
||||
crotZ[i] = CLAMPROT(rotZ[i] / M_2PI_F);
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
if(EulerBasedRotation[i])
|
||||
{
|
||||
rotX[i] = UNCLAMPROT(crotX[i]) * M_2PI_F;
|
||||
rotY[i] = UNCLAMPROT(crotY[i]) * M_2PI_F;
|
||||
rotZ[i] = UNCLAMPROT(crotZ[i]) * M_2PI_F;
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
}
|
||||
54
Engine/source/T3D/gameBase/extended/extendedMove.h
Normal file
54
Engine/source/T3D/gameBase/extended/extendedMove.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef _EXTENDEDMOVE_H_
|
||||
#define _EXTENDEDMOVE_H_
|
||||
|
||||
#include "T3D/gameBase/moveManager.h"
|
||||
#include "math/mQuat.h"
|
||||
|
||||
struct ExtendedMove : public Move
|
||||
{
|
||||
typedef Move Parent;
|
||||
|
||||
enum Constants {
|
||||
MaxPositionsRotations = 3,
|
||||
|
||||
MaxPositionBits = 13,
|
||||
MaxRotationBits = 16,
|
||||
};
|
||||
|
||||
// Position is in millimeters
|
||||
S32 posX[MaxPositionsRotations], posY[MaxPositionsRotations], posZ[MaxPositionsRotations];
|
||||
|
||||
bool EulerBasedRotation[MaxPositionsRotations];
|
||||
|
||||
F32 rotX[MaxPositionsRotations], rotY[MaxPositionsRotations], rotZ[MaxPositionsRotations], rotW[MaxPositionsRotations];
|
||||
|
||||
// Network clamped rotation
|
||||
S32 crotX[MaxPositionsRotations], crotY[MaxPositionsRotations], crotZ[MaxPositionsRotations], crotW[MaxPositionsRotations];
|
||||
|
||||
ExtendedMove();
|
||||
|
||||
virtual void pack(BitStream *stream, const Move * move = NULL);
|
||||
virtual void unpack(BitStream *stream, const Move * move = NULL);
|
||||
|
||||
virtual void clamp();
|
||||
virtual void unclamp();
|
||||
};
|
||||
|
||||
extern const ExtendedMove NullExtendedMove;
|
||||
|
||||
class ExtendedMoveManager
|
||||
{
|
||||
public:
|
||||
static S32 mPosX[ExtendedMove::MaxPositionsRotations];
|
||||
static S32 mPosY[ExtendedMove::MaxPositionsRotations];
|
||||
static S32 mPosZ[ExtendedMove::MaxPositionsRotations];
|
||||
static bool mRotIsEuler[ExtendedMove::MaxPositionsRotations];
|
||||
static F32 mRotAX[ExtendedMove::MaxPositionsRotations];
|
||||
static F32 mRotAY[ExtendedMove::MaxPositionsRotations];
|
||||
static F32 mRotAZ[ExtendedMove::MaxPositionsRotations];
|
||||
static F32 mRotAA[ExtendedMove::MaxPositionsRotations];
|
||||
|
||||
static void init();
|
||||
};
|
||||
|
||||
#endif // _EXTENDEDMOVE_H_
|
||||
380
Engine/source/T3D/gameBase/extended/extendedMoveList.cpp
Normal file
380
Engine/source/T3D/gameBase/extended/extendedMoveList.cpp
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
#include "platform/platform.h"
|
||||
#include "T3D/gameBase/extended/extendedMoveList.h"
|
||||
#include "T3D/gameBase/gameConnection.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
|
||||
#define MAX_MOVE_PACKET_SENDS 4
|
||||
|
||||
ExtendedMoveList::ExtendedMoveList()
|
||||
{
|
||||
mMoveCredit = MaxMoveCount;
|
||||
mControlMismatch = false;
|
||||
reset();
|
||||
}
|
||||
|
||||
void ExtendedMoveList::reset()
|
||||
{
|
||||
mLastMoveAck = 0;
|
||||
mLastClientMove = 0;
|
||||
mFirstMoveIndex = 0;
|
||||
|
||||
mExtMoveVec.clear();
|
||||
}
|
||||
|
||||
bool ExtendedMoveList::getNextExtMove( ExtendedMove &curMove )
|
||||
{
|
||||
if ( mExtMoveVec.size() > MaxMoveQueueSize )
|
||||
return false;
|
||||
|
||||
// From MoveList
|
||||
F32 pitchAdd = MoveManager::mPitchUpSpeed - MoveManager::mPitchDownSpeed;
|
||||
F32 yawAdd = MoveManager::mYawLeftSpeed - MoveManager::mYawRightSpeed;
|
||||
F32 rollAdd = MoveManager::mRollRightSpeed - MoveManager::mRollLeftSpeed;
|
||||
|
||||
curMove.pitch = MoveManager::mPitch + pitchAdd;
|
||||
curMove.yaw = MoveManager::mYaw + yawAdd;
|
||||
curMove.roll = MoveManager::mRoll + rollAdd;
|
||||
|
||||
MoveManager::mPitch = 0;
|
||||
MoveManager::mYaw = 0;
|
||||
MoveManager::mRoll = 0;
|
||||
|
||||
curMove.x = MoveManager::mRightAction - MoveManager::mLeftAction + MoveManager::mXAxis_L;
|
||||
curMove.y = MoveManager::mForwardAction - MoveManager::mBackwardAction + MoveManager::mYAxis_L;
|
||||
curMove.z = MoveManager::mUpAction - MoveManager::mDownAction;
|
||||
|
||||
curMove.freeLook = MoveManager::mFreeLook;
|
||||
curMove.deviceIsKeyboardMouse = MoveManager::mDeviceIsKeyboardMouse;
|
||||
|
||||
for(U32 i = 0; i < MaxTriggerKeys; i++)
|
||||
{
|
||||
curMove.trigger[i] = false;
|
||||
if(MoveManager::mTriggerCount[i] & 1)
|
||||
curMove.trigger[i] = true;
|
||||
else if(!(MoveManager::mPrevTriggerCount[i] & 1) && MoveManager::mPrevTriggerCount[i] != MoveManager::mTriggerCount[i])
|
||||
curMove.trigger[i] = true;
|
||||
MoveManager::mPrevTriggerCount[i] = MoveManager::mTriggerCount[i];
|
||||
}
|
||||
|
||||
for(U32 i=0; i<ExtendedMove::MaxPositionsRotations; ++i)
|
||||
{
|
||||
// Process position
|
||||
curMove.posX[i] = ExtendedMoveManager::mPosX[i];
|
||||
curMove.posY[i] = ExtendedMoveManager::mPosY[i];
|
||||
curMove.posZ[i] = ExtendedMoveManager::mPosZ[i];
|
||||
|
||||
// Process rotation. There are two possible forms of rotation: Angle Axis and Euler angles.
|
||||
curMove.EulerBasedRotation[i] = ExtendedMoveManager::mRotIsEuler[i];
|
||||
if(curMove.EulerBasedRotation[i])
|
||||
{
|
||||
// Euler angle based rotation passed in as degrees. We only need to work with three components.
|
||||
curMove.rotX[i] = mDegToRad(ExtendedMoveManager::mRotAX[i]);
|
||||
curMove.rotY[i] = mDegToRad(ExtendedMoveManager::mRotAY[i]);
|
||||
curMove.rotZ[i] = mDegToRad(ExtendedMoveManager::mRotAZ[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Rotation is passed in as an Angle Axis in degrees. We need to convert this into a Quat.
|
||||
QuatF q(Point3F(ExtendedMoveManager::mRotAX[i], ExtendedMoveManager::mRotAY[i], ExtendedMoveManager::mRotAZ[i]), mDegToRad(ExtendedMoveManager::mRotAA[i]));
|
||||
curMove.rotX[i] = q.x;
|
||||
curMove.rotY[i] = q.y;
|
||||
curMove.rotZ[i] = q.z;
|
||||
curMove.rotW[i] = q.w;
|
||||
}
|
||||
}
|
||||
|
||||
if (mConnection->getControlObject())
|
||||
mConnection->getControlObject()->preprocessMove(&curMove);
|
||||
|
||||
curMove.clamp(); // clamp for net traffic
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 ExtendedMoveList::getMoves(Move** movePtr,U32* numMoves)
|
||||
{
|
||||
// We don't want to be here
|
||||
AssertFatal(0, "getMoves() called");
|
||||
|
||||
numMoves = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U32 ExtendedMoveList::getExtMoves( ExtendedMove** movePtr, U32 *numMoves )
|
||||
{
|
||||
if (!mConnection->isConnectionToServer())
|
||||
{
|
||||
if (mExtMoveVec.size() > mMoveCredit)
|
||||
mExtMoveVec.setSize(mMoveCredit);
|
||||
}
|
||||
|
||||
// From MoveList but converted to use mExtMoveVec
|
||||
if (mConnection->isConnectionToServer())
|
||||
{
|
||||
// give back moves starting at the last client move...
|
||||
|
||||
AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request");
|
||||
AssertFatal(mLastClientMove - mFirstMoveIndex <= mExtMoveVec.size(), "Desynched first and last move.");
|
||||
*numMoves = mExtMoveVec.size() - mLastClientMove + mFirstMoveIndex;
|
||||
*movePtr = mExtMoveVec.address() + mLastClientMove - mFirstMoveIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// return the full list
|
||||
*numMoves = mExtMoveVec.size();
|
||||
*movePtr = mExtMoveVec.begin();
|
||||
}
|
||||
|
||||
return *numMoves;
|
||||
}
|
||||
|
||||
void ExtendedMoveList::collectMove()
|
||||
{
|
||||
ExtendedMove mv;
|
||||
if (mConnection)
|
||||
{
|
||||
if(!mConnection->isPlayingBack() && getNextExtMove(mv))
|
||||
{
|
||||
mv.checksum=Move::ChecksumMismatch;
|
||||
pushMove(mv);
|
||||
mConnection->recordBlock(GameConnection::BlockTypeMove, sizeof(ExtendedMove), &mv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(getNextExtMove(mv))
|
||||
{
|
||||
mv.checksum=Move::ChecksumMismatch;
|
||||
pushMove(mv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtendedMoveList::pushMove(const Move &mv)
|
||||
{
|
||||
const ExtendedMove* extMove = dynamic_cast<const ExtendedMove*>(&mv);
|
||||
AssertFatal(extMove, "Regular Move struct passed to pushMove()");
|
||||
|
||||
pushExtMove(*extMove);
|
||||
}
|
||||
|
||||
void ExtendedMoveList::pushExtMove( const ExtendedMove &mv )
|
||||
{
|
||||
U32 id = mFirstMoveIndex + mExtMoveVec.size();
|
||||
U32 sz = mExtMoveVec.size();
|
||||
mExtMoveVec.push_back(mv);
|
||||
mExtMoveVec[sz].id = id;
|
||||
mExtMoveVec[sz].sendCount = 0;
|
||||
}
|
||||
|
||||
void ExtendedMoveList::clearMoves(U32 count)
|
||||
{
|
||||
if (!mConnection->isConnectionToServer())
|
||||
{
|
||||
count = mClamp(count,0,mMoveCredit);
|
||||
mMoveCredit -= count;
|
||||
}
|
||||
|
||||
// From MoveList but converted to use mExtMoveVec
|
||||
if (mConnection->isConnectionToServer())
|
||||
{
|
||||
mLastClientMove += count;
|
||||
AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request");
|
||||
AssertFatal(mLastClientMove - mFirstMoveIndex <= mExtMoveVec.size(), "Desynched first and last move.");
|
||||
if (!mConnection)
|
||||
// drop right away if no connection
|
||||
ackMoves(count);
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertFatal(count <= mExtMoveVec.size(),"GameConnection: Clearing too many moves");
|
||||
for (S32 i=0; i<count; i++)
|
||||
if (mExtMoveVec[i].checksum == Move::ChecksumMismatch)
|
||||
mControlMismatch = true;
|
||||
else
|
||||
mControlMismatch = false;
|
||||
if (count == mExtMoveVec.size())
|
||||
mExtMoveVec.clear();
|
||||
else
|
||||
while (count--)
|
||||
mExtMoveVec.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void ExtendedMoveList::advanceMove()
|
||||
{
|
||||
AssertFatal(!mConnection->isConnectionToServer(), "Cannot inc move credit on the client.");
|
||||
|
||||
// Game tick increment
|
||||
mMoveCredit++;
|
||||
if (mMoveCredit > MaxMoveCount)
|
||||
mMoveCredit = MaxMoveCount;
|
||||
|
||||
// Clear pending moves for the elapsed time if there
|
||||
// is no control object.
|
||||
if ( mConnection->getControlObject() == NULL )
|
||||
mExtMoveVec.clear();
|
||||
}
|
||||
|
||||
void ExtendedMoveList::clientWriteMovePacket(BitStream *bstream)
|
||||
{
|
||||
AssertFatal(mLastMoveAck == mFirstMoveIndex, "Invalid move index.");
|
||||
U32 count = mExtMoveVec.size();
|
||||
|
||||
ExtendedMove* extMove = mExtMoveVec.address();
|
||||
U32 start = mLastMoveAck;
|
||||
U32 offset;
|
||||
for(offset = 0; offset < count; offset++)
|
||||
if(extMove[offset].sendCount < MAX_MOVE_PACKET_SENDS)
|
||||
break;
|
||||
if(offset == count && count != 0)
|
||||
offset--;
|
||||
|
||||
start += offset;
|
||||
count -= offset;
|
||||
|
||||
if (count > MaxMoveCount)
|
||||
count = MaxMoveCount;
|
||||
bstream->writeInt(start,32);
|
||||
bstream->writeInt(count,MoveCountBits);
|
||||
ExtendedMove* prevExtMove = NULL;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
extMove[offset + i].sendCount++;
|
||||
extMove[offset + i].pack(bstream,prevExtMove);
|
||||
bstream->writeInt(extMove[offset + i].checksum & (~(0xFFFFFFFF << Move::ChecksumBits)),Move::ChecksumBits);
|
||||
prevExtMove = &extMove[offset+i];
|
||||
}
|
||||
}
|
||||
|
||||
void ExtendedMoveList::serverReadMovePacket(BitStream *bstream)
|
||||
{
|
||||
// Server side packet read.
|
||||
U32 start = bstream->readInt(32);
|
||||
U32 count = bstream->readInt(MoveCountBits);
|
||||
|
||||
ExtendedMove* prevExtMove = NULL;
|
||||
ExtendedMove prevExtMoveHolder;
|
||||
|
||||
// Skip forward (must be starting up), or over the moves
|
||||
// we already have.
|
||||
int skip = mLastMoveAck - start;
|
||||
if (skip < 0)
|
||||
{
|
||||
mLastMoveAck = start;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (skip > count)
|
||||
skip = count;
|
||||
for (int i = 0; i < skip; i++)
|
||||
{
|
||||
prevExtMoveHolder.unpack(bstream,prevExtMove);
|
||||
prevExtMoveHolder.checksum = bstream->readInt(Move::ChecksumBits);
|
||||
prevExtMove = &prevExtMoveHolder;
|
||||
S32 idx = mExtMoveVec.size()-skip+i;
|
||||
if (idx>=0)
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
if (mExtMoveVec[idx].checksum != prevExtMoveHolder.checksum)
|
||||
Con::printf("updated checksum on move %i from %i to %i",mExtMoveVec[idx].id,mExtMoveVec[idx].checksum,prevExtMoveHolder.checksum);
|
||||
#endif
|
||||
mExtMoveVec[idx].checksum = prevExtMoveHolder.checksum;
|
||||
}
|
||||
}
|
||||
start += skip;
|
||||
count = count - skip;
|
||||
}
|
||||
|
||||
// Put the rest on the move list.
|
||||
int index = mExtMoveVec.size();
|
||||
mExtMoveVec.increment(count);
|
||||
while (index < mExtMoveVec.size())
|
||||
{
|
||||
mExtMoveVec[index].unpack(bstream,prevExtMove);
|
||||
mExtMoveVec[index].checksum = bstream->readInt(Move::ChecksumBits);
|
||||
prevExtMove = &mExtMoveVec[index];
|
||||
mExtMoveVec[index].id = start++;
|
||||
index ++;
|
||||
}
|
||||
|
||||
mLastMoveAck += count;
|
||||
}
|
||||
|
||||
void ExtendedMoveList::serverWriteMovePacket(BitStream * bstream)
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("ack %i minus %i",mLastMoveAck,mExtMoveVec.size());
|
||||
#endif
|
||||
|
||||
// acknowledge only those moves that have been ticked
|
||||
bstream->writeInt(mLastMoveAck - mExtMoveVec.size(),32);
|
||||
}
|
||||
|
||||
void ExtendedMoveList::clientReadMovePacket(BitStream * bstream)
|
||||
{
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("pre move ack: %i", mLastMoveAck);
|
||||
#endif
|
||||
|
||||
mLastMoveAck = bstream->readInt(32);
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET_MOVES
|
||||
Con::printf("post move ack %i, first move %i, last move %i", mLastMoveAck, mFirstMoveIndex, mLastClientMove);
|
||||
#endif
|
||||
|
||||
if (mLastMoveAck < mFirstMoveIndex)
|
||||
mLastMoveAck = mFirstMoveIndex;
|
||||
|
||||
if(mLastMoveAck > mLastClientMove)
|
||||
mLastClientMove = mLastMoveAck;
|
||||
while(mFirstMoveIndex < mLastMoveAck)
|
||||
{
|
||||
if (mExtMoveVec.size())
|
||||
{
|
||||
mExtMoveVec.pop_front();
|
||||
mFirstMoveIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertWarn(1, "Popping off too many moves!");
|
||||
mFirstMoveIndex = mLastMoveAck;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtendedMoveList::isBacklogged()
|
||||
{
|
||||
if ( !mConnection->isConnectionToServer() )
|
||||
return false;
|
||||
|
||||
return mLastClientMove - mFirstMoveIndex == mExtMoveVec.size() &&
|
||||
mExtMoveVec.size() >= MaxMoveCount;
|
||||
}
|
||||
|
||||
bool ExtendedMoveList::areMovesPending()
|
||||
{
|
||||
return mConnection->isConnectionToServer() ?
|
||||
mExtMoveVec.size() - mLastClientMove + mFirstMoveIndex :
|
||||
mExtMoveVec.size();
|
||||
}
|
||||
|
||||
void ExtendedMoveList::ackMoves(U32 count)
|
||||
{
|
||||
mLastMoveAck += count;
|
||||
if(mLastMoveAck > mLastClientMove)
|
||||
mLastClientMove = mLastMoveAck;
|
||||
while(mFirstMoveIndex < mLastMoveAck)
|
||||
{
|
||||
if (mExtMoveVec.size())
|
||||
{
|
||||
mExtMoveVec.pop_front();
|
||||
mFirstMoveIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
AssertWarn(1, "Popping off too many moves!");
|
||||
mFirstMoveIndex = mLastMoveAck;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
Engine/source/T3D/gameBase/extended/extendedMoveList.h
Normal file
55
Engine/source/T3D/gameBase/extended/extendedMoveList.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef _EXTENDEDMOVELIST_H_
|
||||
#define _EXTENDEDMOVELIST_H_
|
||||
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
#ifndef _MOVELIST_H_
|
||||
#include "T3D/gameBase/moveList.h"
|
||||
#endif
|
||||
|
||||
#include "T3D/gameBase/extended/extendedMove.h"
|
||||
|
||||
class ExtendedMoveList : public MoveList
|
||||
{
|
||||
typedef MoveList Parent;
|
||||
|
||||
public:
|
||||
|
||||
ExtendedMoveList();
|
||||
|
||||
void clientWriteMovePacket(BitStream *);
|
||||
void clientReadMovePacket(BitStream *);
|
||||
|
||||
void serverWriteMovePacket(BitStream *);
|
||||
void serverReadMovePacket(BitStream *);
|
||||
|
||||
void advanceMove();
|
||||
void onAdvanceObjects() {}
|
||||
U32 getMoves(Move** movePtr,U32* numMoves);
|
||||
U32 getExtMoves( ExtendedMove** movePtr, U32 *numMoves );
|
||||
|
||||
void collectMove();
|
||||
void pushMove( const Move &mv );
|
||||
void pushExtMove( const ExtendedMove &mv );
|
||||
void clearMoves( U32 count );
|
||||
|
||||
virtual void reset();
|
||||
|
||||
bool isBacklogged();
|
||||
|
||||
bool areMovesPending();
|
||||
|
||||
void ackMoves( U32 count );
|
||||
|
||||
protected:
|
||||
|
||||
U32 mMoveCredit;
|
||||
|
||||
Vector<ExtendedMove> mExtMoveVec;
|
||||
|
||||
protected:
|
||||
bool getNextExtMove( ExtendedMove &curMove );
|
||||
};
|
||||
|
||||
#endif // _EXTENDEDMOVELIST_H_
|
||||
|
|
@ -614,7 +614,7 @@ void GameBase::onUnmount( SceneObject *obj, S32 node )
|
|||
|
||||
bool GameBase::setDataBlockProperty( void *obj, const char *index, const char *db)
|
||||
{
|
||||
if( db == NULL || !db || !db[ 0 ] )
|
||||
if( db == NULL || !db[ 0 ] )
|
||||
{
|
||||
Con::errorf( "GameBase::setDataBlockProperty - Can't unset datablock on GameBase objects" );
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -409,8 +409,8 @@ public:
|
|||
virtual bool isValidCameraFov( F32 fov ) { return true; }
|
||||
virtual bool useObjsEyePoint() const { return false; }
|
||||
virtual bool onlyFirstPerson() const { return false; }
|
||||
virtual F32 getDamageFlash() const { return 1.0f; }
|
||||
virtual F32 getWhiteOut() const { return 1.0f; }
|
||||
virtual F32 getDamageFlash() const { return 0.0f; }
|
||||
virtual F32 getWhiteOut() const { return 0.0f; }
|
||||
|
||||
// Not implemented here, but should return the Camera to world transformation matrix
|
||||
virtual void getCameraTransform (F32 *pos, MatrixF *mat ) { *mat = MatrixF::Identity; }
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#ifdef TORQUE_HIFI_NET
|
||||
#include "T3D/gameBase/hifi/hifiMoveList.h"
|
||||
#elif defined TORQUE_EXTENDED_MOVE
|
||||
#include "T3D/gameBase/extended/extendedMoveList.h"
|
||||
#else
|
||||
#include "T3D/gameBase/std/stdMoveList.h"
|
||||
#endif
|
||||
|
|
@ -175,6 +177,8 @@ GameConnection::GameConnection()
|
|||
|
||||
#ifdef TORQUE_HIFI_NET
|
||||
mMoveList = new HifiMoveList();
|
||||
#elif defined TORQUE_EXTENDED_MOVE
|
||||
mMoveList = new ExtendedMoveList();
|
||||
#else
|
||||
mMoveList = new StdMoveList();
|
||||
#endif
|
||||
|
|
@ -215,6 +219,14 @@ GameConnection::GameConnection()
|
|||
// first person
|
||||
mFirstPerson = true;
|
||||
mUpdateFirstPerson = false;
|
||||
|
||||
// Control scheme
|
||||
mUpdateControlScheme = false;
|
||||
mAbsoluteRotation = false;
|
||||
mAddYawToAbsRot = false;
|
||||
mAddPitchToAbsRot = false;
|
||||
|
||||
clearDisplayDevice();
|
||||
}
|
||||
|
||||
GameConnection::~GameConnection()
|
||||
|
|
@ -740,7 +752,15 @@ void GameConnection::setFirstPerson(bool firstPerson)
|
|||
mUpdateFirstPerson = true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void GameConnection::setControlSchemeParameters(bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot)
|
||||
{
|
||||
mAbsoluteRotation = absoluteRotation;
|
||||
mAddYawToAbsRot = addYawToAbsRot;
|
||||
mAddPitchToAbsRot = addPitchToAbsRot;
|
||||
mUpdateControlScheme = true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -823,6 +843,11 @@ void GameConnection::writeDemoStartBlock(ResizeBitStream *stream)
|
|||
stream->write(mCameraPos);
|
||||
stream->write(mCameraSpeed);
|
||||
|
||||
// Control scheme
|
||||
stream->write(mAbsoluteRotation);
|
||||
stream->write(mAddYawToAbsRot);
|
||||
stream->write(mAddPitchToAbsRot);
|
||||
|
||||
stream->writeString(Con::getVariable("$Client::MissionFile"));
|
||||
|
||||
mMoveList->writeDemoStartBlock(stream);
|
||||
|
|
@ -899,6 +924,11 @@ bool GameConnection::readDemoStartBlock(BitStream *stream)
|
|||
stream->read(&mCameraPos);
|
||||
stream->read(&mCameraSpeed);
|
||||
|
||||
// Control scheme
|
||||
stream->read(&mAbsoluteRotation);
|
||||
stream->read(&mAddYawToAbsRot);
|
||||
stream->read(&mAddPitchToAbsRot);
|
||||
|
||||
char buf[256];
|
||||
stream->readString(buf);
|
||||
Con::setVariable("$Client::MissionFile",buf);
|
||||
|
|
@ -1075,6 +1105,16 @@ void GameConnection::readPacket(BitStream *bstream)
|
|||
else
|
||||
setCameraObject(0);
|
||||
|
||||
// server changed control scheme
|
||||
if(bstream->readFlag())
|
||||
{
|
||||
bool absoluteRotation = bstream->readFlag();
|
||||
bool addYawToAbsRot = bstream->readFlag();
|
||||
bool addPitchToAbsRot = bstream->readFlag();
|
||||
setControlSchemeParameters(absoluteRotation, addYawToAbsRot, addPitchToAbsRot);
|
||||
mUpdateControlScheme = false;
|
||||
}
|
||||
|
||||
// server changed first person
|
||||
if(bstream->readFlag())
|
||||
{
|
||||
|
|
@ -1105,6 +1145,16 @@ void GameConnection::readPacket(BitStream *bstream)
|
|||
if (bstream->readFlag())
|
||||
mControlForceMismatch = true;
|
||||
|
||||
// client changed control scheme
|
||||
if(bstream->readFlag())
|
||||
{
|
||||
bool absoluteRotation = bstream->readFlag();
|
||||
bool addYawToAbsRot = bstream->readFlag();
|
||||
bool addPitchToAbsRot = bstream->readFlag();
|
||||
setControlSchemeParameters(absoluteRotation, addYawToAbsRot, addPitchToAbsRot);
|
||||
mUpdateControlScheme = false;
|
||||
}
|
||||
|
||||
// client changed first person
|
||||
if(bstream->readFlag())
|
||||
{
|
||||
|
|
@ -1167,6 +1217,15 @@ void GameConnection::writePacket(BitStream *bstream, PacketNotify *note)
|
|||
}
|
||||
bstream->writeFlag(forceUpdate);
|
||||
|
||||
// Control scheme changed?
|
||||
if(bstream->writeFlag(mUpdateControlScheme))
|
||||
{
|
||||
bstream->writeFlag(mAbsoluteRotation);
|
||||
bstream->writeFlag(mAddYawToAbsRot);
|
||||
bstream->writeFlag(mAddPitchToAbsRot);
|
||||
mUpdateControlScheme = false;
|
||||
}
|
||||
|
||||
// first person changed?
|
||||
if(bstream->writeFlag(mUpdateFirstPerson))
|
||||
{
|
||||
|
|
@ -1255,6 +1314,15 @@ void GameConnection::writePacket(BitStream *bstream, PacketNotify *note)
|
|||
else
|
||||
bstream->writeFlag( false );
|
||||
|
||||
// Control scheme changed?
|
||||
if(bstream->writeFlag(mUpdateControlScheme))
|
||||
{
|
||||
bstream->writeFlag(mAbsoluteRotation);
|
||||
bstream->writeFlag(mAddYawToAbsRot);
|
||||
bstream->writeFlag(mAddPitchToAbsRot);
|
||||
mUpdateControlScheme = false;
|
||||
}
|
||||
|
||||
// first person changed?
|
||||
if(bstream->writeFlag(mUpdateFirstPerson))
|
||||
{
|
||||
|
|
@ -1727,6 +1795,13 @@ DefineEngineMethod( GameConnection, setControlObject, bool, (GameBase* ctrlObj),
|
|||
return true;
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, clearDisplayDevice, void, (),,
|
||||
"@brief Clear any display device.\n\n"
|
||||
"A display device may define a number of properties that are used during rendering.\n\n")
|
||||
{
|
||||
object->clearDisplayDevice();
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, getControlObject, GameBase*, (),,
|
||||
"@brief On the server, returns the object that the client is controlling."
|
||||
"By default the control object is an instance of the Player class, but can also be an instance "
|
||||
|
|
@ -2105,3 +2180,21 @@ DefineEngineMethod( GameConnection, setFirstPerson, void, (bool firstPerson),,
|
|||
{
|
||||
object->setFirstPerson(firstPerson);
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, setControlSchemeParameters, void, (bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot),,
|
||||
"@brief Set the control scheme that may be used by a connection's control object.\n\n"
|
||||
|
||||
"@param absoluteRotation Use absolute rotation values from client, likely through ExtendedMove.\n"
|
||||
"@param addYawToAbsRot Add relative yaw control to the absolute rotation calculation. Only useful when absoluteRotation is true.\n\n" )
|
||||
{
|
||||
object->setControlSchemeParameters(absoluteRotation, addYawToAbsRot, addPitchToAbsRot);
|
||||
}
|
||||
|
||||
DefineEngineMethod( GameConnection, getControlSchemeAbsoluteRotation, bool, (),,
|
||||
"@brief Get the connection's control scheme absolute rotation property.\n\n"
|
||||
|
||||
"@return True if the connection's control object should use an absolute rotation control scheme.\n\n"
|
||||
"@see GameConnection::setControlSchemeParameters()\n\n")
|
||||
{
|
||||
return object->getControlSchemeAbsoluteRotation();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ enum GameConnectionConstants
|
|||
DataBlockQueueCount = 16
|
||||
};
|
||||
|
||||
class IDisplayDevice;
|
||||
class SFXProfile;
|
||||
class MatrixF;
|
||||
class MatrixF;
|
||||
|
|
@ -86,6 +87,16 @@ private:
|
|||
F32 mCameraFov; ///< Current camera fov (in degrees).
|
||||
F32 mCameraPos; ///< Current camera pos (0-1).
|
||||
F32 mCameraSpeed; ///< Camera in/out speed.
|
||||
|
||||
IDisplayDevice* mDisplayDevice; ///< Optional client display device that imposes rendering properties.
|
||||
/// @}
|
||||
|
||||
/// @name Client side control scheme that may be referenced by control objects
|
||||
/// @{
|
||||
bool mUpdateControlScheme; ///< Set to notify client or server of control scheme change
|
||||
bool mAbsoluteRotation; ///< Use absolute rotation values from client, likely through ExtendedMove
|
||||
bool mAddYawToAbsRot; ///< Add relative yaw control to the absolute rotation calculation. Only useful with mAbsoluteRotation.
|
||||
bool mAddPitchToAbsRot; ///< Add relative pitch control to the absolute rotation calculation. Only useful with mAbsoluteRotation.
|
||||
/// @}
|
||||
|
||||
public:
|
||||
|
|
@ -263,6 +274,16 @@ public:
|
|||
|
||||
void setFirstPerson(bool firstPerson);
|
||||
|
||||
bool hasDisplayDevice() const { return mDisplayDevice != NULL; }
|
||||
const IDisplayDevice* getDisplayDevice() const { return mDisplayDevice; }
|
||||
void setDisplayDevice(IDisplayDevice* display) { mDisplayDevice = display; }
|
||||
void clearDisplayDevice() { mDisplayDevice = NULL; }
|
||||
|
||||
void setControlSchemeParameters(bool absoluteRotation, bool addYawToAbsRot, bool addPitchToAbsRot);
|
||||
bool getControlSchemeAbsoluteRotation() {return mAbsoluteRotation;}
|
||||
bool getControlSchemeAddYawToAbsRot() {return mAddYawToAbsRot;}
|
||||
bool getControlSchemeAddPitchToAbsRot() {return mAddPitchToAbsRot;}
|
||||
|
||||
/// @}
|
||||
|
||||
void detectLag();
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ public:
|
|||
/// Reset move list back to last acknowledged move.
|
||||
void resetCatchup() { mLastClientMove = mLastMoveAck; }
|
||||
|
||||
void collectMove();
|
||||
void pushMove( const Move &mv );
|
||||
virtual void collectMove();
|
||||
virtual void pushMove( const Move &mv );
|
||||
virtual void clearMoves( U32 count );
|
||||
|
||||
virtual void markControlDirty() { mLastClientMove = mLastMoveAck; }
|
||||
|
|
@ -85,15 +85,15 @@ public:
|
|||
void clearMismatch() { mControlMismatch = false; }
|
||||
|
||||
/// Clear out all moves in the list and reset to initial state.
|
||||
void reset();
|
||||
virtual void reset();
|
||||
|
||||
/// If there are no pending moves and the input queue is full,
|
||||
/// then the connection to the server must be clogged.
|
||||
bool isBacklogged();
|
||||
virtual bool isBacklogged();
|
||||
|
||||
bool areMovesPending();
|
||||
virtual bool areMovesPending();
|
||||
|
||||
void ackMoves( U32 count );
|
||||
virtual void ackMoves( U32 count );
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
|||
|
|
@ -66,20 +66,7 @@ F32 MoveManager::mYAxis_R = 0;
|
|||
U32 MoveManager::mTriggerCount[MaxTriggerKeys] = { 0, };
|
||||
U32 MoveManager::mPrevTriggerCount[MaxTriggerKeys] = { 0, };
|
||||
|
||||
const Move NullMove =
|
||||
{
|
||||
/*px=*/16, /*py=*/16, /*pz=*/16,
|
||||
/*pyaw=*/0, /*ppitch=*/0, /*proll=*/0,
|
||||
/*x=*/0, /*y=*/0,/*z=*/0,
|
||||
/*yaw=*/0, /*pitch=*/0, /*roll=*/0,
|
||||
/*id=*/0,
|
||||
/*sendCount=*/0,
|
||||
|
||||
/*checksum=*/false,
|
||||
/*deviceIsKeyboardMouse=*/false,
|
||||
/*freeLook=*/false,
|
||||
/*triggers=*/{false,false,false,false,false,false}
|
||||
};
|
||||
const Move NullMove;
|
||||
|
||||
void MoveManager::init()
|
||||
{
|
||||
|
|
@ -161,6 +148,26 @@ void MoveManager::init()
|
|||
}
|
||||
}
|
||||
|
||||
Move::Move()
|
||||
{
|
||||
px=16; py=16; pz=16;
|
||||
pyaw=0; ppitch=0; proll=0;
|
||||
x=0; y=0; z=0;
|
||||
yaw=0; pitch=0; roll=0;
|
||||
id=0;
|
||||
sendCount=0;
|
||||
|
||||
checksum = false;
|
||||
deviceIsKeyboardMouse = false;
|
||||
freeLook = false;
|
||||
trigger[0] = false;
|
||||
trigger[1] = false;
|
||||
trigger[2] = false;
|
||||
trigger[3] = false;
|
||||
trigger[4] = false;
|
||||
trigger[5] = false;
|
||||
}
|
||||
|
||||
static inline F32 clampFloatWrap(F32 val)
|
||||
{
|
||||
return val - F32(S32(val));
|
||||
|
|
@ -235,6 +242,11 @@ void Move::pack(BitStream *stream, const Move * basemove)
|
|||
if (!basemove)
|
||||
basemove = &NullMove;
|
||||
|
||||
packMove(stream, basemove, alwaysWriteAll);
|
||||
}
|
||||
|
||||
bool Move::packMove(BitStream *stream, const Move* basemove, bool alwaysWriteAll)
|
||||
{
|
||||
S32 i;
|
||||
bool triggerDifferent = false;
|
||||
for (i=0; i < MaxTriggerKeys; i++)
|
||||
|
|
@ -272,6 +284,8 @@ void Move::pack(BitStream *stream, const Move * basemove)
|
|||
for(i = 0; i < MaxTriggerKeys; i++)
|
||||
stream->writeFlag(trigger[i]);
|
||||
}
|
||||
|
||||
return (triggerDifferent || somethingDifferent);
|
||||
}
|
||||
|
||||
void Move::unpack(BitStream *stream, const Move * basemove)
|
||||
|
|
@ -280,7 +294,20 @@ void Move::unpack(BitStream *stream, const Move * basemove)
|
|||
if (!basemove)
|
||||
basemove=&NullMove;
|
||||
|
||||
if (alwaysReadAll || stream->readFlag())
|
||||
bool readMove = unpackMove(stream, basemove, alwaysReadAll);
|
||||
if(!readMove)
|
||||
*this = *basemove;
|
||||
}
|
||||
|
||||
bool Move::unpackMove(BitStream *stream, const Move* basemove, bool alwaysReadAll)
|
||||
{
|
||||
bool readMove = alwaysReadAll;
|
||||
if(!readMove)
|
||||
{
|
||||
readMove = stream->readFlag();
|
||||
}
|
||||
|
||||
if (readMove)
|
||||
{
|
||||
pyaw = stream->readFlag() ? stream->readInt(16) : basemove->pyaw;
|
||||
ppitch = stream->readFlag() ? stream->readInt(16) : basemove->ppitch;
|
||||
|
|
@ -297,6 +324,6 @@ void Move::unpack(BitStream *stream, const Move * basemove)
|
|||
trigger[i] = triggersDiffer ? stream->readFlag() : basemove->trigger[i];
|
||||
unclamp();
|
||||
}
|
||||
else
|
||||
*this = *basemove;
|
||||
|
||||
return readMove;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,10 +51,16 @@ struct Move
|
|||
bool freeLook;
|
||||
bool trigger[MaxTriggerKeys];
|
||||
|
||||
void pack(BitStream *stream, const Move * move = NULL);
|
||||
void unpack(BitStream *stream, const Move * move = NULL);
|
||||
void clamp();
|
||||
void unclamp();
|
||||
Move();
|
||||
|
||||
virtual void pack(BitStream *stream, const Move * move = NULL);
|
||||
virtual void unpack(BitStream *stream, const Move * move = NULL);
|
||||
virtual void clamp();
|
||||
virtual void unclamp();
|
||||
|
||||
protected:
|
||||
bool packMove(BitStream *stream, const Move* basemove, bool alwaysWriteAll);
|
||||
bool unpackMove(BitStream *stream, const Move* basemove, bool alwaysReadAll);
|
||||
};
|
||||
|
||||
extern const Move NullMove;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ void StdMoveList::clientWriteMovePacket(BitStream *bstream)
|
|||
bstream->writeInt(start,32);
|
||||
bstream->writeInt(count,MoveCountBits);
|
||||
Move * prevMove = NULL;
|
||||
for (int i = 0; i < count; i++)
|
||||
for (S32 i = 0; i < count; i++)
|
||||
{
|
||||
move[offset + i].sendCount++;
|
||||
move[offset + i].pack(bstream,prevMove);
|
||||
|
|
@ -112,7 +112,7 @@ void StdMoveList::serverReadMovePacket(BitStream *bstream)
|
|||
|
||||
// Skip forward (must be starting up), or over the moves
|
||||
// we already have.
|
||||
int skip = mLastMoveAck - start;
|
||||
S32 skip = mLastMoveAck - start;
|
||||
if (skip < 0)
|
||||
{
|
||||
mLastMoveAck = start;
|
||||
|
|
@ -121,7 +121,7 @@ void StdMoveList::serverReadMovePacket(BitStream *bstream)
|
|||
{
|
||||
if (skip > count)
|
||||
skip = count;
|
||||
for (int i = 0; i < skip; i++)
|
||||
for (S32 i = 0; i < skip; i++)
|
||||
{
|
||||
prevMoveHolder.unpack(bstream,prevMove);
|
||||
prevMoveHolder.checksum = bstream->readInt(Move::ChecksumBits);
|
||||
|
|
@ -141,7 +141,7 @@ void StdMoveList::serverReadMovePacket(BitStream *bstream)
|
|||
}
|
||||
|
||||
// Put the rest on the move list.
|
||||
int index = mMoveVec.size();
|
||||
S32 index = mMoveVec.size();
|
||||
mMoveVec.increment(count);
|
||||
while (index < mMoveVec.size())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "math/mEase.h"
|
||||
#include "core/module.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
#include "platform/output/IDisplayDevice.h"
|
||||
|
||||
static void RegisterGameFunctions();
|
||||
static void Process3D();
|
||||
|
|
@ -82,6 +82,8 @@ static S32 gEaseBack = Ease::Back;
|
|||
static S32 gEaseBounce = Ease::Bounce;
|
||||
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
extern void ShowInit();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -143,9 +145,10 @@ ConsoleFunction(containerFindFirst, const char*, 6, 6, "(int mask, Point3F point
|
|||
|
||||
//return the first element
|
||||
sgServerQueryIndex = 0;
|
||||
char *buff = Con::getReturnBuffer(100);
|
||||
static const U32 bufSize = 100;
|
||||
char *buff = Con::getReturnBuffer(bufSize);
|
||||
if (sgServerQueryList.mList.size())
|
||||
dSprintf(buff, 100, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
|
||||
dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
|
||||
else
|
||||
buff[0] = '\0';
|
||||
|
||||
|
|
@ -160,9 +163,10 @@ ConsoleFunction( containerFindNext, const char*, 1, 1, "()"
|
|||
"@ingroup Game")
|
||||
{
|
||||
//return the next element
|
||||
char *buff = Con::getReturnBuffer(100);
|
||||
static const U32 bufSize = 100;
|
||||
char *buff = Con::getReturnBuffer(bufSize);
|
||||
if (sgServerQueryIndex < sgServerQueryList.mList.size())
|
||||
dSprintf(buff, 100, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
|
||||
dSprintf(buff, bufSize, "%d", sgServerQueryList.mList[sgServerQueryIndex++]->getId());
|
||||
else
|
||||
buff[0] = '\0';
|
||||
|
||||
|
|
@ -354,9 +358,44 @@ bool GameProcessCameraQuery(CameraQuery *query)
|
|||
sVisDistanceScale = mClampF( sVisDistanceScale, 0.01f, 1.0f );
|
||||
query->farPlane = gClientSceneGraph->getVisibleDistance() * sVisDistanceScale;
|
||||
|
||||
F32 cameraFov;
|
||||
if(!connection->getControlCameraFov(&cameraFov))
|
||||
// Provide some default values
|
||||
query->projectionOffset = Point2F::Zero;
|
||||
query->eyeOffset = Point3F::Zero;
|
||||
|
||||
F32 cameraFov = 0.0f;
|
||||
bool fovSet = false;
|
||||
|
||||
// Try to use the connection's display deivce, if any, but only if the editor
|
||||
// is not open
|
||||
if(!gEditingMission && connection->hasDisplayDevice())
|
||||
{
|
||||
const IDisplayDevice* display = connection->getDisplayDevice();
|
||||
|
||||
// The connection's display device may want to set the FOV
|
||||
if(display->providesYFOV())
|
||||
{
|
||||
cameraFov = mRadToDeg(display->getYFOV());
|
||||
fovSet = true;
|
||||
}
|
||||
|
||||
// The connection's display device may want to set the projection offset
|
||||
if(display->providesProjectionOffset())
|
||||
{
|
||||
query->projectionOffset = display->getProjectionOffset();
|
||||
}
|
||||
|
||||
// The connection's display device may want to set the eye offset
|
||||
if(display->providesEyeOffset())
|
||||
{
|
||||
query->eyeOffset = display->getEyeOffset();
|
||||
}
|
||||
}
|
||||
|
||||
// Use the connection's FOV settings if requried
|
||||
if(!fovSet && !connection->getControlCameraFov(&cameraFov))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
query->fov = mDegToRad(cameraFov);
|
||||
return true;
|
||||
|
|
@ -404,7 +443,6 @@ static void RegisterGameFunctions()
|
|||
Con::setIntVariable("$TypeMasks::StaticObjectType", StaticObjectType);
|
||||
Con::setIntVariable("$TypeMasks::EnvironmentObjectType", EnvironmentObjectType);
|
||||
Con::setIntVariable("$TypeMasks::TerrainObjectType", TerrainObjectType);
|
||||
Con::setIntVariable("$TypeMasks::InteriorObjectType", InteriorObjectType);
|
||||
Con::setIntVariable("$TypeMasks::WaterObjectType", WaterObjectType);
|
||||
Con::setIntVariable("$TypeMasks::TriggerObjectType", TriggerObjectType);
|
||||
Con::setIntVariable("$TypeMasks::MarkerObjectType", MarkerObjectType);
|
||||
|
|
|
|||
|
|
@ -288,11 +288,45 @@ void GroundPlane::buildConvex( const Box3F& box, Convex* convex )
|
|||
}
|
||||
}
|
||||
|
||||
bool GroundPlane::buildPolyList( PolyListContext context, AbstractPolyList* polyList, const Box3F&, const SphereF& )
|
||||
bool GroundPlane::buildPolyList( PolyListContext context, AbstractPolyList* polyList, const Box3F& box, const SphereF& )
|
||||
{
|
||||
polyList->setObject( this );
|
||||
polyList->setTransform( &MatrixF::Identity, Point3F( 1.0f, 1.0f, 1.0f ) );
|
||||
|
||||
if(context == PLC_Navigation)
|
||||
{
|
||||
F32 z = getPosition().z;
|
||||
Point3F
|
||||
p0(box.minExtents.x, box.maxExtents.y, z),
|
||||
p1(box.maxExtents.x, box.maxExtents.y, z),
|
||||
p2(box.maxExtents.x, box.minExtents.y, z),
|
||||
p3(box.minExtents.x, box.minExtents.y, z);
|
||||
|
||||
// Add vertices to poly list.
|
||||
U32 v0 = polyList->addPoint(p0);
|
||||
polyList->addPoint(p1);
|
||||
polyList->addPoint(p2);
|
||||
polyList->addPoint(p3);
|
||||
|
||||
// Add plane between first three vertices.
|
||||
polyList->begin(0, 0);
|
||||
polyList->vertex(v0);
|
||||
polyList->vertex(v0+1);
|
||||
polyList->vertex(v0+2);
|
||||
polyList->plane(v0, v0+1, v0+2);
|
||||
polyList->end();
|
||||
|
||||
// Add plane between last three vertices.
|
||||
polyList->begin(0, 1);
|
||||
polyList->vertex(v0+2);
|
||||
polyList->vertex(v0+3);
|
||||
polyList->vertex(v0);
|
||||
polyList->plane(v0+2, v0+3, v0);
|
||||
polyList->end();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Box3F planeBox = getPlaneBox();
|
||||
polyList->addBox( planeBox, mMaterial );
|
||||
|
||||
|
|
@ -318,7 +352,7 @@ void GroundPlane::prepRenderImage( SceneRenderState* state )
|
|||
PROFILE_SCOPE( GroundPlane_prepRender );
|
||||
|
||||
// Update the geometry.
|
||||
createGeometry( state->getFrustum() );
|
||||
createGeometry( state->getCullingFrustum() );
|
||||
if( mVertexBuffer.isNull() )
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ GuiObjectView::GuiObjectView()
|
|||
mMountNodeName( "mount0" ),
|
||||
mMountNode( -1 ),
|
||||
mCameraSpeed( 0.01f ),
|
||||
mCameraRotation( 0.0f, 0.0f, 0.0f ),
|
||||
mLightColor( 1.0f, 1.0f, 1.0f ),
|
||||
mLightAmbient( 0.5f, 0.5f, 0.5f ),
|
||||
mLightDirection( 0.f, 0.707f, -0.707f )
|
||||
|
|
@ -182,7 +183,8 @@ void GuiObjectView::initPersistFields()
|
|||
"Minimum distance below which the camera will not zoom in further." );
|
||||
addField( "cameraSpeed", TypeF32, Offset( mCameraSpeed, GuiObjectView ),
|
||||
"Multiplier for mouse camera operations." );
|
||||
|
||||
addField( "cameraRotation", TypePoint3F, Offset( mCameraRotation, GuiObjectView ),
|
||||
"Set the camera rotation." );
|
||||
endGroup( "Camera" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
|
|
@ -205,6 +207,7 @@ void GuiObjectView::onStaticModified( StringTableEntry slotName, const char* new
|
|||
static StringTableEntry sOrbitDistance = StringTable->insert( "orbitDistance" );
|
||||
static StringTableEntry sMinOrbitDistance = StringTable->insert( "minOrbitDistance" );
|
||||
static StringTableEntry sMaxOrbitDistance = StringTable->insert( "maxOrbitDistance" );
|
||||
static StringTableEntry sCameraRotation = StringTable->insert( "cameraRotation" );
|
||||
static StringTableEntry sAnimSequence = StringTable->insert( "animSequence" );
|
||||
|
||||
if( slotName == sShapeFile )
|
||||
|
|
@ -225,6 +228,8 @@ void GuiObjectView::onStaticModified( StringTableEntry slotName, const char* new
|
|||
setLightDirection( mLightDirection );
|
||||
else if( slotName == sOrbitDistance || slotName == sMinOrbitDistance || slotName == sMaxOrbitDistance )
|
||||
setOrbitDistance( mOrbitDist );
|
||||
else if( slotName == sCameraRotation )
|
||||
setCameraRotation( mCameraRotation );
|
||||
else if( slotName == sAnimSequence )
|
||||
setObjectAnimation( String( mAnimationSeqName ) );
|
||||
}
|
||||
|
|
@ -579,6 +584,12 @@ void GuiObjectView::setCameraSpeed( F32 factor )
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void GuiObjectView::setCameraRotation( const EulerF& rotation )
|
||||
{
|
||||
mCameraRot.set(rotation);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GuiObjectView::setLightColor( const ColorF& color )
|
||||
{
|
||||
mLightColor = color;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ class GuiObjectView : public GuiTSCtrl
|
|||
|
||||
F32 mMaxOrbitDist;
|
||||
F32 mMinOrbitDist;
|
||||
EulerF mCameraRotation;
|
||||
|
||||
///
|
||||
F32 mOrbitDist;
|
||||
|
|
@ -245,6 +246,9 @@ class GuiObjectView : public GuiTSCtrl
|
|||
/// @param distance The distance to set the orbit to (will be clamped).
|
||||
void setOrbitDistance( F32 distance );
|
||||
|
||||
/// Sets the angle of the camera on it's orbit in relation to the object.
|
||||
void setCameraRotation( const EulerF& rotation );
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Lighting
|
||||
|
|
|
|||
|
|
@ -53,8 +53,9 @@ static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
|||
F32 Item::mGravity = -20.0f;
|
||||
|
||||
const U32 sClientCollisionMask = (TerrainObjectType |
|
||||
InteriorObjectType | StaticShapeObjectType |
|
||||
VehicleObjectType | PlayerObjectType);
|
||||
StaticShapeObjectType |
|
||||
VehicleObjectType |
|
||||
PlayerObjectType);
|
||||
|
||||
const U32 sServerCollisionMask = (sClientCollisionMask);
|
||||
|
||||
|
|
@ -892,7 +893,7 @@ void Item::updatePos(const U32 /*mask*/, const F32 dt)
|
|||
// Pick the most resistant surface
|
||||
F32 bd = 0;
|
||||
const Collision* collision = 0;
|
||||
for (int c = 0; c < collisionList.getCount(); c++) {
|
||||
for (S32 c = 0; c < collisionList.getCount(); c++) {
|
||||
const Collision &cp = collisionList[c];
|
||||
F32 dot = -mDot(mVelocity,cp.normal);
|
||||
if (dot > bd) {
|
||||
|
|
@ -1203,7 +1204,7 @@ DefineEngineMethod( Item, isRotating, bool, (),,
|
|||
return object->isRotating();
|
||||
}
|
||||
|
||||
DefineEngineMethod( Item, setCollisionTimeout, bool, (int ignoreColObj),(NULL),
|
||||
DefineEngineMethod( Item, setCollisionTimeout, bool, (S32 ignoreColObj),(NULL),
|
||||
"@brief Temporarily disable collisions against a specific ShapeBase object.\n\n"
|
||||
|
||||
"This is useful to prevent a player from immediately picking up an Item they have "
|
||||
|
|
@ -1240,9 +1241,10 @@ DefineEngineMethod( Item, getLastStickyPos, const char*, (),,
|
|||
"@note Server side only.\n"
|
||||
)
|
||||
{
|
||||
char* ret = Con::getReturnBuffer(256);
|
||||
static const U32 bufSize = 256;
|
||||
char* ret = Con::getReturnBuffer(bufSize);
|
||||
if (object->isServerObject())
|
||||
dSprintf(ret, 255, "%g %g %g",
|
||||
dSprintf(ret, bufSize, "%g %g %g",
|
||||
object->mStickyCollisionPos.x,
|
||||
object->mStickyCollisionPos.y,
|
||||
object->mStickyCollisionPos.z);
|
||||
|
|
@ -1262,9 +1264,10 @@ DefineEngineMethod( Item, getLastStickyNormal, const char *, (),,
|
|||
"@note Server side only.\n"
|
||||
)
|
||||
{
|
||||
char* ret = Con::getReturnBuffer(256);
|
||||
static const U32 bufSize = 256;
|
||||
char* ret = Con::getReturnBuffer(bufSize);
|
||||
if (object->isServerObject())
|
||||
dSprintf(ret, 255, "%g %g %g",
|
||||
dSprintf(ret, bufSize, "%g %g %g",
|
||||
object->mStickyCollisionNormal.x,
|
||||
object->mStickyCollisionNormal.y,
|
||||
object->mStickyCollisionNormal.z);
|
||||
|
|
|
|||
|
|
@ -278,7 +278,11 @@ bool LightFlareData::_testVisibility(const SceneRenderState *state, LightFlareSt
|
|||
// the last result.
|
||||
const Point3F &lightPos = flareState->lightMat.getPosition();
|
||||
const RectI &viewport = GFX->getViewport();
|
||||
bool onScreen = MathUtils::mProjectWorldToScreen( lightPos, outLightPosSS, viewport, GFX->getWorldMatrix(), state->getSceneManager()->getNonClipProjection() );
|
||||
MatrixF projMatrix;
|
||||
state->getCameraFrustum().getProjectionMatrix(&projMatrix);
|
||||
if( state->isReflectPass() )
|
||||
projMatrix = state->getSceneManager()->getNonClipProjection();
|
||||
bool onScreen = MathUtils::mProjectWorldToScreen( lightPos, outLightPosSS, viewport, GFX->getWorldMatrix(), projMatrix );
|
||||
|
||||
// It is onscreen, so raycast as a simple occlusion test.
|
||||
const LightInfo *lightInfo = flareState->lightInfo;
|
||||
|
|
@ -452,13 +456,17 @@ void LightFlareData::prepRender( SceneRenderState *state, LightFlareState *flare
|
|||
Point3F oneOverViewportExtent( 1.0f / (F32)viewport.extent.x, 1.0f / (F32)viewport.extent.y, 0.0f );
|
||||
|
||||
// Really convert it to screen space.
|
||||
lightPosSS.x -= viewport.point.x;
|
||||
lightPosSS.y -= viewport.point.y;
|
||||
lightPosSS *= oneOverViewportExtent;
|
||||
lightPosSS = ( lightPosSS * 2.0f ) - Point3F::One;
|
||||
lightPosSS.y = -lightPosSS.y;
|
||||
lightPosSS.z = 0.0f;
|
||||
|
||||
Point3F flareVec( -lightPosSS );
|
||||
// Take any projection offset into account so that the point where the flare's
|
||||
// elements converge is at the 'eye' point rather than the center of the viewport.
|
||||
const Point2F& projOffset = state->getCameraFrustum().getProjectionOffset();
|
||||
Point3F flareVec( -lightPosSS + Point3F(projOffset.x, projOffset.y, 0.0f) );
|
||||
const F32 flareLength = flareVec.len();
|
||||
if ( flareLength > 0.0f )
|
||||
flareVec *= 1.0f / flareLength;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ ConsoleDocClass( MissionArea,
|
|||
|
||||
RectI MissionArea::smMissionArea(Point2I(768, 768), Point2I(512, 512));
|
||||
|
||||
MissionArea * MissionArea::smServerObject = NULL;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
MissionArea::MissionArea()
|
||||
|
|
@ -79,27 +81,24 @@ void MissionArea::setArea(const RectI & area)
|
|||
|
||||
MissionArea * MissionArea::getServerObject()
|
||||
{
|
||||
SimSet * scopeAlwaysSet = Sim::getGhostAlwaysSet();
|
||||
for(SimSet::iterator itr = scopeAlwaysSet->begin(); itr != scopeAlwaysSet->end(); itr++)
|
||||
{
|
||||
MissionArea * ma = dynamic_cast<MissionArea*>(*itr);
|
||||
if(ma)
|
||||
{
|
||||
AssertFatal(ma->isServerObject(), "MissionArea::getServerObject: found client object in ghost always set!");
|
||||
return(ma);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
return smServerObject;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool MissionArea::onAdd()
|
||||
{
|
||||
if(isServerObject() && MissionArea::getServerObject())
|
||||
if(isServerObject())
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "MissionArea::onAdd - MissionArea already instantiated!");
|
||||
return(false);
|
||||
if(MissionArea::getServerObject())
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::General, "MissionArea::onAdd - MissionArea already instantiated!");
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
smServerObject = this;
|
||||
}
|
||||
}
|
||||
|
||||
if(!Parent::onAdd())
|
||||
|
|
@ -109,6 +108,14 @@ bool MissionArea::onAdd()
|
|||
return(true);
|
||||
}
|
||||
|
||||
void MissionArea::onRemove()
|
||||
{
|
||||
if (smServerObject == this)
|
||||
smServerObject = NULL;
|
||||
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void MissionArea::inspectPostApply()
|
||||
|
|
@ -169,10 +176,11 @@ DefineEngineFunction(getMissionAreaServerObject, MissionArea*, (),,
|
|||
DefineEngineMethod( MissionArea, getArea, const char *, (),,
|
||||
"Returns 4 fields: starting x, starting y, extents x, extents y.\n")
|
||||
{
|
||||
char* returnBuffer = Con::getReturnBuffer(48);
|
||||
static const U32 bufSize = 48;
|
||||
char* returnBuffer = Con::getReturnBuffer(bufSize);
|
||||
|
||||
RectI area = object->getArea();
|
||||
dSprintf(returnBuffer, sizeof(returnBuffer), "%d %d %d %d", area.point.x, area.point.y, area.extent.x, area.extent.y);
|
||||
dSprintf(returnBuffer, bufSize, "%d %d %d %d", area.point.x, area.point.y, area.extent.x, area.extent.y);
|
||||
return(returnBuffer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ class MissionArea : public NetObject
|
|||
F32 mFlightCeiling;
|
||||
F32 mFlightCeilingRange;
|
||||
|
||||
static MissionArea * smServerObject;
|
||||
|
||||
public:
|
||||
MissionArea();
|
||||
|
||||
|
|
@ -53,6 +55,7 @@ class MissionArea : public NetObject
|
|||
/// @name SimObject Inheritance
|
||||
/// @{
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
void inspectPostApply();
|
||||
|
||||
|
|
|
|||
|
|
@ -304,8 +304,9 @@ ConsoleType( WayPointTeam, TypeWayPointTeam, WayPointTeam )
|
|||
|
||||
ConsoleGetType( TypeWayPointTeam )
|
||||
{
|
||||
char * buf = Con::getReturnBuffer(32);
|
||||
dSprintf(buf, 32, "%d", ((WayPointTeam*)dptr)->mTeamId);
|
||||
static const U32 bufSize = 32;
|
||||
char * buf = Con::getReturnBuffer(bufSize);
|
||||
dSprintf(buf, bufSize, "%d", ((WayPointTeam*)dptr)->mTeamId);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,25 +53,21 @@ enum SceneObjectTypes
|
|||
/// @see TerrainBlock
|
||||
TerrainObjectType = BIT( 2 ),
|
||||
|
||||
/// A legacy DIF interior object.
|
||||
/// @see InteriorInstance
|
||||
InteriorObjectType = BIT( 3 ),
|
||||
|
||||
/// An object defining a water volume.
|
||||
/// @see WaterObject
|
||||
WaterObjectType = BIT( 4 ),
|
||||
WaterObjectType = BIT( 3 ),
|
||||
|
||||
/// An object defining an invisible trigger volume.
|
||||
/// @see Trigger
|
||||
TriggerObjectType = BIT( 5 ),
|
||||
TriggerObjectType = BIT( 4 ),
|
||||
|
||||
/// An object defining an invisible marker.
|
||||
/// @see MissionMarker
|
||||
MarkerObjectType = BIT( 6 ),
|
||||
MarkerObjectType = BIT( 5 ),
|
||||
|
||||
/// A light emitter.
|
||||
/// @see LightBase
|
||||
LightObjectType = BIT( 7 ),
|
||||
LightObjectType = BIT( 6 ),
|
||||
|
||||
/// An object that manages zones. This is automatically set by
|
||||
/// SceneZoneSpaceManager when a SceneZoneSpace registers zones. Should
|
||||
|
|
@ -79,7 +75,7 @@ enum SceneObjectTypes
|
|||
///
|
||||
/// @see SceneZoneSpace
|
||||
/// @see SceneZoneSpaceManager
|
||||
ZoneObjectType = BIT( 8 ),
|
||||
ZoneObjectType = BIT( 7 ),
|
||||
|
||||
/// Any object that defines one or more solid, renderable static geometries that
|
||||
/// should be included in collision and raycasts.
|
||||
|
|
@ -87,13 +83,13 @@ enum SceneObjectTypes
|
|||
/// Use this mask to find objects that are part of the static level geometry.
|
||||
///
|
||||
/// @note If you set this, you will also want to set StaticObjectType.
|
||||
StaticShapeObjectType = BIT( 9 ),
|
||||
StaticShapeObjectType = BIT( 8 ),
|
||||
|
||||
/// Any object that defines one or more solid, renderable dynamic geometries that
|
||||
/// should be included in collision and raycasts.
|
||||
///
|
||||
/// Use this mask to find objects that are part of the dynamic game geometry.
|
||||
DynamicShapeObjectType = BIT( 10 ),
|
||||
DynamicShapeObjectType = BIT( 9 ),
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
@ -102,54 +98,54 @@ enum SceneObjectTypes
|
|||
|
||||
/// Any GameBase-derived object.
|
||||
/// @see GameBase
|
||||
GameBaseObjectType = BIT( 11 ),
|
||||
GameBaseObjectType = BIT( 10 ),
|
||||
|
||||
/// An object that uses hifi networking.
|
||||
GameBaseHiFiObjectType = BIT( 12 ),
|
||||
GameBaseHiFiObjectType = BIT( 11 ),
|
||||
|
||||
/// Any ShapeBase-derived object.
|
||||
/// @see ShapeBase
|
||||
ShapeBaseObjectType = BIT( 13 ),
|
||||
ShapeBaseObjectType = BIT( 12 ),
|
||||
|
||||
/// A camera object.
|
||||
/// @see Camera
|
||||
CameraObjectType = BIT( 14 ),
|
||||
CameraObjectType = BIT( 13 ),
|
||||
|
||||
/// A human or AI player object.
|
||||
/// @see Player
|
||||
PlayerObjectType = BIT( 15 ),
|
||||
PlayerObjectType = BIT( 14 ),
|
||||
|
||||
/// An item pickup.
|
||||
/// @see Item
|
||||
ItemObjectType = BIT( 16 ),
|
||||
ItemObjectType = BIT( 15 ),
|
||||
|
||||
/// A vehicle.
|
||||
/// @see Vehicle
|
||||
VehicleObjectType = BIT( 17 ),
|
||||
VehicleObjectType = BIT( 16 ),
|
||||
|
||||
/// An object that blocks vehicles.
|
||||
/// @see VehicleBlocker
|
||||
VehicleBlockerObjectType = BIT( 18 ),
|
||||
VehicleBlockerObjectType = BIT( 17 ),
|
||||
|
||||
/// A weapon projectile.
|
||||
/// @see Projectile
|
||||
ProjectileObjectType = BIT( 19 ),
|
||||
ProjectileObjectType = BIT( 18 ),
|
||||
|
||||
/// An explosion object.
|
||||
/// @see Explosion
|
||||
ExplosionObjectType = BIT( 20 ),
|
||||
ExplosionObjectType = BIT( 19 ),
|
||||
|
||||
/// A dead player. This is dynamically set and unset.
|
||||
/// @see Player
|
||||
CorpseObjectType = BIT( 21 ),
|
||||
CorpseObjectType = BIT( 20 ),
|
||||
|
||||
/// A debris object.
|
||||
/// @see Debris
|
||||
DebrisObjectType = BIT( 22 ),
|
||||
DebrisObjectType = BIT( 21 ),
|
||||
|
||||
/// A volume that asserts forces on player objects.
|
||||
/// @see PhysicalZone
|
||||
PhysicalZoneObjectType = BIT( 23 ),
|
||||
PhysicalZoneObjectType = BIT( 22 ),
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
|
@ -173,8 +169,7 @@ enum SceneObjectTypeMasks
|
|||
///
|
||||
/// Also, objects that do their own culling internally (terrains, forests, etc.)
|
||||
/// should be excluded.
|
||||
CULLING_INCLUDE_TYPEMASK = ( InteriorObjectType |
|
||||
GameBaseObjectType | // Includes most other renderable types; but broader than we ideally want.
|
||||
CULLING_INCLUDE_TYPEMASK = ( GameBaseObjectType | // Includes most other renderable types; but broader than we ideally want.
|
||||
StaticShapeObjectType |
|
||||
DynamicShapeObjectType |
|
||||
ZoneObjectType ), // This improves the result of zone traversals.
|
||||
|
|
@ -200,7 +195,6 @@ enum SceneObjectTypeMasks
|
|||
///
|
||||
/// @note Terrains have their own means for rendering inside interior zones.
|
||||
OUTDOOR_OBJECT_TYPEMASK = ( TerrainObjectType |
|
||||
InteriorObjectType |
|
||||
EnvironmentObjectType )
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ U32 PathCamera::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
if (stream->writeFlag(mask & WindowMask)) {
|
||||
stream->write(mNodeBase);
|
||||
stream->write(mNodeCount);
|
||||
for (int i = 0; i < mNodeCount; i++) {
|
||||
for (S32 i = 0; i < mNodeCount; i++) {
|
||||
CameraSpline::Knot *knot = mSpline.getKnot(i);
|
||||
mathWrite(*stream, knot->mPosition);
|
||||
mathWrite(*stream, knot->mRotation);
|
||||
|
|
@ -477,7 +477,7 @@ void PathCamera::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
mSpline.removeAll();
|
||||
stream->read(&mNodeBase);
|
||||
stream->read(&mNodeCount);
|
||||
for (int i = 0; i < mNodeCount; i++)
|
||||
for (S32 i = 0; i < mNodeCount; i++)
|
||||
{
|
||||
CameraSpline::Knot *knot = new CameraSpline::Knot();
|
||||
mathRead(*stream, &knot->mPosition);
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ private:
|
|||
S32 mNodeBase;
|
||||
S32 mNodeCount;
|
||||
F32 mPosition;
|
||||
int mState;
|
||||
S32 mState;
|
||||
F32 mTarget;
|
||||
bool mTargetSet;
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
#define _BULLET_H_
|
||||
|
||||
// NOTE: We set these defines which bullet needs here.
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
#ifdef TORQUE_OS_WIN
|
||||
#define WIN32
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -335,16 +335,22 @@ void BtBody::applyImpulse( const Point3F &origin, const Point3F &force )
|
|||
AssertFatal( mActor, "BtBody::applyImpulse - The actor is null!" );
|
||||
AssertFatal( isDynamic(), "BtBody::applyImpulse - This call is only for dynamics!" );
|
||||
|
||||
// Convert the world position to local
|
||||
MatrixF trans = btCast<MatrixF>( mActor->getCenterOfMassTransform() );
|
||||
trans.inverse();
|
||||
Point3F localOrigin( origin );
|
||||
trans.mulP( localOrigin );
|
||||
|
||||
if ( mCenterOfMass )
|
||||
{
|
||||
Point3F relOrigin( origin );
|
||||
Point3F relOrigin( localOrigin );
|
||||
mCenterOfMass->mulP( relOrigin );
|
||||
Point3F relForce( force );
|
||||
mCenterOfMass->mulV( relForce );
|
||||
mActor->applyImpulse( btCast<btVector3>( relForce ), btCast<btVector3>( relOrigin ) );
|
||||
}
|
||||
else
|
||||
mActor->applyImpulse( btCast<btVector3>( force ), btCast<btVector3>( origin ) );
|
||||
mActor->applyImpulse( btCast<btVector3>( force ), btCast<btVector3>( localOrigin ) );
|
||||
|
||||
if ( !mActor->isActive() )
|
||||
mActor->activate();
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ void BtWorld::explosion( const Point3F &pos, F32 radius, F32 forceMagnitude )
|
|||
|
||||
void BtWorld::onDebugDraw( const SceneRenderState *state )
|
||||
{
|
||||
mDebugDraw.setCuller( &state->getFrustum() );
|
||||
mDebugDraw.setCuller( &state->getCullingFrustum() );
|
||||
|
||||
mDynamicsWorld->setDebugDrawer( &mDebugDraw );
|
||||
mDynamicsWorld->debugDrawWorld();
|
||||
|
|
|
|||
|
|
@ -311,7 +311,8 @@ PhysicsDebris* PhysicsDebris::create( PhysicsDebrisData *datablock,
|
|||
}
|
||||
|
||||
PhysicsDebris::PhysicsDebris()
|
||||
: mLifetime( 0.0f ),
|
||||
: mDataBlock( NULL ),
|
||||
mLifetime( 0.0f ),
|
||||
mShapeInstance( NULL ),
|
||||
mWorld( NULL ),
|
||||
mInitialLinVel( Point3F::Zero )
|
||||
|
|
@ -342,6 +343,12 @@ bool PhysicsDebris::onAdd()
|
|||
if ( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
if( !mDataBlock )
|
||||
{
|
||||
Con::errorf("PhysicsDebris::onAdd - Fail - No datablock");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it has a fixed lifetime then calculate it.
|
||||
if ( mDataBlock->lifetime > 0.0f )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "lighting/lightQuery.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
using namespace Torque;
|
||||
|
||||
bool PhysicsShape::smNoCorrections = false;
|
||||
bool PhysicsShape::smNoSmoothing = false;
|
||||
|
|
@ -240,7 +241,7 @@ void PhysicsShapeData::onRemove()
|
|||
|
||||
void PhysicsShapeData::_onResourceChanged( const Torque::Path &path )
|
||||
{
|
||||
if ( path != Path( shapeName ) )
|
||||
if ( path != Path( shapeName ) )
|
||||
return;
|
||||
|
||||
// Reload the changed shape.
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
#define __APPLE__
|
||||
#elif defined(TORQUE_OS_LINUX) && !defined(LINUX)
|
||||
#define LINUX
|
||||
#elif defined(TORQUE_OS_WIN32) && !defined(WIN32)
|
||||
#elif defined(TORQUE_OS_WIN) && !defined(WIN32)
|
||||
#define WIN32
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ bool PxMultiActorData::preload( bool server, String &errorBuffer )
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!shapeName || shapeName == '\0')
|
||||
if (!shapeName || shapeName[0] == '\0')
|
||||
{
|
||||
errorBuffer = "PxMultiActorDatas::preload: no shape name!";
|
||||
return false;
|
||||
|
|
@ -570,7 +570,7 @@ bool PxMultiActorData::preload( bool server, String &errorBuffer )
|
|||
|
||||
// Register for file change notification to reload the collection
|
||||
if ( server )
|
||||
FS::AddChangeNotification( physXStream, this, &PxMultiActorData::_onFileChanged );
|
||||
Torque::FS::AddChangeNotification( physXStream, this, &PxMultiActorData::_onFileChanged );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2648,4 +2648,4 @@ ConsoleMethod( PxMultiActorData, reload, void, 2, 2, ""
|
|||
"If the reload sucessfully completes, all PxMultiActor's will be notified.\n\n")
|
||||
{
|
||||
object->reload();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ AFTER_MODULE_INIT( Sim )
|
|||
{
|
||||
NamedFactory<PhysicsPlugin>::add( "PhysX", &PxPlugin::create );
|
||||
|
||||
#if defined(TORQUE_OS_WIN32) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)
|
||||
#if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)
|
||||
NamedFactory<PhysicsPlugin>::add( "default", &PxPlugin::create );
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -448,9 +448,8 @@ void PxWorld::releaseActor( NxActor &actor )
|
|||
// Clear the userdata.
|
||||
actor.userData = NULL;
|
||||
|
||||
// If the scene is not simulating then we have the
|
||||
// write lock and can safely delete it now.
|
||||
if ( !mIsSimulating )
|
||||
// actors are one of the few objects that are stable removing this way in physx 2.8
|
||||
if (mScene->isWritable() )
|
||||
{
|
||||
mScene->releaseActor( actor );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@
|
|||
#include "T3D/decal/decalData.h"
|
||||
#include "materials/baseMatInstance.h"
|
||||
|
||||
#ifdef TORQUE_EXTENDED_MOVE
|
||||
#include "T3D/gameBase/extended/extendedMove.h"
|
||||
#endif
|
||||
|
||||
// Amount of time if takes to transition to a new action sequence.
|
||||
static F32 sAnimationTransitionTime = 0.25f;
|
||||
static bool sUseAnimationTransitions = true;
|
||||
|
|
@ -96,12 +100,13 @@ static F32 sMinWarpTicks = 0.5f; // Fraction of tick at which instant warp
|
|||
static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
||||
static S32 sMaxPredictionTicks = 30; // Number of ticks to predict
|
||||
|
||||
S32 Player::smExtendedMoveHeadPosRotIndex = 0; // The ExtendedMove position/rotation index used for head movements
|
||||
|
||||
// Anchor point compression
|
||||
const F32 sAnchorMaxDistance = 32.0f;
|
||||
|
||||
//
|
||||
static U32 sCollisionMoveMask = TerrainObjectType |
|
||||
InteriorObjectType |
|
||||
WaterObjectType |
|
||||
PlayerObjectType |
|
||||
StaticShapeObjectType |
|
||||
|
|
@ -123,14 +128,6 @@ enum PlayerConstants {
|
|||
//----------------------------------------------------------------------------
|
||||
// Player shape animation sequences:
|
||||
|
||||
// look Used to control the upper body arm motion. Must animate
|
||||
// vertically +-80 deg.
|
||||
Player::Range Player::mArmRange(mDegToRad(-80.0f),mDegToRad(+80.0f));
|
||||
|
||||
// head Used to control the direction the head is looking. Must
|
||||
// animated vertically +-80 deg .
|
||||
Player::Range Player::mHeadVRange(mDegToRad(-80.0f),mDegToRad(+80.0f));
|
||||
|
||||
// Action Animations:
|
||||
PlayerData::ActionAnimationDef PlayerData::ActionAnimationList[NumTableActionAnims] =
|
||||
{
|
||||
|
|
@ -430,9 +427,9 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
{
|
||||
for( U32 i = 0; i < MaxSounds; ++ i )
|
||||
{
|
||||
String errorStr;
|
||||
if( !sfxResolve( &sound[ i ], errorStr ) )
|
||||
Con::errorf( "PlayerData::preload: %s", errorStr.c_str() );
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &sound[ i ], sfxErrorStr ) )
|
||||
Con::errorf( "PlayerData::preload: %s", sfxErrorStr.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -470,7 +467,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
// Extract ground transform velocity from animations
|
||||
// Get the named ones first so they can be indexed directly.
|
||||
ActionAnimation *dp = &actionList[0];
|
||||
for (int i = 0; i < NumTableActionAnims; i++,dp++)
|
||||
for (S32 i = 0; i < NumTableActionAnims; i++,dp++)
|
||||
{
|
||||
ActionAnimationDef *sp = &ActionAnimationList[i];
|
||||
dp->name = sp->name;
|
||||
|
|
@ -490,12 +487,8 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
dp->death = false;
|
||||
if (dp->sequence != -1)
|
||||
getGroundInfo(si,thread,dp);
|
||||
|
||||
// No real reason to spam the console about a missing jet animation
|
||||
if (dStricmp(sp->name, "jet") != 0)
|
||||
AssertWarn(dp->sequence != -1, avar("PlayerData::preload - Unable to find named animation sequence '%s'!", sp->name));
|
||||
}
|
||||
for (int b = 0; b < mShape->sequences.size(); b++)
|
||||
for (S32 b = 0; b < mShape->sequences.size(); b++)
|
||||
{
|
||||
if (!isTableSequence(b))
|
||||
{
|
||||
|
|
@ -512,7 +505,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
// Resolve lookAction index
|
||||
dp = &actionList[0];
|
||||
String lookName("look");
|
||||
for (int c = 0; c < actionCount; c++,dp++)
|
||||
for (S32 c = 0; c < actionCount; c++,dp++)
|
||||
if( dStricmp( dp->name, lookName ) == 0 )
|
||||
lookAction = c;
|
||||
|
||||
|
|
@ -560,7 +553,7 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
if (!Sim::findObject(dustID, dustEmitter))
|
||||
Con::errorf(ConsoleLogEntry::General, "PlayerData::preload - Invalid packet, bad datablockId(dustEmitter): 0x%x", dustID);
|
||||
|
||||
for (int i=0; i<NUM_SPLASH_EMITTERS; i++)
|
||||
for (S32 i=0; i<NUM_SPLASH_EMITTERS; i++)
|
||||
if( !splashEmitterList[i] && splashEmitterIDList[i] != 0 )
|
||||
if( Sim::findObject( splashEmitterIDList[i], splashEmitterList[i] ) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "PlayerData::onAdd - Invalid packet, bad datablockId(particle emitter): 0x%x", splashEmitterIDList[i]);
|
||||
|
|
@ -589,7 +582,10 @@ bool PlayerData::preload(bool server, String &errorStr)
|
|||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShapeFP[i].getPath());
|
||||
|
||||
if (!fileRef)
|
||||
{
|
||||
errorStr = String::ToString("PlayerData: Mounted image %d loading failed, shape \"%s\" is not found.",i,mShapeFP[i].getPath().getFullPath().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(server)
|
||||
mCRCFP[i] = fileRef->getChecksum();
|
||||
|
|
@ -650,7 +646,7 @@ bool PlayerData::isTableSequence(S32 seq)
|
|||
{
|
||||
// The sequences from the table must already have
|
||||
// been loaded for this to work.
|
||||
for (int i = 0; i < NumTableActionAnims; i++)
|
||||
for (S32 i = 0; i < NumTableActionAnims; i++)
|
||||
if (actionList[i].sequence == seq)
|
||||
return true;
|
||||
return false;
|
||||
|
|
@ -1650,6 +1646,9 @@ Player::Player()
|
|||
mShapeFPFlashThread[i] = 0;
|
||||
mShapeFPSpinThread[i] = 0;
|
||||
}
|
||||
|
||||
mLastAbsoluteYaw = 0.0f;
|
||||
mLastAbsolutePitch = 0.0f;
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
|
|
@ -1755,6 +1754,12 @@ void Player::onRemove()
|
|||
setControlObject(0);
|
||||
scriptOnRemove();
|
||||
removeFromScene();
|
||||
|
||||
if ( isGhost() )
|
||||
{
|
||||
SFX_DELETE( mMoveBubbleSound );
|
||||
SFX_DELETE( mWaterBreathSound );
|
||||
}
|
||||
|
||||
U32 i;
|
||||
for( i=0; i<PlayerData::NUM_SPLASH_EMITTERS; i++ )
|
||||
|
|
@ -1938,7 +1943,7 @@ void Player::reSkin()
|
|||
Vector<String> skins;
|
||||
String(mSkinNameHandle.getString()).split( ";", skins );
|
||||
|
||||
for ( int i = 0; i < skins.size(); i++ )
|
||||
for ( S32 i = 0; i < skins.size(); i++ )
|
||||
{
|
||||
String oldSkin( mAppliedSkinName.c_str() );
|
||||
String newSkin( skins[i] );
|
||||
|
|
@ -1955,7 +1960,7 @@ void Player::reSkin()
|
|||
|
||||
// Apply skin to both 3rd person and 1st person shape instances
|
||||
mShapeInstance->reSkin( newSkin, oldSkin );
|
||||
for ( int j = 0; j < ShapeBase::MaxMountedImages; j++ )
|
||||
for ( S32 j = 0; j < ShapeBase::MaxMountedImages; j++ )
|
||||
{
|
||||
if (mShapeFPInstance[j])
|
||||
mShapeFPInstance[j]->reSkin( newSkin, oldSkin );
|
||||
|
|
@ -2523,38 +2528,130 @@ void Player::updateMove(const Move* move)
|
|||
F32 prevZRot = mRot.z;
|
||||
delta.headVec = mHead;
|
||||
|
||||
F32 p = move->pitch * (mPose == SprintPose ? mDataBlock->sprintPitchScale : 1.0f);
|
||||
if (p > M_PI_F)
|
||||
p -= M_2PI_F;
|
||||
mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle,
|
||||
mDataBlock->maxLookAngle);
|
||||
|
||||
F32 y = move->yaw * (mPose == SprintPose ? mDataBlock->sprintYawScale : 1.0f);
|
||||
if (y > M_PI_F)
|
||||
y -= M_2PI_F;
|
||||
|
||||
bool doStandardMove = true;
|
||||
GameConnection* con = getControllingClient();
|
||||
if (move->freeLook && ((isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson())))
|
||||
{
|
||||
mHead.z = mClampF(mHead.z + y,
|
||||
-mDataBlock->maxFreelookAngle,
|
||||
mDataBlock->maxFreelookAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
mRot.z += y;
|
||||
// Rotate the head back to the front, center horizontal
|
||||
// as well if we're controlling another object.
|
||||
mHead.z *= 0.5f;
|
||||
if (mControlObject)
|
||||
mHead.x *= 0.5f;
|
||||
}
|
||||
|
||||
// constrain the range of mRot.z
|
||||
while (mRot.z < 0.0f)
|
||||
mRot.z += M_2PI_F;
|
||||
while (mRot.z > M_2PI_F)
|
||||
mRot.z -= M_2PI_F;
|
||||
#ifdef TORQUE_EXTENDED_MOVE
|
||||
// Work with an absolute rotation from the ExtendedMove class?
|
||||
if(con && con->getControlSchemeAbsoluteRotation())
|
||||
{
|
||||
doStandardMove = false;
|
||||
const ExtendedMove* emove = dynamic_cast<const ExtendedMove*>(move);
|
||||
U32 emoveIndex = smExtendedMoveHeadPosRotIndex;
|
||||
if(emoveIndex >= ExtendedMove::MaxPositionsRotations)
|
||||
emoveIndex = 0;
|
||||
|
||||
if(emove->EulerBasedRotation[emoveIndex])
|
||||
{
|
||||
// Head pitch
|
||||
mHead.x += (emove->rotX[emoveIndex] - mLastAbsolutePitch);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if(con->getControlSchemeAddPitchToAbsRot())
|
||||
{
|
||||
F32 x = move->pitch;
|
||||
if (x > M_PI_F)
|
||||
x -= M_2PI_F;
|
||||
|
||||
mHead.x += x;
|
||||
}
|
||||
|
||||
// Constrain the range of mHead.x
|
||||
while (mHead.x < -M_PI_F)
|
||||
mHead.x += M_2PI_F;
|
||||
while (mHead.x > M_PI_F)
|
||||
mHead.x -= M_2PI_F;
|
||||
|
||||
// Rotate (heading) head or body?
|
||||
if (move->freeLook && ((isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson())))
|
||||
{
|
||||
// Rotate head
|
||||
mHead.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if(con->getControlSchemeAddYawToAbsRot())
|
||||
{
|
||||
F32 z = move->yaw;
|
||||
if (z > M_PI_F)
|
||||
z -= M_2PI_F;
|
||||
|
||||
mHead.z += z;
|
||||
}
|
||||
|
||||
// Constrain the range of mHead.z
|
||||
while (mHead.z < 0.0f)
|
||||
mHead.z += M_2PI_F;
|
||||
while (mHead.z > M_2PI_F)
|
||||
mHead.z -= M_2PI_F;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rotate body
|
||||
mRot.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
|
||||
|
||||
// Do we also include the relative yaw value?
|
||||
if(con->getControlSchemeAddYawToAbsRot())
|
||||
{
|
||||
F32 z = move->yaw;
|
||||
if (z > M_PI_F)
|
||||
z -= M_2PI_F;
|
||||
|
||||
mRot.z += z;
|
||||
}
|
||||
|
||||
// Constrain the range of mRot.z
|
||||
while (mRot.z < 0.0f)
|
||||
mRot.z += M_2PI_F;
|
||||
while (mRot.z > M_2PI_F)
|
||||
mRot.z -= M_2PI_F;
|
||||
}
|
||||
mLastAbsoluteYaw = emove->rotZ[emoveIndex];
|
||||
mLastAbsolutePitch = emove->rotX[emoveIndex];
|
||||
|
||||
// Head bank
|
||||
mHead.y = emove->rotY[emoveIndex];
|
||||
|
||||
// Constrain the range of mHead.y
|
||||
while (mHead.y > M_PI_F)
|
||||
mHead.y -= M_2PI_F;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(doStandardMove)
|
||||
{
|
||||
F32 p = move->pitch * (mPose == SprintPose ? mDataBlock->sprintPitchScale : 1.0f);
|
||||
if (p > M_PI_F)
|
||||
p -= M_2PI_F;
|
||||
mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle,
|
||||
mDataBlock->maxLookAngle);
|
||||
|
||||
F32 y = move->yaw * (mPose == SprintPose ? mDataBlock->sprintYawScale : 1.0f);
|
||||
if (y > M_PI_F)
|
||||
y -= M_2PI_F;
|
||||
|
||||
if (move->freeLook && ((isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson())))
|
||||
{
|
||||
mHead.z = mClampF(mHead.z + y,
|
||||
-mDataBlock->maxFreelookAngle,
|
||||
mDataBlock->maxFreelookAngle);
|
||||
}
|
||||
else
|
||||
{
|
||||
mRot.z += y;
|
||||
// Rotate the head back to the front, center horizontal
|
||||
// as well if we're controlling another object.
|
||||
mHead.z *= 0.5f;
|
||||
if (mControlObject)
|
||||
mHead.x *= 0.5f;
|
||||
}
|
||||
|
||||
// constrain the range of mRot.z
|
||||
while (mRot.z < 0.0f)
|
||||
mRot.z += M_2PI_F;
|
||||
while (mRot.z > M_2PI_F)
|
||||
mRot.z -= M_2PI_F;
|
||||
}
|
||||
|
||||
delta.rot = mRot;
|
||||
delta.rotVec.x = delta.rotVec.y = 0.0f;
|
||||
|
|
@ -2566,6 +2663,13 @@ void Player::updateMove(const Move* move)
|
|||
|
||||
delta.head = mHead;
|
||||
delta.headVec -= mHead;
|
||||
for(U32 i=0; i<3; ++i)
|
||||
{
|
||||
if (delta.headVec[i] > M_PI_F)
|
||||
delta.headVec[i] -= M_2PI_F;
|
||||
else if (delta.headVec[i] < -M_PI_F)
|
||||
delta.headVec[i] += M_2PI_F;
|
||||
}
|
||||
}
|
||||
MatrixF zRot;
|
||||
zRot.set(EulerF(0.0f, 0.0f, mRot.z));
|
||||
|
|
@ -2757,7 +2861,7 @@ void Player::updateMove(const Move* move)
|
|||
if (pvl)
|
||||
pv *= moveSpeed / pvl;
|
||||
|
||||
VectorF runAcc = pv - acc;
|
||||
VectorF runAcc = pv - (mVelocity + acc);
|
||||
runAcc.z = 0;
|
||||
runAcc.x = runAcc.x * mDataBlock->airControl;
|
||||
runAcc.y = runAcc.y * mDataBlock->airControl;
|
||||
|
|
@ -2847,7 +2951,7 @@ void Player::updateMove(const Move* move)
|
|||
|
||||
// Clamp acceleration.
|
||||
F32 maxAcc = (mDataBlock->swimForce / getMass()) * TickSec;
|
||||
if ( false && swimSpeed > maxAcc )
|
||||
if ( swimSpeed > maxAcc )
|
||||
swimAcc *= maxAcc / swimSpeed;
|
||||
|
||||
acc += swimAcc;
|
||||
|
|
@ -2993,6 +3097,8 @@ void Player::updateMove(const Move* move)
|
|||
}
|
||||
|
||||
// Container buoyancy & drag
|
||||
/* Commented out until the buoyancy calculation can be reworked so that a container and
|
||||
** player with the same density will result in neutral buoyancy.
|
||||
if (mBuoyancy != 0)
|
||||
{
|
||||
// Applying buoyancy when standing still causing some jitters-
|
||||
|
|
@ -3009,9 +3115,10 @@ void Player::updateMove(const Move* move)
|
|||
if ( currHeight + mVelocity.z * TickSec * C > mLiquidHeight )
|
||||
buoyancyForce *= M;
|
||||
|
||||
//mVelocity.z -= buoyancyForce;
|
||||
mVelocity.z -= buoyancyForce;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Apply drag
|
||||
if ( mSwimming )
|
||||
|
|
@ -3318,31 +3425,38 @@ void Player::updateDamageState()
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void Player::updateLookAnimation(F32 dT)
|
||||
void Player::updateLookAnimation(F32 dt)
|
||||
{
|
||||
// Calculate our interpolated head position.
|
||||
Point3F renderHead = delta.head + delta.headVec * dT;
|
||||
Point3F renderHead = delta.head + delta.headVec * dt;
|
||||
|
||||
// Adjust look pos. This assumes that the animations match
|
||||
// the min and max look angles provided in the datablock.
|
||||
if (mArmAnimation.thread)
|
||||
{
|
||||
// TG: Adjust arm position to avoid collision.
|
||||
F32 tp = mControlObject? 0.5:
|
||||
(renderHead.x - mArmRange.min) / mArmRange.delta;
|
||||
mShapeInstance->setPos(mArmAnimation.thread,mClampF(tp,0,1));
|
||||
if(mControlObject)
|
||||
{
|
||||
mShapeInstance->setPos(mArmAnimation.thread,0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 d = mDataBlock->maxLookAngle - mDataBlock->minLookAngle;
|
||||
F32 tp = (renderHead.x - mDataBlock->minLookAngle) / d;
|
||||
mShapeInstance->setPos(mArmAnimation.thread,mClampF(tp,0,1));
|
||||
}
|
||||
}
|
||||
|
||||
if (mHeadVThread)
|
||||
{
|
||||
F32 tp = (renderHead.x - mHeadVRange.min) / mHeadVRange.delta;
|
||||
F32 d = mDataBlock->maxLookAngle - mDataBlock->minLookAngle;
|
||||
F32 tp = (renderHead.x - mDataBlock->minLookAngle) / d;
|
||||
mShapeInstance->setPos(mHeadVThread,mClampF(tp,0,1));
|
||||
}
|
||||
|
||||
if (mHeadHThread)
|
||||
{
|
||||
F32 dt = 2 * mDataBlock->maxFreelookAngle;
|
||||
F32 tp = (renderHead.z + mDataBlock->maxFreelookAngle) / dt;
|
||||
F32 d = 2 * mDataBlock->maxFreelookAngle;
|
||||
F32 tp = (renderHead.z + mDataBlock->maxFreelookAngle) / d;
|
||||
mShapeInstance->setPos(mHeadHThread,mClampF(tp,0,1));
|
||||
}
|
||||
}
|
||||
|
|
@ -3386,8 +3500,7 @@ void Player::updateDeathOffsets()
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static const U32 sPlayerConformMask = InteriorObjectType|StaticShapeObjectType|
|
||||
StaticObjectType|TerrainObjectType;
|
||||
static const U32 sPlayerConformMask = StaticShapeObjectType | StaticObjectType | TerrainObjectType;
|
||||
|
||||
static void accel(F32& from, F32 to, F32 rate)
|
||||
{
|
||||
|
|
@ -5259,7 +5372,7 @@ void Player::setTransform(const MatrixF& mat)
|
|||
|
||||
void Player::getEyeTransform(MatrixF* mat)
|
||||
{
|
||||
getEyeBaseTransform(mat);
|
||||
getEyeBaseTransform(mat, true);
|
||||
|
||||
// The shape instance is animated in getEyeBaseTransform() so we're
|
||||
// good here when attempting to get the eye node position on the server.
|
||||
|
|
@ -5297,7 +5410,7 @@ void Player::getEyeTransform(MatrixF* mat)
|
|||
}
|
||||
}
|
||||
|
||||
void Player::getEyeBaseTransform(MatrixF* mat)
|
||||
void Player::getEyeBaseTransform(MatrixF* mat, bool includeBank)
|
||||
{
|
||||
// Eye transform in world space. We only use the eye position
|
||||
// from the animation and supply our own rotation.
|
||||
|
|
@ -5313,7 +5426,19 @@ void Player::getEyeBaseTransform(MatrixF* mat)
|
|||
else
|
||||
zmat.identity();
|
||||
|
||||
pmat.mul(zmat,xmat);
|
||||
if(includeBank && mDataBlock->cameraCanBank)
|
||||
{
|
||||
// Take mHead.y into account to bank the camera
|
||||
MatrixF imat;
|
||||
imat.mul(zmat, xmat);
|
||||
MatrixF ymat;
|
||||
ymat.set(EulerF(0.0f, mHead.y, 0.0f));
|
||||
pmat.mul(imat, ymat);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmat.mul(zmat,xmat);
|
||||
}
|
||||
|
||||
F32 *dp = pmat;
|
||||
|
||||
|
|
@ -5340,7 +5465,7 @@ void Player::getEyeBaseTransform(MatrixF* mat)
|
|||
|
||||
void Player::getRenderEyeTransform(MatrixF* mat)
|
||||
{
|
||||
getRenderEyeBaseTransform(mat);
|
||||
getRenderEyeBaseTransform(mat, true);
|
||||
|
||||
// Use the first image that is set to use the eye node
|
||||
for (U32 i=0; i<ShapeBase::MaxMountedImages; ++i)
|
||||
|
|
@ -5369,7 +5494,7 @@ void Player::getRenderEyeTransform(MatrixF* mat)
|
|||
}
|
||||
}
|
||||
|
||||
void Player::getRenderEyeBaseTransform(MatrixF* mat)
|
||||
void Player::getRenderEyeBaseTransform(MatrixF* mat, bool includeBank)
|
||||
{
|
||||
// Eye transform in world space. We only use the eye position
|
||||
// from the animation and supply our own rotation.
|
||||
|
|
@ -5381,7 +5506,19 @@ void Player::getRenderEyeBaseTransform(MatrixF* mat)
|
|||
else
|
||||
zmat.identity();
|
||||
|
||||
pmat.mul(zmat,xmat);
|
||||
if(includeBank && mDataBlock->cameraCanBank)
|
||||
{
|
||||
// Take mHead.y delta into account to bank the camera
|
||||
MatrixF imat;
|
||||
imat.mul(zmat, xmat);
|
||||
MatrixF ymat;
|
||||
ymat.set(EulerF(0.0f, delta.head.y + delta.headVec.y * delta.dt, 0.0f));
|
||||
pmat.mul(imat, ymat);
|
||||
}
|
||||
else
|
||||
{
|
||||
pmat.mul(zmat,xmat);
|
||||
}
|
||||
|
||||
F32 *dp = pmat;
|
||||
|
||||
|
|
@ -5539,7 +5676,7 @@ void Player::renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRend
|
|||
if (data.useEyeNode && data.eyeMountNode[imageShapeIndex] != -1)
|
||||
{
|
||||
MatrixF nmat;
|
||||
getRenderEyeBaseTransform(&nmat);
|
||||
getRenderEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank);
|
||||
MatrixF offsetMat = image.shapeInstance[imageShapeIndex]->mNodeTransforms[data.eyeMountNode[imageShapeIndex]];
|
||||
offsetMat.affineInverse();
|
||||
world.mul(nmat,offsetMat);
|
||||
|
|
@ -5547,7 +5684,7 @@ void Player::renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRend
|
|||
else
|
||||
{
|
||||
MatrixF nmat;
|
||||
getRenderEyeBaseTransform(&nmat);
|
||||
getRenderEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank);
|
||||
world.mul(nmat,data.eyeOffset);
|
||||
}
|
||||
|
||||
|
|
@ -5684,7 +5821,7 @@ bool Player::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
|
|||
F32 const *si = &start.x;
|
||||
F32 const *ei = &end.x;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (S32 i = 0; i < 3; i++) {
|
||||
if (*si < *ei) {
|
||||
if (*si > *bmax || *ei < *bmin)
|
||||
return false;
|
||||
|
|
@ -5866,6 +6003,11 @@ void Player::writePacketData(GameConnection *connection, BitStream *stream)
|
|||
}
|
||||
}
|
||||
stream->write(mHead.x);
|
||||
if(stream->writeFlag(mDataBlock->cameraCanBank))
|
||||
{
|
||||
// Include mHead.y to allow for camera banking
|
||||
stream->write(mHead.y);
|
||||
}
|
||||
stream->write(mHead.z);
|
||||
stream->write(mRot.z);
|
||||
|
||||
|
|
@ -5928,6 +6070,11 @@ void Player::readPacketData(GameConnection *connection, BitStream *stream)
|
|||
else
|
||||
pos = delta.pos;
|
||||
stream->read(&mHead.x);
|
||||
if(stream->readFlag())
|
||||
{
|
||||
// Include mHead.y to allow for camera banking
|
||||
stream->read(&mHead.y);
|
||||
}
|
||||
stream->read(&mHead.z);
|
||||
stream->read(&rot.z);
|
||||
rot.x = rot.y = 0;
|
||||
|
|
@ -6359,8 +6506,9 @@ DefineEngineMethod( Player, getDamageLocation, const char*, ( Point3F pos ),,
|
|||
|
||||
object->getDamageLocation(pos, buffer1, buffer2);
|
||||
|
||||
char *buff = Con::getReturnBuffer(128);
|
||||
dSprintf(buff, 128, "%s %s", buffer1, buffer2);
|
||||
static const U32 bufSize = 128;
|
||||
char *buff = Con::getReturnBuffer(bufSize);
|
||||
dSprintf(buff, bufSize, "%s %s", buffer1, buffer2);
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
|
@ -6587,6 +6735,11 @@ void Player::consoleInit()
|
|||
Con::addVariable("$player::vehicleDismountTrigger", TypeS32, &sVehicleDismountTrigger,
|
||||
"@brief The move trigger index used to dismount player.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
|
||||
// ExtendedMove support
|
||||
Con::addVariable("$player::extendedMoveHeadPosRotIndex", TypeS32, &smExtendedMoveHeadPosRotIndex,
|
||||
"@brief The ExtendedMove position/rotation index used for head movements.\n\n"
|
||||
"@ingroup GameObjects\n");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -385,6 +385,9 @@ public:
|
|||
NumPoseBits = 3
|
||||
};
|
||||
|
||||
/// The ExtendedMove position/rotation index used for head movements
|
||||
static S32 smExtendedMoveHeadPosRotIndex;
|
||||
|
||||
protected:
|
||||
|
||||
/// Bit masks for different types of events
|
||||
|
|
@ -395,16 +398,6 @@ protected:
|
|||
NextFreeMask = Parent::NextFreeMask << 3
|
||||
};
|
||||
|
||||
struct Range {
|
||||
Range(F32 _min,F32 _max) {
|
||||
min = _min;
|
||||
max = _max;
|
||||
delta = _max - _min;
|
||||
};
|
||||
F32 min,max;
|
||||
F32 delta;
|
||||
};
|
||||
|
||||
SimObjectPtr<ParticleEmitter> mSplashEmitter[PlayerData::NUM_SPLASH_EMITTERS];
|
||||
F32 mBubbleEmitterTime;
|
||||
|
||||
|
|
@ -444,6 +437,9 @@ protected:
|
|||
|
||||
bool mUseHeadZCalc; ///< Including mHead.z in transform calculations
|
||||
|
||||
F32 mLastAbsoluteYaw; ///< Stores that last absolute yaw value as passed in by ExtendedMove
|
||||
F32 mLastAbsolutePitch; ///< Stores that last absolute pitch value as passed in by ExtendedMove
|
||||
|
||||
S32 mMountPending; ///< mMountPending suppresses tickDelay countdown so players will sit until
|
||||
///< their mount, or another animation, comes through (or 13 seconds elapses).
|
||||
|
||||
|
|
@ -502,9 +498,6 @@ protected:
|
|||
TSThread* mHeadHThread;
|
||||
TSThread* mRecoilThread;
|
||||
TSThread* mImageStateThread;
|
||||
static Range mArmRange;
|
||||
static Range mHeadVRange;
|
||||
static Range mHeadHRange;
|
||||
/// @}
|
||||
|
||||
bool mInMissionArea; ///< Are we in the mission area?
|
||||
|
|
@ -687,9 +680,9 @@ public:
|
|||
|
||||
void setTransform(const MatrixF &mat);
|
||||
void getEyeTransform(MatrixF* mat);
|
||||
void getEyeBaseTransform(MatrixF* mat);
|
||||
void getEyeBaseTransform(MatrixF* mat, bool includeBank);
|
||||
void getRenderEyeTransform(MatrixF* mat);
|
||||
void getRenderEyeBaseTransform(MatrixF* mat);
|
||||
void getRenderEyeBaseTransform(MatrixF* mat, bool includeBank);
|
||||
void getCameraParameters(F32 *min, F32 *max, Point3F *offset, MatrixF *rot);
|
||||
void getMuzzleTransform(U32 imageSlot,MatrixF* mat);
|
||||
void getRenderMuzzleTransform(U32 imageSlot,MatrixF* mat);
|
||||
|
|
|
|||
|
|
@ -126,12 +126,9 @@ IMPLEMENT_CALLBACK( ProjectileData, onCollision, void, ( Projectile* proj, Scene
|
|||
"@see Projectile\n"
|
||||
);
|
||||
|
||||
const U32 Projectile::csmStaticCollisionMask = TerrainObjectType |
|
||||
InteriorObjectType |
|
||||
StaticShapeObjectType;
|
||||
const U32 Projectile::csmStaticCollisionMask = TerrainObjectType | StaticShapeObjectType;
|
||||
|
||||
const U32 Projectile::csmDynamicCollisionMask = PlayerObjectType |
|
||||
VehicleObjectType;
|
||||
const U32 Projectile::csmDynamicCollisionMask = PlayerObjectType | VehicleObjectType;
|
||||
|
||||
const U32 Projectile::csmDamageableMask = Projectile::csmDynamicCollisionMask;
|
||||
|
||||
|
|
@ -323,9 +320,9 @@ bool ProjectileData::preload(bool server, String &errorStr)
|
|||
if (Sim::findObject(decalId, decal) == false)
|
||||
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(decal): %d", decalId);
|
||||
|
||||
String errorStr;
|
||||
if( !sfxResolve( &sound, errorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet: %s", errorStr.c_str());
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &sound, sfxErrorStr ) )
|
||||
Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet: %s", sfxErrorStr.c_str());
|
||||
|
||||
if (!lightDesc && lightDescId != 0)
|
||||
if (Sim::findObject(lightDescId, lightDesc) == false)
|
||||
|
|
@ -553,6 +550,7 @@ S32 ProjectileData::scaleValue( S32 value, bool down )
|
|||
//
|
||||
Projectile::Projectile()
|
||||
: mPhysicsWorld( NULL ),
|
||||
mDataBlock( NULL ),
|
||||
mCurrPosition( 0, 0, 0 ),
|
||||
mCurrVelocity( 0, 0, 1 ),
|
||||
mSourceObjectId( -1 ),
|
||||
|
|
@ -700,6 +698,12 @@ bool Projectile::onAdd()
|
|||
if(!Parent::onAdd())
|
||||
return false;
|
||||
|
||||
if( !mDataBlock )
|
||||
{
|
||||
Con::errorf("Projectile::onAdd - Fail - Not datablock");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isServerObject())
|
||||
{
|
||||
ShapeBase* ptr;
|
||||
|
|
@ -1014,7 +1018,7 @@ void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideT
|
|||
|
||||
// Client (impact) decal.
|
||||
if ( mDataBlock->decal )
|
||||
gDecalManager->addDecal( p, n, 0.0f, mDataBlock->decal );
|
||||
gDecalManager->addDecal(p, n, mRandF(0.0f, M_2PI_F), mDataBlock->decal);
|
||||
|
||||
// Client object
|
||||
updateSound();
|
||||
|
|
@ -1109,68 +1113,67 @@ void Projectile::simulate( F32 dt )
|
|||
if ( isServerObject() && ( rInfo.object->getTypeMask() & csmStaticCollisionMask ) == 0 )
|
||||
setMaskBits( BounceMask );
|
||||
|
||||
MatrixF xform( true );
|
||||
xform.setColumn( 3, rInfo.point );
|
||||
setTransform( xform );
|
||||
mCurrPosition = rInfo.point;
|
||||
|
||||
// Get the object type before the onCollision call, in case
|
||||
// the object is destroyed.
|
||||
U32 objectType = rInfo.object->getTypeMask();
|
||||
|
||||
// re-enable the collision response on the source object since
|
||||
// we need to process the onCollision and explode calls
|
||||
if ( disableSourceObjCollision )
|
||||
mSourceObject->enableCollision();
|
||||
|
||||
// Ok, here is how this works:
|
||||
// onCollision is called to notify the server scripts that a collision has occurred, then
|
||||
// a call to explode is made to start the explosion process. The call to explode is made
|
||||
// twice, once on the server and once on the client.
|
||||
// The server process is responsible for two things:
|
||||
// 1) setting the ExplosionMask network bit to guarantee that the client calls explode
|
||||
// 2) initiate the explosion process on the server scripts
|
||||
// The client process is responsible for only one thing:
|
||||
// 1) drawing the appropriate explosion
|
||||
|
||||
// It is possible that during the processTick the server may have decided that a hit
|
||||
// has occurred while the client prediction has decided that a hit has not occurred.
|
||||
// In this particular scenario the client will have failed to call onCollision and
|
||||
// explode during the processTick. However, the explode function will be called
|
||||
// during the next packet update, due to the ExplosionMask network bit being set.
|
||||
// onCollision will remain uncalled on the client however, therefore no client
|
||||
// specific code should be placed inside the function!
|
||||
onCollision( rInfo.point, rInfo.normal, rInfo.object );
|
||||
// Next order of business: do we explode on this hit?
|
||||
if ( mCurrTick > mDataBlock->armingDelay || mDataBlock->armingDelay == 0 )
|
||||
{
|
||||
MatrixF xform( true );
|
||||
xform.setColumn( 3, rInfo.point );
|
||||
setTransform( xform );
|
||||
mCurrPosition = rInfo.point;
|
||||
mCurrVelocity = Point3F::Zero;
|
||||
|
||||
// Get the object type before the onCollision call, in case
|
||||
// the object is destroyed.
|
||||
U32 objectType = rInfo.object->getTypeMask();
|
||||
|
||||
// re-enable the collision response on the source object since
|
||||
// we need to process the onCollision and explode calls
|
||||
if ( disableSourceObjCollision )
|
||||
mSourceObject->enableCollision();
|
||||
|
||||
// Ok, here is how this works:
|
||||
// onCollision is called to notify the server scripts that a collision has occurred, then
|
||||
// a call to explode is made to start the explosion process. The call to explode is made
|
||||
// twice, once on the server and once on the client.
|
||||
// The server process is responsible for two things:
|
||||
// 1) setting the ExplosionMask network bit to guarantee that the client calls explode
|
||||
// 2) initiate the explosion process on the server scripts
|
||||
// The client process is responsible for only one thing:
|
||||
// 1) drawing the appropriate explosion
|
||||
|
||||
// It is possible that during the processTick the server may have decided that a hit
|
||||
// has occurred while the client prediction has decided that a hit has not occurred.
|
||||
// In this particular scenario the client will have failed to call onCollision and
|
||||
// explode during the processTick. However, the explode function will be called
|
||||
// during the next packet update, due to the ExplosionMask network bit being set.
|
||||
// onCollision will remain uncalled on the client however, therefore no client
|
||||
// specific code should be placed inside the function!
|
||||
onCollision( rInfo.point, rInfo.normal, rInfo.object );
|
||||
explode( rInfo.point, rInfo.normal, objectType );
|
||||
}
|
||||
|
||||
// break out of the collision check, since we've exploded
|
||||
// we don't want to mess with the position and velocity
|
||||
if ( mDataBlock->isBallistic )
|
||||
{
|
||||
// Otherwise, this represents a bounce. First, reflect our velocity
|
||||
// around the normal...
|
||||
Point3F bounceVel = mCurrVelocity - rInfo.normal * (mDot( mCurrVelocity, rInfo.normal ) * 2.0);
|
||||
mCurrVelocity = bounceVel;
|
||||
|
||||
// Add in surface friction...
|
||||
Point3F tangent = bounceVel - rInfo.normal * mDot(bounceVel, rInfo.normal);
|
||||
mCurrVelocity -= tangent * mDataBlock->bounceFriction;
|
||||
|
||||
// Now, take elasticity into account for modulating the speed of the grenade
|
||||
mCurrVelocity *= mDataBlock->bounceElasticity;
|
||||
|
||||
// Set the new position to the impact and the bounce
|
||||
// will apply on the next frame.
|
||||
//F32 timeLeft = 1.0f - rInfo.t;
|
||||
newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mDataBlock->isBallistic )
|
||||
{
|
||||
// Otherwise, this represents a bounce. First, reflect our velocity
|
||||
// around the normal...
|
||||
Point3F bounceVel = mCurrVelocity - rInfo.normal * (mDot( mCurrVelocity, rInfo.normal ) * 2.0);
|
||||
mCurrVelocity = bounceVel;
|
||||
|
||||
// Add in surface friction...
|
||||
Point3F tangent = bounceVel - rInfo.normal * mDot(bounceVel, rInfo.normal);
|
||||
mCurrVelocity -= tangent * mDataBlock->bounceFriction;
|
||||
|
||||
// Now, take elasticity into account for modulating the speed of the grenade
|
||||
mCurrVelocity *= mDataBlock->bounceElasticity;
|
||||
|
||||
// Set the new position to the impact and the bounce
|
||||
// will apply on the next frame.
|
||||
//F32 timeLeft = 1.0f - rInfo.t;
|
||||
newPosition = oldPosition = rInfo.point + rInfo.normal * 0.05f;
|
||||
}
|
||||
mCurrVelocity = Point3F::Zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1447,4 +1450,4 @@ DefineEngineMethod(Projectile, presimulate, void, (F32 seconds), (1.0f),
|
|||
"@note This function is not called if the SimObject::hidden is true.")
|
||||
{
|
||||
object->simulate( seconds );
|
||||
}
|
||||
}
|
||||
|
|
@ -215,9 +215,9 @@ public:
|
|||
|
||||
void updateSound();
|
||||
|
||||
virtual bool calculateImpact( float simTime,
|
||||
virtual bool calculateImpact( F32 simTime,
|
||||
Point3F &pointOfImpact,
|
||||
float &impactTime );
|
||||
F32 &impactTime );
|
||||
|
||||
void setInitialPosition( const Point3F& pos );
|
||||
void setInitialVelocity( const Point3F& vel );
|
||||
|
|
|
|||
|
|
@ -136,11 +136,11 @@ bool ProximityMineData::preload( bool server, String& errorStr )
|
|||
if ( !server )
|
||||
{
|
||||
// Resolve sounds
|
||||
String errorStr;
|
||||
if( !sfxResolve( &armingSound, errorStr ) )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", errorStr.c_str() );
|
||||
if( !sfxResolve( &triggerSound, errorStr ) )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", errorStr.c_str() );
|
||||
String sfxErrorStr;
|
||||
if( !sfxResolve( &armingSound, sfxErrorStr ) )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() );
|
||||
if( !sfxResolve( &triggerSound, sfxErrorStr ) )
|
||||
Con::errorf( ConsoleLogEntry::General, "ProximityMineData::preload: Invalid packet: %s", sfxErrorStr.c_str() );
|
||||
}
|
||||
|
||||
if ( mShape )
|
||||
|
|
@ -451,7 +451,7 @@ void ProximityMine::processTick( const Move* move )
|
|||
SimpleQueryList sql;
|
||||
getContainer()->findObjects( triggerBox, sTriggerCollisionMask,
|
||||
SimpleQueryList::insertionCallback, &sql );
|
||||
for ( int i = 0; i < sql.mList.size(); i++ )
|
||||
for ( S32 i = 0; i < sql.mList.size(); i++ )
|
||||
{
|
||||
// Detect movement in the trigger area
|
||||
if ( ( sql.mList[i] == mOwner && !mDataBlock->triggerOnOwner ) ||
|
||||
|
|
|
|||
|
|
@ -265,8 +265,8 @@ void Rigid::translateCenterOfMass(const Point3F &oldPos,const Point3F &newPos)
|
|||
MatrixF oldx,newx;
|
||||
oldx.setCrossProduct(oldPos);
|
||||
newx.setCrossProduct(newPos);
|
||||
for (int row = 0; row < 3; row++)
|
||||
for (int col = 0; col < 3; col++) {
|
||||
for (S32 row = 0; row < 3; row++)
|
||||
for (S32 col = 0; col < 3; col++) {
|
||||
F32 n = newx(row,col), o = oldx(row,col);
|
||||
objectInertia(row,col) += mass * ((o * o) - (n * n));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,11 +196,11 @@ namespace {
|
|||
|
||||
// Physics and collision constants
|
||||
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
|
||||
static int sRestCount = 10; // Consecutive ticks before comming to rest
|
||||
static S32 sRestCount = 10; // Consecutive ticks before comming to rest
|
||||
|
||||
const U32 sCollisionMoveMask = (TerrainObjectType | InteriorObjectType |
|
||||
PlayerObjectType | StaticShapeObjectType | VehicleObjectType |
|
||||
VehicleBlockerObjectType);
|
||||
const U32 sCollisionMoveMask = ( TerrainObjectType | PlayerObjectType |
|
||||
StaticShapeObjectType | VehicleObjectType |
|
||||
VehicleBlockerObjectType );
|
||||
|
||||
const U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
|
||||
const U32 sClientCollisionMask = sCollisionMoveMask;
|
||||
|
|
@ -302,6 +302,7 @@ bool RigidShapeData::preload(bool server, String &errorStr)
|
|||
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
||||
{
|
||||
Con::errorf("RigidShapeData::preload failed: Rigid shapes must define a collision-1 detail");
|
||||
errorStr = String::ToString("RigidShapeData: Couldn't load shape \"%s\"",shapeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -774,7 +775,8 @@ void RigidShape::processTick(const Move* move)
|
|||
|
||||
// Update the physics based on the integration rate
|
||||
S32 count = mDataBlock->integration;
|
||||
updateWorkingCollisionSet(getCollisionMask());
|
||||
if (!mDisableMove)
|
||||
updateWorkingCollisionSet(getCollisionMask());
|
||||
for (U32 i = 0; i < count; i++)
|
||||
updatePos(TickSec / count);
|
||||
|
||||
|
|
@ -1003,6 +1005,11 @@ void RigidShape::setTransform(const MatrixF& newMat)
|
|||
mContacts.clear();
|
||||
}
|
||||
|
||||
void RigidShape::forceClientTransform()
|
||||
{
|
||||
setMaskBits(ForceMoveMask);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -1134,11 +1141,11 @@ void RigidShape::updatePos(F32 dt)
|
|||
|
||||
void RigidShape::updateForces(F32 /*dt*/)
|
||||
{
|
||||
if (mDisableMove) return;
|
||||
Point3F gravForce(0, 0, sRigidShapeGravity * mRigid.mass * mGravityMod);
|
||||
|
||||
MatrixF currTransform;
|
||||
mRigid.getTransform(&currTransform);
|
||||
mRigid.atRest = false;
|
||||
|
||||
Point3F torque(0, 0, 0);
|
||||
Point3F force(0, 0, 0);
|
||||
|
|
@ -1456,6 +1463,8 @@ U32 RigidShape::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
|
||||
if (stream->writeFlag(mask & PositionMask))
|
||||
{
|
||||
stream->writeFlag(mask & ForceMoveMask);
|
||||
|
||||
stream->writeCompressedPoint(mRigid.linPosition);
|
||||
mathWrite(*stream, mRigid.angPosition);
|
||||
mathWrite(*stream, mRigid.linMomentum);
|
||||
|
|
@ -1480,6 +1489,10 @@ void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
// Check if we need to jump to the given transform
|
||||
// rather than interpolate to it.
|
||||
bool forceUpdate = stream->readFlag();
|
||||
|
||||
mPredictionCount = sMaxPredictionTicks;
|
||||
F32 speed = mRigid.linVelocity.len();
|
||||
mDelta.warpRot[0] = mRigid.angPosition;
|
||||
|
|
@ -1492,7 +1505,7 @@ void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
mRigid.atRest = stream->readFlag();
|
||||
mRigid.updateVelocity();
|
||||
|
||||
if (isProperlyAdded())
|
||||
if (!forceUpdate && isProperlyAdded())
|
||||
{
|
||||
// Determine number of ticks to warp based on the average
|
||||
// of the client and server velocities.
|
||||
|
|
@ -1640,7 +1653,7 @@ void RigidShape::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState
|
|||
GFX->getDrawUtil()->drawCube( desc, Point3F(0.1f,0.1f,0.1f), mDataBlock->massCenter, ColorI(255, 255, 255), &mRenderObjToWorld );
|
||||
|
||||
// Collision points...
|
||||
for (int i = 0; i < mCollisionList.getCount(); i++)
|
||||
for (S32 i = 0; i < mCollisionList.getCount(); i++)
|
||||
{
|
||||
const Collision& collision = mCollisionList[i];
|
||||
GFX->getDrawUtil()->drawCube( desc, Point3F(0.05f,0.05f,0.05f), collision.point, ColorI(0, 0, 255) );
|
||||
|
|
@ -1648,7 +1661,7 @@ void RigidShape::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState
|
|||
|
||||
// Render the normals as one big batch...
|
||||
PrimBuild::begin(GFXLineList, mCollisionList.getCount() * 2);
|
||||
for (int i = 0; i < mCollisionList.getCount(); i++)
|
||||
for (S32 i = 0; i < mCollisionList.getCount(); i++)
|
||||
{
|
||||
|
||||
const Collision& collision = mCollisionList[i];
|
||||
|
|
@ -1710,3 +1723,12 @@ DefineEngineMethod( RigidShape, freezeSim, void, (bool isFrozen),,
|
|||
{
|
||||
object->freezeSim(isFrozen);
|
||||
}
|
||||
|
||||
DefineEngineMethod( RigidShape, forceClientTransform, void, (),,
|
||||
"@brief Forces the client to jump to the RigidShape's transform rather then warp to it.\n\n")
|
||||
{
|
||||
if(object->isServerObject())
|
||||
{
|
||||
object->forceClientTransform();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,10 +152,11 @@ class RigidShape: public ShapeBase
|
|||
WheelCollision = BIT(1),
|
||||
};
|
||||
enum MaskBits {
|
||||
PositionMask = Parent::NextFreeMask << 0,
|
||||
EnergyMask = Parent::NextFreeMask << 1,
|
||||
FreezeMask = Parent::NextFreeMask << 2,
|
||||
NextFreeMask = Parent::NextFreeMask << 3
|
||||
PositionMask = Parent::NextFreeMask << 0,
|
||||
EnergyMask = Parent::NextFreeMask << 1,
|
||||
FreezeMask = Parent::NextFreeMask << 2,
|
||||
ForceMoveMask = Parent::NextFreeMask << 3,
|
||||
NextFreeMask = Parent::NextFreeMask << 4
|
||||
};
|
||||
|
||||
void updateDustTrail( F32 dt );
|
||||
|
|
@ -194,7 +195,7 @@ class RigidShape: public ShapeBase
|
|||
CollisionList mContacts;
|
||||
Rigid mRigid;
|
||||
ShapeBaseConvex mConvex;
|
||||
int restCount;
|
||||
S32 restCount;
|
||||
|
||||
SimObjectPtr<ParticleEmitter> mDustEmitterList[RigidShapeData::VC_NUM_DUST_EMITTERS];
|
||||
SimObjectPtr<ParticleEmitter> mSplashEmitterList[RigidShapeData::VC_NUM_SPLASH_EMITTERS];
|
||||
|
|
@ -283,6 +284,10 @@ public:
|
|||
/// @param impulse Impulse vector to apply.
|
||||
void applyImpulse(const Point3F &r, const Point3F &impulse);
|
||||
|
||||
/// Forces the client to jump to the RigidShape's transform rather
|
||||
/// then warp to it.
|
||||
void forceClientTransform();
|
||||
|
||||
void getCameraParameters(F32 *min, F32* max, Point3F* offset, MatrixF* rot);
|
||||
void getCameraTransform(F32* pos, MatrixF* mat);
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -114,11 +114,12 @@ IMPLEMENT_CALLBACK( ShapeBaseData, onTrigger, void, ( ShapeBase* obj, S32 index,
|
|||
"@param index Index of the trigger that changed\n"
|
||||
"@param state New state of the trigger\n" );
|
||||
|
||||
IMPLEMENT_CALLBACK( ShapeBaseData, onEndSequence, void, ( ShapeBase* obj, S32 slot ), ( obj, slot ),
|
||||
IMPLEMENT_CALLBACK(ShapeBaseData, onEndSequence, void, (ShapeBase* obj, S32 slot, const char* name), (obj, slot, name),
|
||||
"@brief Called when a thread playing a non-cyclic sequence reaches the end of the "
|
||||
"sequence.\n\n"
|
||||
"@param obj The ShapeBase object\n"
|
||||
"@param slot Thread slot that finished playing\n" );
|
||||
"@param slot Thread slot that finished playing\n"
|
||||
"@param name Thread name that finished playing\n");
|
||||
|
||||
IMPLEMENT_CALLBACK( ShapeBaseData, onForceUncloak, void, ( ShapeBase* obj, const char* reason ), ( obj, reason ),
|
||||
"@brief Called when the object is forced to uncloak.\n\n"
|
||||
|
|
@ -171,6 +172,8 @@ ShapeBaseData::ShapeBaseData()
|
|||
cameraDefaultFov( 75.0f ),
|
||||
cameraMinFov( 5.0f ),
|
||||
cameraMaxFov( 120.f ),
|
||||
cameraCanBank( false ),
|
||||
mountedImagesBank( false ),
|
||||
isInvincible( false ),
|
||||
renderWhenDestroyed( true ),
|
||||
debris( NULL ),
|
||||
|
|
@ -304,7 +307,10 @@ bool ShapeBaseData::preload(bool server, String &errorStr)
|
|||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(mShape.getPath());
|
||||
|
||||
if (!fileRef)
|
||||
{
|
||||
errorStr = String::ToString("ShapeBaseData: Couldn't load shape \"%s\"",shapeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(server)
|
||||
mCRC = fileRef->getChecksum();
|
||||
|
|
@ -544,6 +550,10 @@ void ShapeBaseData::initPersistFields()
|
|||
"The minimum camera vertical FOV allowed in degrees." );
|
||||
addField( "cameraMaxFov", TypeF32, Offset(cameraMaxFov, ShapeBaseData),
|
||||
"The maximum camera vertical FOV allowed in degrees." );
|
||||
addField( "cameraCanBank", TypeBool, Offset(cameraCanBank, ShapeBaseData),
|
||||
"If the derrived class supports it, allow the camera to bank." );
|
||||
addField( "mountedImagesBank", TypeBool, Offset(mountedImagesBank, ShapeBaseData),
|
||||
"Do mounted images bank along with the camera?" );
|
||||
addField( "firstPersonOnly", TypeBool, Offset(firstPersonOnly, ShapeBaseData),
|
||||
"Flag controlling whether the view from this object is first person "
|
||||
"only." );
|
||||
|
|
@ -622,7 +632,7 @@ DefineEngineMethod( ShapeBaseData, checkDeployPos, bool, ( TransformF txfm ),,
|
|||
polyList.mPlaneList[i] = temp;
|
||||
}
|
||||
|
||||
if (gServerContainer.buildPolyList(PLC_Collision, wBox, InteriorObjectType | StaticShapeObjectType, &polyList))
|
||||
if (gServerContainer.buildPolyList(PLC_Collision, wBox, StaticShapeObjectType, &polyList))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -689,6 +699,8 @@ void ShapeBaseData::packData(BitStream* stream)
|
|||
stream->write(cameraMinFov);
|
||||
if(stream->writeFlag(cameraMaxFov != gShapeBaseDataProto.cameraMaxFov))
|
||||
stream->write(cameraMaxFov);
|
||||
stream->writeFlag(cameraCanBank);
|
||||
stream->writeFlag(mountedImagesBank);
|
||||
stream->writeString( debrisShapeName );
|
||||
|
||||
stream->writeFlag(observeThroughObject);
|
||||
|
|
@ -788,6 +800,9 @@ void ShapeBaseData::unpackData(BitStream* stream)
|
|||
else
|
||||
cameraMaxFov = gShapeBaseDataProto.cameraMaxFov;
|
||||
|
||||
cameraCanBank = stream->readFlag();
|
||||
mountedImagesBank = stream->readFlag();
|
||||
|
||||
debrisShapeName = stream->readSTString();
|
||||
|
||||
observeThroughObject = stream->readFlag();
|
||||
|
|
@ -887,17 +902,9 @@ ShapeBase::ShapeBase()
|
|||
mCloakLevel( 0.0f ),
|
||||
mDamageFlash( 0.0f ),
|
||||
mWhiteOut( 0.0f ),
|
||||
mInvincibleEffect( 0.0f ),
|
||||
mInvincibleDelta( 0.0f ),
|
||||
mInvincibleCount( 0.0f ),
|
||||
mInvincibleSpeed( 0.0f ),
|
||||
mInvincibleTime( 0.0f ),
|
||||
mInvincibleFade( 0.1f ),
|
||||
mInvincibleOn( false ),
|
||||
mIsControlled( false ),
|
||||
mConvexList( new Convex ),
|
||||
mCameraFov( 90.0f ),
|
||||
mShieldNormal( 0.0f, 0.0f, 1.0f ),
|
||||
mFadeOut( true ),
|
||||
mFading( false ),
|
||||
mFadeVal( 1.0f ),
|
||||
|
|
@ -925,7 +932,6 @@ ShapeBase::ShapeBase()
|
|||
for (i = 0; i < MaxScriptThreads; i++) {
|
||||
mScriptThread[i].sequence = -1;
|
||||
mScriptThread[i].thread = 0;
|
||||
mScriptThread[i].sound = 0;
|
||||
mScriptThread[i].state = Thread::Stop;
|
||||
mScriptThread[i].atEnd = false;
|
||||
mScriptThread[i].timescale = 1.f;
|
||||
|
|
@ -947,6 +953,7 @@ ShapeBase::~ShapeBase()
|
|||
if( mShapeInstance && (mShapeInstance->getDebrisRefCount() == 0) )
|
||||
{
|
||||
delete mShapeInstance;
|
||||
mShapeInstance = NULL;
|
||||
}
|
||||
|
||||
CollisionTimeout* ptr = mTimeoutList;
|
||||
|
|
@ -1270,7 +1277,7 @@ void ShapeBase::processTick(const Move* move)
|
|||
{
|
||||
mMoveMotion = true;
|
||||
}
|
||||
for (int i = 0; i < MaxMountedImages; i++)
|
||||
for (S32 i = 0; i < MaxMountedImages; i++)
|
||||
{
|
||||
setImageMotionState(i, mMoveMotion);
|
||||
}
|
||||
|
|
@ -1293,7 +1300,7 @@ void ShapeBase::processTick(const Move* move)
|
|||
// Advance images
|
||||
if (isServerObject())
|
||||
{
|
||||
for (int i = 0; i < MaxMountedImages; i++)
|
||||
for (S32 i = 0; i < MaxMountedImages; i++)
|
||||
{
|
||||
if (mMountedImageList[i].dataBlock)
|
||||
updateImageState(i, TickSec);
|
||||
|
|
@ -1335,7 +1342,7 @@ void ShapeBase::advanceTime(F32 dt)
|
|||
// advanced at framerate.
|
||||
advanceThreads(dt);
|
||||
updateAudioPos();
|
||||
for (int i = 0; i < MaxMountedImages; i++)
|
||||
for (S32 i = 0; i < MaxMountedImages; i++)
|
||||
if (mMountedImageList[i].dataBlock)
|
||||
{
|
||||
updateImageState(i, dt);
|
||||
|
|
@ -1370,9 +1377,6 @@ void ShapeBase::advanceTime(F32 dt)
|
|||
mCloakLevel = 0.0;
|
||||
}
|
||||
}
|
||||
if(mInvincibleOn)
|
||||
updateInvincibleEffect(dt);
|
||||
|
||||
if(mFading)
|
||||
{
|
||||
mFadeElapsedTime += dt;
|
||||
|
|
@ -1872,10 +1876,10 @@ Point3F ShapeBase::getAIRepairPoint()
|
|||
|
||||
void ShapeBase::getEyeTransform(MatrixF* mat)
|
||||
{
|
||||
getEyeBaseTransform(mat);
|
||||
getEyeBaseTransform(mat, true);
|
||||
}
|
||||
|
||||
void ShapeBase::getEyeBaseTransform(MatrixF* mat)
|
||||
void ShapeBase::getEyeBaseTransform(MatrixF* mat, bool includeBank)
|
||||
{
|
||||
// Returns eye to world space transform
|
||||
S32 eyeNode = mDataBlock->eyeNode;
|
||||
|
|
@ -1887,10 +1891,10 @@ void ShapeBase::getEyeBaseTransform(MatrixF* mat)
|
|||
|
||||
void ShapeBase::getRenderEyeTransform(MatrixF* mat)
|
||||
{
|
||||
getRenderEyeBaseTransform(mat);
|
||||
getRenderEyeBaseTransform(mat, true);
|
||||
}
|
||||
|
||||
void ShapeBase::getRenderEyeBaseTransform(MatrixF* mat)
|
||||
void ShapeBase::getRenderEyeBaseTransform(MatrixF* mat, bool includeBank)
|
||||
{
|
||||
// Returns eye to world space transform
|
||||
S32 eyeNode = mDataBlock->eyeNode;
|
||||
|
|
@ -1975,119 +1979,6 @@ void ShapeBase::getCameraTransform(F32* pos,MatrixF* mat)
|
|||
mat->mul( gCamFXMgr.getTrans() );
|
||||
}
|
||||
|
||||
// void ShapeBase::getCameraTransform(F32* pos,MatrixF* mat)
|
||||
// {
|
||||
// // Returns camera to world space transform
|
||||
// // Handles first person / third person camera position
|
||||
|
||||
// if (isServerObject() && mShapeInstance)
|
||||
// mShapeInstance->animateNodeSubtrees(true);
|
||||
|
||||
// if (*pos != 0) {
|
||||
// F32 min,max;
|
||||
// Point3F offset;
|
||||
// MatrixF eye,rot;
|
||||
// getCameraParameters(&min,&max,&offset,&rot);
|
||||
// getRenderEyeTransform(&eye);
|
||||
// mat->mul(eye,rot);
|
||||
|
||||
// // Use the eye transform to orient the camera
|
||||
// VectorF vp,vec;
|
||||
// vp.x = vp.z = 0;
|
||||
// vp.y = -(max - min) * *pos;
|
||||
// eye.mulV(vp,&vec);
|
||||
|
||||
// // Use the camera node's pos.
|
||||
// Point3F osp,sp;
|
||||
// if (mDataBlock->cameraNode != -1) {
|
||||
// mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp);
|
||||
// getRenderTransform().mulP(osp,&sp);
|
||||
// }
|
||||
// else
|
||||
// getRenderTransform().getColumn(3,&sp);
|
||||
|
||||
// // Make sure we don't extend the camera into anything solid
|
||||
// Point3F ep = sp + vec;
|
||||
// ep += offset;
|
||||
// disableCollision();
|
||||
// if (isMounted())
|
||||
// getObjectMount()->disableCollision();
|
||||
// RayInfo collision;
|
||||
// if (mContainer->castRay(sp,ep,(0xFFFFFFFF & ~(WaterObjectType|ForceFieldObjectType|GameBaseObjectType|DefaultObjectType)),&collision)) {
|
||||
// *pos = collision.t *= 0.9;
|
||||
// if (*pos == 0)
|
||||
// eye.getColumn(3,&ep);
|
||||
// else
|
||||
// ep = sp + vec * *pos;
|
||||
// }
|
||||
// mat->setColumn(3,ep);
|
||||
// if (isMounted())
|
||||
// getObjectMount()->enableCollision();
|
||||
// enableCollision();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// getRenderEyeTransform(mat);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// void ShapeBase::getRenderCameraTransform(F32* pos,MatrixF* mat)
|
||||
// {
|
||||
// // Returns camera to world space transform
|
||||
// // Handles first person / third person camera position
|
||||
|
||||
// if (isServerObject() && mShapeInstance)
|
||||
// mShapeInstance->animateNodeSubtrees(true);
|
||||
|
||||
// if (*pos != 0) {
|
||||
// F32 min,max;
|
||||
// Point3F offset;
|
||||
// MatrixF eye,rot;
|
||||
// getCameraParameters(&min,&max,&offset,&rot);
|
||||
// getRenderEyeTransform(&eye);
|
||||
// mat->mul(eye,rot);
|
||||
|
||||
// // Use the eye transform to orient the camera
|
||||
// VectorF vp,vec;
|
||||
// vp.x = vp.z = 0;
|
||||
// vp.y = -(max - min) * *pos;
|
||||
// eye.mulV(vp,&vec);
|
||||
|
||||
// // Use the camera node's pos.
|
||||
// Point3F osp,sp;
|
||||
// if (mDataBlock->cameraNode != -1) {
|
||||
// mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp);
|
||||
// getRenderTransform().mulP(osp,&sp);
|
||||
// }
|
||||
// else
|
||||
// getRenderTransform().getColumn(3,&sp);
|
||||
|
||||
// // Make sure we don't extend the camera into anything solid
|
||||
// Point3F ep = sp + vec;
|
||||
// ep += offset;
|
||||
// disableCollision();
|
||||
// if (isMounted())
|
||||
// getObjectMount()->disableCollision();
|
||||
// RayInfo collision;
|
||||
// if (mContainer->castRay(sp,ep,(0xFFFFFFFF & ~(WaterObjectType|ForceFieldObjectType|GameBaseObjectType|DefaultObjectType)),&collision)) {
|
||||
// *pos = collision.t *= 0.9;
|
||||
// if (*pos == 0)
|
||||
// eye.getColumn(3,&ep);
|
||||
// else
|
||||
// ep = sp + vec * *pos;
|
||||
// }
|
||||
// mat->setColumn(3,ep);
|
||||
// if (isMounted())
|
||||
// getObjectMount()->enableCollision();
|
||||
// enableCollision();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// getRenderEyeTransform(mat);
|
||||
// }
|
||||
// }
|
||||
|
||||
void ShapeBase::getCameraParameters(F32 *min,F32* max,Point3F* off,MatrixF* rot)
|
||||
{
|
||||
*min = mDataBlock->cameraMinDist;
|
||||
|
|
@ -2141,52 +2032,6 @@ bool ShapeBase::useObjsEyePoint() const
|
|||
return mDataBlock->useEyePoint;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
F32 ShapeBase::getInvincibleEffect() const
|
||||
{
|
||||
return mInvincibleEffect;
|
||||
}
|
||||
|
||||
void ShapeBase::setupInvincibleEffect(F32 time, F32 speed)
|
||||
{
|
||||
if(isClientObject())
|
||||
{
|
||||
mInvincibleCount = mInvincibleTime = time;
|
||||
mInvincibleSpeed = mInvincibleDelta = speed;
|
||||
mInvincibleEffect = 0.0f;
|
||||
mInvincibleOn = true;
|
||||
mInvincibleFade = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mInvincibleTime = time;
|
||||
mInvincibleSpeed = speed;
|
||||
setMaskBits(InvincibleMask);
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeBase::updateInvincibleEffect(F32 dt)
|
||||
{
|
||||
if(mInvincibleCount > 0.0f )
|
||||
{
|
||||
if(mInvincibleEffect >= ((0.3 * mInvincibleFade) + 0.05f) && mInvincibleDelta > 0.0f)
|
||||
mInvincibleDelta = -mInvincibleSpeed;
|
||||
else if(mInvincibleEffect <= 0.05f && mInvincibleDelta < 0.0f)
|
||||
{
|
||||
mInvincibleDelta = mInvincibleSpeed;
|
||||
mInvincibleFade = mInvincibleCount / mInvincibleTime;
|
||||
}
|
||||
mInvincibleEffect += mInvincibleDelta;
|
||||
mInvincibleCount -= dt;
|
||||
}
|
||||
else
|
||||
{
|
||||
mInvincibleEffect = 0.0f;
|
||||
mInvincibleOn = false;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void ShapeBase::setVelocity(const VectorF&)
|
||||
{
|
||||
|
|
@ -2228,7 +2073,7 @@ void ShapeBase::stopAudio(U32 slot)
|
|||
void ShapeBase::updateServerAudio()
|
||||
{
|
||||
// Timeout non-looping sounds
|
||||
for (int i = 0; i < MaxSoundThreads; i++) {
|
||||
for (S32 i = 0; i < MaxSoundThreads; i++) {
|
||||
Sound& st = mSoundThread[i];
|
||||
if (st.play && st.timeout && st.timeout < Sim::getCurrentTime()) {
|
||||
clearMaskBits(SoundMaskN << i);
|
||||
|
|
@ -2268,7 +2113,7 @@ void ShapeBase::updateAudioState(Sound& st)
|
|||
|
||||
void ShapeBase::updateAudioPos()
|
||||
{
|
||||
for (int i = 0; i < MaxSoundThreads; i++)
|
||||
for (S32 i = 0; i < MaxSoundThreads; i++)
|
||||
{
|
||||
SFXSource* source = mSoundThread[i].sound;
|
||||
if ( source )
|
||||
|
|
@ -2310,14 +2155,13 @@ bool ShapeBase::setThreadSequence(U32 slot, S32 seq, bool reset)
|
|||
if (reset) {
|
||||
st.state = Thread::Play;
|
||||
st.atEnd = false;
|
||||
st.timescale = 1.f;
|
||||
st.position = 0.f;
|
||||
st.timescale = 1.f;
|
||||
st.position = 0.f;
|
||||
}
|
||||
if (mShapeInstance) {
|
||||
if (!st.thread)
|
||||
st.thread = mShapeInstance->addThread();
|
||||
mShapeInstance->setSequence(st.thread,seq,0);
|
||||
stopThreadSound(st);
|
||||
mShapeInstance->setSequence(st.thread,seq,st.position);
|
||||
updateThread(st);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -2332,19 +2176,12 @@ void ShapeBase::updateThread(Thread& st)
|
|||
case Thread::Stop:
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 1.f );
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 0.0f : 1.0f );
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f );
|
||||
} // Drop through to pause state
|
||||
|
||||
case Thread::Pause:
|
||||
{
|
||||
if ( st.position != -1.f )
|
||||
{
|
||||
mShapeInstance->setTimeScale( st.thread, 1.f );
|
||||
mShapeInstance->setPos( st.thread, st.position );
|
||||
}
|
||||
|
||||
mShapeInstance->setTimeScale( st.thread, 0.f );
|
||||
stopThreadSound( st );
|
||||
} break;
|
||||
|
||||
case Thread::Play:
|
||||
|
|
@ -2354,7 +2191,6 @@ void ShapeBase::updateThread(Thread& st)
|
|||
mShapeInstance->setTimeScale(st.thread,1);
|
||||
mShapeInstance->setPos( st.thread, ( st.timescale > 0.f ) ? 1.0f : 0.0f );
|
||||
mShapeInstance->setTimeScale(st.thread,0);
|
||||
stopThreadSound(st);
|
||||
st.state = Thread::Stop;
|
||||
}
|
||||
else
|
||||
|
|
@ -2366,16 +2202,11 @@ void ShapeBase::updateThread(Thread& st)
|
|||
}
|
||||
|
||||
mShapeInstance->setTimeScale(st.thread, st.timescale );
|
||||
if (!st.sound)
|
||||
{
|
||||
startSequenceSound(st);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Thread::Destroy:
|
||||
{
|
||||
stopThreadSound(st);
|
||||
st.atEnd = true;
|
||||
st.sequence = -1;
|
||||
if(st.thread)
|
||||
|
|
@ -2483,19 +2314,6 @@ bool ShapeBase::setThreadTimeScale( U32 slot, F32 timeScale )
|
|||
return false;
|
||||
}
|
||||
|
||||
void ShapeBase::stopThreadSound(Thread& thread)
|
||||
{
|
||||
if (thread.sound) {
|
||||
}
|
||||
}
|
||||
|
||||
void ShapeBase::startSequenceSound(Thread& thread)
|
||||
{
|
||||
if (!isGhost() || !thread.thread)
|
||||
return;
|
||||
stopThreadSound(thread);
|
||||
}
|
||||
|
||||
void ShapeBase::advanceThreads(F32 dt)
|
||||
{
|
||||
for (U32 i = 0; i < MaxScriptThreads; i++) {
|
||||
|
|
@ -2507,7 +2325,7 @@ void ShapeBase::advanceThreads(F32 dt)
|
|||
st.atEnd = true;
|
||||
updateThread(st);
|
||||
if (!isGhost()) {
|
||||
mDataBlock->onEndSequence_callback( this, i );
|
||||
mDataBlock->onEndSequence_callback(this, i, this->getThreadSequenceName(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2516,6 +2334,7 @@ void ShapeBase::advanceThreads(F32 dt)
|
|||
if(st.thread)
|
||||
{
|
||||
mShapeInstance->advanceTime(dt,st.thread);
|
||||
st.position = mShapeInstance->getPos(st.thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2582,7 +2401,7 @@ void ShapeBase::_prepRenderImage( SceneRenderState *state,
|
|||
return;
|
||||
|
||||
// We don't need to render if all the meshes are forced hidden.
|
||||
if ( mMeshHidden.testAll() )
|
||||
if ( mMeshHidden.getSize() > 0 && mMeshHidden.testAll() )
|
||||
return;
|
||||
|
||||
// If we're rendering shadows don't render the mounted
|
||||
|
|
@ -3090,8 +2909,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
}
|
||||
|
||||
if(!stream->writeFlag(mask & (NameMask | DamageMask | SoundMask | MeshHiddenMask |
|
||||
ThreadMask | ImageMask | CloakMask | InvincibleMask |
|
||||
ShieldMask | SkinMask)))
|
||||
ThreadMask | ImageMask | CloakMask | SkinMask)))
|
||||
return retMask;
|
||||
|
||||
if (stream->writeFlag(mask & DamageMask)) {
|
||||
|
|
@ -3101,7 +2919,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
}
|
||||
|
||||
if (stream->writeFlag(mask & ThreadMask)) {
|
||||
for (int i = 0; i < MaxScriptThreads; i++) {
|
||||
for (S32 i = 0; i < MaxScriptThreads; i++) {
|
||||
Thread& st = mScriptThread[i];
|
||||
if (stream->writeFlag( (st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i)) ) ) {
|
||||
stream->writeInt(st.sequence,ThreadSequenceBits);
|
||||
|
|
@ -3114,7 +2932,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
}
|
||||
|
||||
if (stream->writeFlag(mask & SoundMask)) {
|
||||
for (int i = 0; i < MaxSoundThreads; i++) {
|
||||
for (S32 i = 0; i < MaxSoundThreads; i++) {
|
||||
Sound& st = mSoundThread[i];
|
||||
if (stream->writeFlag(mask & (SoundMaskN << i)))
|
||||
if (stream->writeFlag(st.play))
|
||||
|
|
@ -3124,7 +2942,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
}
|
||||
|
||||
if (stream->writeFlag(mask & ImageMask)) {
|
||||
for (int i = 0; i < MaxMountedImages; i++)
|
||||
for (S32 i = 0; i < MaxMountedImages; i++)
|
||||
if (stream->writeFlag(mask & (ImageMaskN << i))) {
|
||||
MountedImage& image = mMountedImageList[i];
|
||||
if (stream->writeFlag(image.dataBlock))
|
||||
|
|
@ -3146,9 +2964,9 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
stream->writeFlag(image.triggerDown);
|
||||
stream->writeFlag(image.altTriggerDown);
|
||||
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxGenericTriggers; ++i)
|
||||
for (U32 j=0; j<ShapeBaseImageData::MaxGenericTriggers; ++j)
|
||||
{
|
||||
stream->writeFlag(image.genericTrigger[i]);
|
||||
stream->writeFlag(image.genericTrigger[j]);
|
||||
}
|
||||
|
||||
stream->writeInt(image.fireCount,3);
|
||||
|
|
@ -3161,7 +2979,7 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
}
|
||||
|
||||
// Group some of the uncommon stuff together.
|
||||
if (stream->writeFlag(mask & (NameMask | ShieldMask | CloakMask | InvincibleMask | SkinMask | MeshHiddenMask ))) {
|
||||
if (stream->writeFlag(mask & (NameMask | CloakMask | SkinMask | MeshHiddenMask ))) {
|
||||
|
||||
if (stream->writeFlag(mask & CloakMask))
|
||||
{
|
||||
|
|
@ -3182,14 +3000,6 @@ U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
|
|||
if (stream->writeFlag(mask & NameMask)) {
|
||||
con->packNetStringHandleU(stream, mShapeNameHandle);
|
||||
}
|
||||
if (stream->writeFlag(mask & ShieldMask)) {
|
||||
stream->writeNormalVector(mShieldNormal, ShieldNormalBits);
|
||||
stream->writeFloat( getEnergyValue(), EnergyLevelBits );
|
||||
}
|
||||
if (stream->writeFlag(mask & InvincibleMask)) {
|
||||
stream->write(mInvincibleTime);
|
||||
stream->write(mInvincibleSpeed);
|
||||
}
|
||||
|
||||
if ( stream->writeFlag( mask & MeshHiddenMask ) )
|
||||
stream->writeBits( mMeshHidden );
|
||||
|
|
@ -3225,9 +3035,9 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
if (stream->readFlag()) {
|
||||
Thread& st = mScriptThread[i];
|
||||
U32 seq = stream->readInt(ThreadSequenceBits);
|
||||
st.state = stream->readInt(2);
|
||||
stream->read( &st.timescale );
|
||||
stream->read( &st.position );
|
||||
st.state = Thread::State(stream->readInt(2));
|
||||
stream->read( &st.timescale );
|
||||
stream->read( &st.position );
|
||||
st.atEnd = stream->readFlag();
|
||||
if (st.sequence != seq && st.state != Thread::Destroy)
|
||||
setThreadSequence(i,seq,false);
|
||||
|
|
@ -3259,7 +3069,7 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
|
||||
// Mounted Images
|
||||
if (stream->readFlag()) {
|
||||
for (int i = 0; i < MaxMountedImages; i++) {
|
||||
for (S32 i = 0; i < MaxMountedImages; i++) {
|
||||
if (stream->readFlag()) {
|
||||
MountedImage& image = mMountedImageList[i];
|
||||
ShapeBaseImageData* imageData = 0;
|
||||
|
|
@ -3291,14 +3101,14 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
image.triggerDown = stream->readFlag();
|
||||
image.altTriggerDown = stream->readFlag();
|
||||
|
||||
for (U32 i=0; i<ShapeBaseImageData::MaxGenericTriggers; ++i)
|
||||
for (U32 j=0; j<ShapeBaseImageData::MaxGenericTriggers; ++j)
|
||||
{
|
||||
image.genericTrigger[i] = stream->readFlag();
|
||||
image.genericTrigger[j] = stream->readFlag();
|
||||
}
|
||||
|
||||
int count = stream->readInt(3);
|
||||
int altCount = stream->readInt(3);
|
||||
int reloadCount = stream->readInt(3);
|
||||
S32 count = stream->readInt(3);
|
||||
S32 altCount = stream->readInt(3);
|
||||
S32 reloadCount = stream->readInt(3);
|
||||
|
||||
bool datablockChange = image.dataBlock != imageData;
|
||||
if (datablockChange || (image.skinNameHandle != skinDesiredNameHandle))
|
||||
|
|
@ -3431,25 +3241,6 @@ void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
|
|||
if (stream->readFlag()) { // NameMask
|
||||
mShapeNameHandle = con->unpackNetStringHandleU(stream);
|
||||
}
|
||||
if(stream->readFlag()) // ShieldMask
|
||||
{
|
||||
// Cloaking, Shield, and invul masking
|
||||
Point3F shieldNormal;
|
||||
stream->readNormalVector(&shieldNormal, ShieldNormalBits);
|
||||
|
||||
// CodeReview [bjg 4/6/07] This is our energy level - why aren't we storing it? Was in a
|
||||
// local variable called energyPercent.
|
||||
stream->readFloat(EnergyLevelBits);
|
||||
}
|
||||
|
||||
if (stream->readFlag())
|
||||
{
|
||||
// InvincibleMask
|
||||
F32 time, speed;
|
||||
stream->read(&time);
|
||||
stream->read(&speed);
|
||||
setupInvincibleEffect(time, speed);
|
||||
}
|
||||
|
||||
if ( stream->readFlag() ) // MeshHiddenMask
|
||||
{
|
||||
|
|
@ -3730,7 +3521,7 @@ void ShapeBase::reSkin()
|
|||
Vector<String> skins;
|
||||
String(mSkinNameHandle.getString()).split( ";", skins );
|
||||
|
||||
for (int i = 0; i < skins.size(); i++)
|
||||
for (S32 i = 0; i < skins.size(); i++)
|
||||
{
|
||||
String oldSkin( mAppliedSkinName.c_str() );
|
||||
String newSkin( skins[i] );
|
||||
|
|
@ -4601,6 +4392,11 @@ DefineEngineMethod( ShapeBase, isEnabled, bool, (),,
|
|||
return object->getDamageState() == ShapeBase::Enabled;
|
||||
}
|
||||
|
||||
DefineEngineMethod(ShapeBase, blowUp, void, (),, "@brief Explodes an object into pieces.")
|
||||
{
|
||||
object->blowUp();
|
||||
}
|
||||
|
||||
DefineEngineMethod( ShapeBase, applyDamage, void, ( F32 amount ),,
|
||||
"@brief Increment the current damage level by the specified amount.\n\n"
|
||||
|
||||
|
|
@ -4809,18 +4605,6 @@ DefineEngineMethod( ShapeBase, setCameraFov, void, ( F32 fov ),,
|
|||
object->setCameraFov( fov );
|
||||
}
|
||||
|
||||
DefineEngineMethod( ShapeBase, setInvincibleMode, void, ( F32 time, F32 speed ),,
|
||||
"@brief Setup the invincible effect.\n\n"
|
||||
|
||||
"This effect is used for HUD feedback to the user that they are invincible.\n"
|
||||
"@note Currently not implemented\n"
|
||||
|
||||
"@param time duration in seconds for the invincible effect\n"
|
||||
"@param speed speed at which the invincible effect progresses\n" )
|
||||
{
|
||||
object->setupInvincibleEffect( time, speed );
|
||||
}
|
||||
|
||||
DefineEngineMethod( ShapeBase, startFade, void, ( S32 time, S32 delay, bool fadeOut ),,
|
||||
"@brief Fade the object in or out without removing it from the scene.\n\n"
|
||||
|
||||
|
|
@ -5038,7 +4822,7 @@ DefineEngineMethod( ShapeBase, dumpMeshVisibility, void, (),,
|
|||
#endif // #ifndef TORQUE_SHIPPING
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//These functions are duplicated in tsStatic, shapeBase, and interiorInstance.
|
||||
//These functions are duplicated in tsStatic and shapeBase.
|
||||
//They each function a little differently; but achieve the same purpose of gathering
|
||||
//target names/counts without polluting simObject.
|
||||
|
||||
|
|
@ -5127,8 +4911,8 @@ DefineEngineMethod( ShapeBase, changeMaterial, void, ( const char* mapTo, Materi
|
|||
|
||||
newMat->mMapTo = mapTo;
|
||||
|
||||
// Map the material in the in the matmgr
|
||||
MATMGR->mapMaterial( mapTo, newMat->mMapTo );
|
||||
// Map the material by name in the matmgr
|
||||
MATMGR->mapMaterial( mapTo, newMat->getName() );
|
||||
|
||||
// Replace instances with the new material being traded in. For ShapeBase
|
||||
// class we have to update the server/client objects separately so both
|
||||
|
|
|
|||
|
|
@ -578,6 +578,12 @@ public:
|
|||
F32 cameraMaxFov; ///< Max vertical FOV allowed in degrees.
|
||||
/// @}
|
||||
|
||||
/// @name Camera Misc
|
||||
/// @{
|
||||
bool cameraCanBank; ///< If the derrived class supports it, allow the camera to bank
|
||||
bool mountedImagesBank; ///< Do mounted images bank along with the camera?
|
||||
/// @}
|
||||
|
||||
/// @name Data initialized on preload
|
||||
/// @{
|
||||
|
||||
|
|
@ -642,7 +648,7 @@ public:
|
|||
DECLARE_CALLBACK( void, onCollision, ( ShapeBase* obj, SceneObject* collObj, VectorF vec, F32 len ) );
|
||||
DECLARE_CALLBACK( void, onDamage, ( ShapeBase* obj, F32 delta ) );
|
||||
DECLARE_CALLBACK( void, onTrigger, ( ShapeBase* obj, S32 index, bool state ) );
|
||||
DECLARE_CALLBACK( void, onEndSequence, ( ShapeBase* obj, S32 slot ) );
|
||||
DECLARE_CALLBACK(void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name));
|
||||
DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) );
|
||||
/// @}
|
||||
};
|
||||
|
|
@ -683,7 +689,6 @@ public:
|
|||
MaxMountedImages = 4, ///< Should be a power of 2
|
||||
MaxImageEmitters = 3,
|
||||
NumImageBits = 3,
|
||||
ShieldNormalBits = 8,
|
||||
CollisionTimeoutValue = 250 ///< Timeout in ms.
|
||||
};
|
||||
|
||||
|
|
@ -724,12 +729,9 @@ protected:
|
|||
Play, Stop, Pause, Destroy
|
||||
};
|
||||
TSThread* thread; ///< Pointer to 3space data.
|
||||
U32 state; ///< State of the thread
|
||||
///
|
||||
/// @see Thread::State
|
||||
State state; ///< State of the thread
|
||||
S32 sequence; ///< The animation sequence which is running in this thread.
|
||||
F32 timescale; ///< Timescale
|
||||
U32 sound; ///< Handle to sound.
|
||||
F32 timescale; ///< Timescale
|
||||
bool atEnd; ///< Are we at the end of this thread?
|
||||
F32 position;
|
||||
};
|
||||
|
|
@ -737,17 +739,6 @@ protected:
|
|||
|
||||
/// @}
|
||||
|
||||
/// @name Invincibility
|
||||
/// @{
|
||||
F32 mInvincibleCount;
|
||||
F32 mInvincibleTime;
|
||||
F32 mInvincibleSpeed;
|
||||
F32 mInvincibleDelta;
|
||||
F32 mInvincibleEffect;
|
||||
F32 mInvincibleFade;
|
||||
bool mInvincibleOn;
|
||||
/// @}
|
||||
|
||||
/// @name Motion
|
||||
/// @{
|
||||
bool mMoveMotion; ///< Indicates that a Move has come in requesting x, y or z motion
|
||||
|
|
@ -912,9 +903,6 @@ protected:
|
|||
|
||||
bool mFlipFadeVal;
|
||||
|
||||
/// Last shield direction (cur. unused)
|
||||
Point3F mShieldNormal;
|
||||
|
||||
/// Camera shake caused by weapon fire.
|
||||
CameraShake *mWeaponCamShake;
|
||||
|
||||
|
|
@ -1115,7 +1103,6 @@ protected:
|
|||
virtual void ejectShellCasing( U32 imageSlot );
|
||||
virtual void updateDamageLevel();
|
||||
virtual void updateDamageState();
|
||||
virtual void blowUp();
|
||||
virtual void onImpact(SceneObject* obj, VectorF vec);
|
||||
virtual void onImpact(VectorF vec);
|
||||
/// @}
|
||||
|
|
@ -1151,11 +1138,9 @@ public:
|
|||
DamageMask = Parent::NextFreeMask << 1,
|
||||
NoWarpMask = Parent::NextFreeMask << 2,
|
||||
CloakMask = Parent::NextFreeMask << 3,
|
||||
ShieldMask = Parent::NextFreeMask << 4,
|
||||
InvincibleMask = Parent::NextFreeMask << 5,
|
||||
SkinMask = Parent::NextFreeMask << 6,
|
||||
MeshHiddenMask = Parent::NextFreeMask << 7,
|
||||
SoundMaskN = Parent::NextFreeMask << 8, ///< Extends + MaxSoundThreads bits
|
||||
SkinMask = Parent::NextFreeMask << 4,
|
||||
MeshHiddenMask = Parent::NextFreeMask << 5,
|
||||
SoundMaskN = Parent::NextFreeMask << 6, ///< Extends + MaxSoundThreads bits
|
||||
ThreadMaskN = SoundMaskN << MaxSoundThreads, ///< Extends + MaxScriptThreads bits
|
||||
ImageMaskN = ThreadMaskN << MaxScriptThreads, ///< Extends + MaxMountedImage bits
|
||||
NextFreeMask = ImageMaskN << MaxMountedImages
|
||||
|
|
@ -1301,6 +1286,9 @@ public:
|
|||
/// Returns the recharge rate
|
||||
F32 getRechargeRate() { return mRechargeRate; }
|
||||
|
||||
/// Makes the shape explode.
|
||||
virtual void blowUp();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Script sounds
|
||||
|
|
@ -1363,14 +1351,6 @@ public:
|
|||
/// @param timescale Timescale
|
||||
bool setThreadTimeScale( U32 slot, F32 timeScale );
|
||||
|
||||
/// Start the sound associated with an animation thread
|
||||
/// @param thread Thread
|
||||
void startSequenceSound(Thread& thread);
|
||||
|
||||
/// Stop the sound associated with an animation thread
|
||||
/// @param thread Thread
|
||||
void stopThreadSound(Thread& thread);
|
||||
|
||||
/// Advance all animation threads attached to this shapebase
|
||||
/// @param dt Change in time from last call to this function
|
||||
void advanceThreads(F32 dt);
|
||||
|
|
@ -1618,7 +1598,7 @@ public:
|
|||
|
||||
/// Returns the eye transform of this shape without including mounted images, IE the eyes of a player
|
||||
/// @param mat Eye transform (out)
|
||||
virtual void getEyeBaseTransform(MatrixF* mat);
|
||||
virtual void getEyeBaseTransform(MatrixF* mat, bool includeBank);
|
||||
|
||||
/// The retraction transform is the muzzle transform in world space.
|
||||
///
|
||||
|
|
@ -1671,7 +1651,7 @@ public:
|
|||
virtual void getRenderMuzzleVector(U32 imageSlot,VectorF* vec);
|
||||
virtual void getRenderMuzzlePoint(U32 imageSlot,Point3F* pos);
|
||||
virtual void getRenderEyeTransform(MatrixF* mat);
|
||||
virtual void getRenderEyeBaseTransform(MatrixF* mat);
|
||||
virtual void getRenderEyeBaseTransform(MatrixF* mat, bool includeBank);
|
||||
/// @}
|
||||
|
||||
|
||||
|
|
@ -1694,26 +1674,6 @@ public:
|
|||
virtual void setWhiteOut(const F32);
|
||||
/// @}
|
||||
|
||||
/// @name Invincibility effect
|
||||
/// This is the screen effect when invincible in the HUD
|
||||
/// @see GameRenderFilters()
|
||||
/// @{
|
||||
|
||||
/// Returns the level of invincibility effect
|
||||
virtual F32 getInvincibleEffect() const;
|
||||
|
||||
/// Initializes invincibility effect and interpolation parameters
|
||||
///
|
||||
/// @param time Time it takes to become invincible
|
||||
/// @param speed Speed at which invincibility effects progress
|
||||
virtual void setupInvincibleEffect(F32 time, F32 speed);
|
||||
|
||||
/// Advance invincibility effect animation
|
||||
/// @param dt Time since last call of this function
|
||||
virtual void updateInvincibleEffect(F32 dt);
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Movement & velocity
|
||||
/// @{
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ ShapeBaseImageData::ShapeBaseImageData()
|
|||
scriptAnimTransitionTime = 0.25f;
|
||||
|
||||
//
|
||||
for (int i = 0; i < MaxStates; i++) {
|
||||
for (S32 i = 0; i < MaxStates; i++) {
|
||||
stateName[i] = 0;
|
||||
|
||||
stateTransitionLoaded[i] = 0;
|
||||
|
|
@ -462,7 +462,10 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr)
|
|||
Torque::FS::FileNodeRef fileRef = Torque::FS::GetFileNode(shape[i].getPath());
|
||||
|
||||
if (!fileRef)
|
||||
{
|
||||
errorStr = String::ToString("ShapeBaseImageData: Couldn't load shape \"%s\"",name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(server)
|
||||
{
|
||||
|
|
@ -686,10 +689,6 @@ void ShapeBaseImageData::initPersistFields()
|
|||
"@see eyeOffset\n\n"
|
||||
"@see animateOnServer\n\n");
|
||||
|
||||
addField( "correctMuzzleVector", TypeBool, Offset(correctMuzzleVector, ShapeBaseImageData),
|
||||
"@brief Flag to adjust the aiming vector to the eye's LOS point.\n\n"
|
||||
"@see ShapeBase::getMuzzleVector()" );
|
||||
|
||||
addField( "correctMuzzleVector", TypeBool, Offset(correctMuzzleVector, ShapeBaseImageData),
|
||||
"@brief Flag to adjust the aiming vector to the eye's LOS point when in 1st person view.\n\n"
|
||||
"@see ShapeBase::getMuzzleVector()" );
|
||||
|
|
@ -1861,7 +1860,7 @@ void ShapeBase::getImageTransform(U32 imageSlot,MatrixF* mat)
|
|||
// We need to animate, even on the server, to make sure the nodes are in the correct location.
|
||||
image.shapeInstance[shapeIndex]->animate();
|
||||
|
||||
getEyeBaseTransform(&nmat);
|
||||
getEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank);
|
||||
|
||||
MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
|
||||
|
||||
|
|
@ -1900,7 +1899,7 @@ void ShapeBase::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat)
|
|||
image.shapeInstance[shapeIndex]->animate();
|
||||
|
||||
MatrixF emat;
|
||||
getEyeBaseTransform(&emat);
|
||||
getEyeBaseTransform(&emat, mDataBlock->mountedImagesBank);
|
||||
|
||||
MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
|
||||
mountTransform.affineInverse();
|
||||
|
|
@ -1985,7 +1984,7 @@ void ShapeBase::getRenderImageTransform( U32 imageSlot, MatrixF* mat, bool noEye
|
|||
|
||||
MatrixF nmat;
|
||||
if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 ) {
|
||||
getRenderEyeBaseTransform(&nmat);
|
||||
getRenderEyeBaseTransform(&nmat, mDataBlock->mountedImagesBank);
|
||||
|
||||
MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
|
||||
|
||||
|
|
@ -2023,7 +2022,7 @@ void ShapeBase::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat)
|
|||
if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 )
|
||||
{
|
||||
MatrixF emat;
|
||||
getRenderEyeBaseTransform(&emat);
|
||||
getRenderEyeBaseTransform(&emat, mDataBlock->mountedImagesBank);
|
||||
|
||||
MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
|
||||
mountTransform.affineInverse();
|
||||
|
|
@ -3061,7 +3060,7 @@ TICKAGAIN:
|
|||
|
||||
if (image.spinThread[i])
|
||||
{
|
||||
float timeScale;
|
||||
F32 timeScale;
|
||||
|
||||
switch (stateData.spin)
|
||||
{
|
||||
|
|
@ -3092,7 +3091,10 @@ TICKAGAIN:
|
|||
}
|
||||
|
||||
if ( image.rDT > 0.0f && image.delayTime > 0.0f && imageData.useRemainderDT && dt != 0.0f )
|
||||
{
|
||||
dt = image.rDT;
|
||||
goto TICKAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3259,7 +3261,7 @@ void ShapeBase::submitLights( LightManager *lm, bool staticLighting )
|
|||
{
|
||||
S32 elapsed = Sim::getCurrentTime() - image.lightStart;
|
||||
if ( elapsed > imageData->lightDuration )
|
||||
return;
|
||||
continue;
|
||||
intensity = ( 1.0 - (F32)elapsed / (F32)imageData->lightDuration ) * imageData->lightBrightness;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ bool Trigger::castRay(const Point3F &start, const Point3F &end, RayInfo* info)
|
|||
F32 const *si = &start.x;
|
||||
F32 const *ei = &end.x;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
for (S32 i = 0; i < 3; i++)
|
||||
{
|
||||
if (*si < *ei)
|
||||
{
|
||||
|
|
@ -259,12 +259,14 @@ ConsoleGetType( TypeTriggerPolyhedron )
|
|||
AssertFatal(currVec == 3, "Internal error: Bad trigger polyhedron");
|
||||
|
||||
// Build output string.
|
||||
char* retBuf = Con::getReturnBuffer(1024);
|
||||
dSprintf(retBuf, 1023, "%7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f",
|
||||
static const U32 bufSize = 1024;
|
||||
char* retBuf = Con::getReturnBuffer(bufSize);
|
||||
dSprintf(retBuf, bufSize, "%7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f %7.7f",
|
||||
origin.x, origin.y, origin.z,
|
||||
vecs[0].x, vecs[0].y, vecs[0].z,
|
||||
vecs[2].x, vecs[2].y, vecs[2].z,
|
||||
vecs[1].x, vecs[1].y, vecs[1].z);
|
||||
|
||||
|
||||
return retBuf;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@
|
|||
#include "materials/materialFeatureTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
using namespace Torque;
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(TSStatic);
|
||||
|
|
@ -440,7 +442,7 @@ void TSStatic::reSkin()
|
|||
Vector<String> skins;
|
||||
String(mSkinNameHandle.getString()).split( ";", skins );
|
||||
|
||||
for (int i = 0; i < skins.size(); i++)
|
||||
for (S32 i = 0; i < skins.size(); i++)
|
||||
{
|
||||
String oldSkin( mAppliedSkinName.c_str() );
|
||||
String newSkin( skins[i] );
|
||||
|
|
@ -523,7 +525,7 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
|
|||
Frustum culler;
|
||||
if ( mMeshCulling )
|
||||
{
|
||||
culler = state->getFrustum();
|
||||
culler = state->getCullingFrustum();
|
||||
MatrixF xfm( true );
|
||||
xfm.scale( Point3F::One / getScale() );
|
||||
xfm.mul( getRenderWorldTransform() );
|
||||
|
|
@ -1036,7 +1038,7 @@ void TSStaticPolysoupConvex::getFeatures(const MatrixF& mat,const VectorF& n, Co
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//These functions are duplicated in tsStatic, shapeBase, and interiorInstance.
|
||||
//These functions are duplicated in tsStatic and shapeBase.
|
||||
//They each function a little differently; but achieve the same purpose of gathering
|
||||
//target names/counts without polluting simObject.
|
||||
|
||||
|
|
@ -1120,8 +1122,8 @@ DefineEngineMethod( TSStatic, changeMaterial, void, ( const char* mapTo, Materia
|
|||
|
||||
newMat->mMapTo = mapTo;
|
||||
|
||||
// Map the material in the in the matmgr
|
||||
MATMGR->mapMaterial( mapTo, newMat->mMapTo );
|
||||
// Map the material by name in the matmgr
|
||||
MATMGR->mapMaterial( mapTo, newMat->getName() );
|
||||
|
||||
// Replace instances with the new material being traded in. Lets make sure that we only
|
||||
// target the specific targets per inst, this is actually doing more than we thought
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ static U32 sScanTypeMask = PlayerObjectType |
|
|||
VehicleObjectType;
|
||||
|
||||
static U32 sAimTypeMask = TerrainObjectType |
|
||||
InteriorObjectType |
|
||||
WaterObjectType |
|
||||
PlayerObjectType |
|
||||
StaticShapeObjectType |
|
||||
|
|
@ -100,7 +99,7 @@ AITurretShapeData::AITurretShapeData()
|
|||
|
||||
weaponLeadVelocity = 0;
|
||||
|
||||
for (int i = 0; i < MaxStates; i++) {
|
||||
for (S32 i = 0; i < MaxStates; i++) {
|
||||
stateName[i] = 0;
|
||||
stateTransitionAtRest[i] = 0;
|
||||
stateTransitionNotAtRest[i] = 0;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ static F32 sMinWarpTicks = 0.5 ; // Fraction of tick at which instant war
|
|||
static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
||||
|
||||
const U32 sClientCollisionMask = (TerrainObjectType |
|
||||
InteriorObjectType | StaticShapeObjectType |
|
||||
StaticShapeObjectType |
|
||||
VehicleObjectType);
|
||||
|
||||
const U32 sServerCollisionMask = (sClientCollisionMask);
|
||||
|
|
@ -1270,7 +1270,7 @@ void TurretShape::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat)
|
|||
image.shapeInstance[shapeIndex]->animate();
|
||||
|
||||
MatrixF emat;
|
||||
getEyeBaseTransform(&emat);
|
||||
getEyeBaseTransform(&emat, mDataBlock->mountedImagesBank);
|
||||
|
||||
MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
|
||||
mountTransform.affineInverse();
|
||||
|
|
@ -1318,7 +1318,7 @@ void TurretShape::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat)
|
|||
if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 )
|
||||
{
|
||||
MatrixF emat;
|
||||
getRenderEyeBaseTransform(&emat);
|
||||
getRenderEyeBaseTransform(&emat, mDataBlock->mountedImagesBank);
|
||||
|
||||
MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
|
||||
mountTransform.affineInverse();
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
const static U32 sCollisionMoveMask = ( TerrainObjectType | InteriorObjectType |
|
||||
WaterObjectType | PlayerObjectType |
|
||||
StaticShapeObjectType | VehicleObjectType |
|
||||
VehicleBlockerObjectType );
|
||||
const static U32 sCollisionMoveMask = ( TerrainObjectType | WaterObjectType |
|
||||
PlayerObjectType | StaticShapeObjectType |
|
||||
VehicleObjectType | VehicleBlockerObjectType );
|
||||
|
||||
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
|
||||
static U32 sClientCollisionMask = sCollisionMoveMask;
|
||||
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ namespace {
|
|||
const U32 sIntergrationsPerTick = 1;
|
||||
const F32 sHoverVehicleGravity = -20;
|
||||
|
||||
const U32 sCollisionMoveMask = (TerrainObjectType | InteriorObjectType |
|
||||
PlayerObjectType | StaticShapeObjectType |
|
||||
VehicleObjectType | VehicleBlockerObjectType);
|
||||
const U32 sCollisionMoveMask = (TerrainObjectType | PlayerObjectType |
|
||||
StaticShapeObjectType | VehicleObjectType |
|
||||
VehicleBlockerObjectType);
|
||||
|
||||
const U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
|
||||
const U32 sClientCollisionMask = sCollisionMoveMask;
|
||||
|
|
@ -724,7 +724,7 @@ void HoverVehicle::updateForces(F32 /*dt*/)
|
|||
for (j = 0; j < 2; j++) {
|
||||
if (getContainer()->castRay(stabPoints[j].wsPoint, stabPoints[j].wsPoint + stabPoints[j].wsExtension * 2.0,
|
||||
TerrainObjectType |
|
||||
InteriorObjectType | WaterObjectType, &rinfo))
|
||||
WaterObjectType, &rinfo))
|
||||
{
|
||||
reallyFloating = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ const F32 sVehicleGravity = -20;
|
|||
|
||||
// Physics and collision constants
|
||||
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
|
||||
static int sRestCount = 10; // Consecutive ticks before comming to rest
|
||||
static S32 sRestCount = 10; // Consecutive ticks before comming to rest
|
||||
|
||||
} // namespace {}
|
||||
|
||||
|
|
@ -172,6 +172,10 @@ VehicleData::VehicleData()
|
|||
jetEnergyDrain = 0.8f;
|
||||
minJetEnergy = 1;
|
||||
|
||||
steeringReturn = 0.0f;
|
||||
steeringReturnSpeedScale = 0.01f;
|
||||
powerSteering = false;
|
||||
|
||||
for (S32 i = 0; i < Body::MaxSounds; i++)
|
||||
body.sound[i] = 0;
|
||||
|
||||
|
|
@ -214,6 +218,7 @@ bool VehicleData::preload(bool server, String &errorStr)
|
|||
if (!collisionDetails.size() || collisionDetails[0] == -1)
|
||||
{
|
||||
Con::errorf("VehicleData::preload failed: Vehicle models must define a collision-1 detail");
|
||||
errorStr = String::ToString("VehicleData: Couldn't load shape \"%s\"",shapeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -292,6 +297,10 @@ void VehicleData::packData(BitStream* stream)
|
|||
stream->write(jetEnergyDrain);
|
||||
stream->write(minJetEnergy);
|
||||
|
||||
stream->write(steeringReturn);
|
||||
stream->write(steeringReturnSpeedScale);
|
||||
stream->writeFlag(powerSteering);
|
||||
|
||||
stream->writeFlag(cameraRoll);
|
||||
stream->write(cameraLag);
|
||||
stream->write(cameraDecay);
|
||||
|
|
@ -333,14 +342,14 @@ void VehicleData::packData(BitStream* stream)
|
|||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < VC_NUM_DAMAGE_EMITTER_AREAS; j++)
|
||||
for (S32 j = 0; j < VC_NUM_DAMAGE_EMITTER_AREAS; j++)
|
||||
{
|
||||
stream->write( damageEmitterOffset[j].x );
|
||||
stream->write( damageEmitterOffset[j].y );
|
||||
stream->write( damageEmitterOffset[j].z );
|
||||
}
|
||||
|
||||
for (int k = 0; k < VC_NUM_DAMAGE_LEVELS; k++)
|
||||
for (S32 k = 0; k < VC_NUM_DAMAGE_LEVELS; k++)
|
||||
{
|
||||
stream->write( damageLevelTolerance[k] );
|
||||
}
|
||||
|
|
@ -384,6 +393,10 @@ void VehicleData::unpackData(BitStream* stream)
|
|||
stream->read(&jetEnergyDrain);
|
||||
stream->read(&minJetEnergy);
|
||||
|
||||
stream->read(&steeringReturn);
|
||||
stream->read(&steeringReturnSpeedScale);
|
||||
powerSteering = stream->readFlag();
|
||||
|
||||
cameraRoll = stream->readFlag();
|
||||
stream->read(&cameraLag);
|
||||
stream->read(&cameraDecay);
|
||||
|
|
@ -428,14 +441,14 @@ void VehicleData::unpackData(BitStream* stream)
|
|||
}
|
||||
}
|
||||
|
||||
for( int j=0; j<VC_NUM_DAMAGE_EMITTER_AREAS; j++ )
|
||||
for( S32 j=0; j<VC_NUM_DAMAGE_EMITTER_AREAS; j++ )
|
||||
{
|
||||
stream->read( &damageEmitterOffset[j].x );
|
||||
stream->read( &damageEmitterOffset[j].y );
|
||||
stream->read( &damageEmitterOffset[j].z );
|
||||
}
|
||||
|
||||
for( int k=0; k<VC_NUM_DAMAGE_LEVELS; k++ )
|
||||
for( S32 k=0; k<VC_NUM_DAMAGE_LEVELS; k++ )
|
||||
{
|
||||
stream->read( &damageLevelTolerance[k] );
|
||||
}
|
||||
|
|
@ -462,6 +475,13 @@ void VehicleData::initPersistFields()
|
|||
addField( "minJetEnergy", TypeF32, Offset(minJetEnergy, VehicleData),
|
||||
"Minimum vehicle energy level to begin jetting." );
|
||||
|
||||
addField( "steeringReturn", TypeF32, Offset(steeringReturn, VehicleData),
|
||||
"Rate at which the vehicle's steering returns to forwards when it is moving." );
|
||||
addField( "steeringReturnSpeedScale", TypeF32, Offset(steeringReturnSpeedScale, VehicleData),
|
||||
"Amount of effect the vehicle's speed has on its rate of steering return." );
|
||||
addField( "powerSteering", TypeBool, Offset(powerSteering, VehicleData),
|
||||
"If true, steering does not auto-centre while the vehicle is being steered by its driver." );
|
||||
|
||||
addField( "massCenter", TypePoint3F, Offset(massCenter, VehicleData),
|
||||
"Defines the vehicle's center of mass (offset from the origin of the model)." );
|
||||
addField( "massBox", TypePoint3F, Offset(massBox, VehicleData),
|
||||
|
|
@ -699,7 +719,7 @@ bool Vehicle::onAdd()
|
|||
{
|
||||
if( mDataBlock->dustEmitter )
|
||||
{
|
||||
for( int i=0; i<VehicleData::VC_NUM_DUST_EMITTERS; i++ )
|
||||
for( S32 i=0; i<VehicleData::VC_NUM_DUST_EMITTERS; i++ )
|
||||
{
|
||||
mDustEmitterList[i] = new ParticleEmitter;
|
||||
mDustEmitterList[i]->onNewDataBlock( mDataBlock->dustEmitter, false );
|
||||
|
|
@ -1085,6 +1105,22 @@ void Vehicle::updateMove(const Move* move)
|
|||
mSteering.y = 0;
|
||||
}
|
||||
|
||||
// Steering return
|
||||
if(mDataBlock->steeringReturn > 0.0f &&
|
||||
(!mDataBlock->powerSteering || (move->yaw == 0.0f && move->pitch == 0.0f)))
|
||||
{
|
||||
Point2F returnAmount(mSteering.x * mDataBlock->steeringReturn * TickSec,
|
||||
mSteering.y * mDataBlock->steeringReturn * TickSec);
|
||||
if(mDataBlock->steeringReturnSpeedScale > 0.0f)
|
||||
{
|
||||
Point3F vel;
|
||||
mWorldToObj.mulV(getVelocity(), &vel);
|
||||
returnAmount += Point2F(mSteering.x * vel.y * mDataBlock->steeringReturnSpeedScale * TickSec,
|
||||
mSteering.y * vel.y * mDataBlock->steeringReturnSpeedScale * TickSec);
|
||||
}
|
||||
mSteering -= returnAmount;
|
||||
}
|
||||
|
||||
// Jetting flag
|
||||
if (move->trigger[3]) {
|
||||
if (!mJetting && getEnergyLevel() >= mDataBlock->minJetEnergy)
|
||||
|
|
@ -1769,7 +1805,7 @@ void Vehicle::updateDamageSmoke( F32 dt )
|
|||
F32 damagePercent = mDamage / mDataBlock->maxDamage;
|
||||
if( damagePercent >= mDataBlock->damageLevelTolerance[j] )
|
||||
{
|
||||
for( int i=0; i<mDataBlock->numDmgEmitterAreas; i++ )
|
||||
for( S32 i=0; i<mDataBlock->numDmgEmitterAreas; i++ )
|
||||
{
|
||||
MatrixF trans = getTransform();
|
||||
Point3F offset = mDataBlock->damageEmitterOffset[i];
|
||||
|
|
@ -1900,7 +1936,7 @@ void Vehicle::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *st
|
|||
GFX->getDrawUtil()->drawCube(desc, Point3F(0.1f,0.1f,0.1f),mDataBlock->massCenter, ColorI(255, 255, 255), &mRenderObjToWorld);
|
||||
|
||||
// Now render all the contact points.
|
||||
for (int i = 0; i < mCollisionList.getCount(); i++)
|
||||
for (S32 i = 0; i < mCollisionList.getCount(); i++)
|
||||
{
|
||||
const Collision& collision = mCollisionList[i];
|
||||
GFX->getDrawUtil()->drawCube(desc, Point3F(0.05f,0.05f,0.05f),collision.point, ColorI(0, 0, 255));
|
||||
|
|
@ -1908,7 +1944,7 @@ void Vehicle::_renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *st
|
|||
|
||||
// Finally render the normals as one big batch.
|
||||
PrimBuild::begin(GFXLineList, mCollisionList.getCount() * 2);
|
||||
for (int i = 0; i < mCollisionList.getCount(); i++)
|
||||
for (S32 i = 0; i < mCollisionList.getCount(); i++)
|
||||
{
|
||||
const Collision& collision = mCollisionList[i];
|
||||
PrimBuild::color3f(1, 1, 1);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ struct VehicleData: public ShapeBaseData
|
|||
F32 jetEnergyDrain; ///< Energy drain/tick
|
||||
F32 minJetEnergy;
|
||||
|
||||
F32 steeringReturn;
|
||||
F32 steeringReturnSpeedScale;
|
||||
bool powerSteering;
|
||||
|
||||
ParticleEmitterData * dustEmitter;
|
||||
S32 dustID;
|
||||
F32 triggerDustHeight; ///< height vehicle has to be under to kick up dust
|
||||
|
|
@ -198,7 +202,7 @@ class Vehicle: public ShapeBase
|
|||
CollisionList mContacts;
|
||||
Rigid mRigid;
|
||||
ShapeBaseConvex mConvex;
|
||||
int restCount;
|
||||
S32 restCount;
|
||||
|
||||
SimObjectPtr<ParticleEmitter> mDustEmitterList[VehicleData::VC_NUM_DUST_EMITTERS];
|
||||
SimObjectPtr<ParticleEmitter> mDamageEmitterList[VehicleData::VC_NUM_DAMAGE_EMITTERS];
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ bool VehicleBlocker::onAdd()
|
|||
|
||||
mObjBox.minExtents.set(-mDimensions.x, -mDimensions.y, 0);
|
||||
mObjBox.maxExtents.set( mDimensions.x, mDimensions.y, mDimensions.z);
|
||||
if( !mObjBox.isValidBox() )
|
||||
{
|
||||
Con::errorf("VehicleBlocker::onAdd - Fail - No valid object box");
|
||||
return false;
|
||||
}
|
||||
|
||||
resetWorldBox();
|
||||
setRenderTransform(mObjToWorld);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,12 +47,12 @@
|
|||
#include "lighting/lightQuery.h"
|
||||
|
||||
|
||||
// Collision masks are used to determin what type of objects the
|
||||
// Collision masks are used to determine what type of objects the
|
||||
// wheeled vehicle will collide with.
|
||||
static U32 sClientCollisionMask =
|
||||
TerrainObjectType | InteriorObjectType |
|
||||
PlayerObjectType | StaticShapeObjectType |
|
||||
VehicleObjectType | VehicleBlockerObjectType;
|
||||
TerrainObjectType | PlayerObjectType |
|
||||
StaticShapeObjectType | VehicleObjectType |
|
||||
VehicleBlockerObjectType;
|
||||
|
||||
// Gravity constant
|
||||
static F32 sWheeledVehicleGravity = -20;
|
||||
|
|
|
|||
|
|
@ -23,10 +23,6 @@
|
|||
#ifndef _AUTH_H_
|
||||
#define _AUTH_H_
|
||||
|
||||
#ifndef _EVENT_H_
|
||||
#include "platform/event.h"
|
||||
#endif
|
||||
|
||||
/// Formerly contained a certificate, showing that something was valid.
|
||||
class Auth2Certificate
|
||||
{
|
||||
|
|
|
|||
|
|
@ -241,6 +241,16 @@ void StandardMainLoop::init()
|
|||
DebugOutputConsumer::init();
|
||||
#endif
|
||||
|
||||
// init Filesystem first, so we can actually log errors for all components that follow
|
||||
Platform::FS::InstallFileSystems(); // install all drives for now until we have everything using the volume stuff
|
||||
Platform::FS::MountDefaults();
|
||||
|
||||
// Set our working directory.
|
||||
Torque::FS::SetCwd( "game:/" );
|
||||
|
||||
// Set our working directory.
|
||||
Platform::setCurrentDirectory( Platform::getMainDotCsDir() );
|
||||
|
||||
Processor::init();
|
||||
Math::init();
|
||||
Platform::init(); // platform specific initialization
|
||||
|
|
@ -291,6 +301,9 @@ void StandardMainLoop::init()
|
|||
tm = new TimeManager;
|
||||
tm->timeEvent.notify(&::processTimeEvent);
|
||||
|
||||
// Start up the Input Event Manager
|
||||
INPUTMGR->start();
|
||||
|
||||
Sampler::init();
|
||||
|
||||
// Hook in for UDP notification
|
||||
|
|
@ -307,6 +320,9 @@ void StandardMainLoop::init()
|
|||
|
||||
void StandardMainLoop::shutdown()
|
||||
{
|
||||
// Stop the Input Event Manager
|
||||
INPUTMGR->stop();
|
||||
|
||||
delete tm;
|
||||
preShutdown();
|
||||
|
||||
|
|
@ -380,15 +396,6 @@ bool StandardMainLoop::handleCommandLine( S32 argc, const char **argv )
|
|||
for (i = 0; i < argc; i++)
|
||||
Con::setVariable(avar("Game::argv%d", i), argv[i]);
|
||||
|
||||
Platform::FS::InstallFileSystems(); // install all drives for now until we have everything using the volume stuff
|
||||
Platform::FS::MountDefaults();
|
||||
|
||||
// Set our working directory.
|
||||
Torque::FS::SetCwd( "game:/" );
|
||||
|
||||
// Set our working directory.
|
||||
Platform::setCurrentDirectory( Platform::getMainDotCsDir() );
|
||||
|
||||
#ifdef TORQUE_PLAYER
|
||||
if(argc > 2 && dStricmp(argv[1], "-project") == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include "app/net/httpObject.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/event.h"
|
||||
#include "core/stream/fileStream.h"
|
||||
#include "console/simBase.h"
|
||||
#include "console/consoleInternal.h"
|
||||
|
|
@ -299,7 +298,7 @@ void HTTPObject::onDisconnect()
|
|||
Parent::onDisconnect();
|
||||
}
|
||||
|
||||
bool HTTPObject::processLine(U8 *line)
|
||||
bool HTTPObject::processLine(UTF8 *line)
|
||||
{
|
||||
if(mParseState == ParsingStatusLine)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ public:
|
|||
virtual void onConnected();
|
||||
virtual void onConnectFailed();
|
||||
virtual void onDisconnect();
|
||||
bool processLine(U8 *line);
|
||||
bool processLine(UTF8 *line);
|
||||
|
||||
DECLARE_CONOBJECT(HTTPObject);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,27 +31,14 @@
|
|||
#include "sim/netObject.h"
|
||||
#include "app/net/serverQuery.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
#include <vector>
|
||||
#include "net.h"
|
||||
//----------------------------------------------------------------
|
||||
// remote procedure call console functions
|
||||
//----------------------------------------------------------------
|
||||
|
||||
class RemoteCommandEvent : public NetEvent
|
||||
{
|
||||
public:
|
||||
typedef NetEvent Parent;
|
||||
enum {
|
||||
MaxRemoteCommandArgs = 20,
|
||||
CommandArgsBits = 5
|
||||
};
|
||||
|
||||
private:
|
||||
S32 mArgc;
|
||||
char *mArgv[MaxRemoteCommandArgs + 1];
|
||||
NetStringHandle mTagv[MaxRemoteCommandArgs + 1];
|
||||
static char mBuf[1024];
|
||||
public:
|
||||
RemoteCommandEvent(S32 argc=0, const char **argv=NULL, NetConnection *conn = NULL)
|
||||
RemoteCommandEvent::RemoteCommandEvent(S32 argc, const char **argv, NetConnection *conn)
|
||||
{
|
||||
mArgc = argc;
|
||||
for(S32 i = 0; i < argc; i++)
|
||||
|
|
@ -73,7 +60,7 @@ public:
|
|||
}
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET
|
||||
const char *getDebugName()
|
||||
const char *RemoteCommandEvent::getDebugName()
|
||||
{
|
||||
static char buffer[256];
|
||||
dSprintf(buffer, sizeof(buffer), "%s [%s]", getClassName(), mTagv[1].isValidString() ? mTagv[1].getString() : "--unknown--" );
|
||||
|
|
@ -81,13 +68,13 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
~RemoteCommandEvent()
|
||||
RemoteCommandEvent::~RemoteCommandEvent()
|
||||
{
|
||||
for(S32 i = 0; i < mArgc; i++)
|
||||
dFree(mArgv[i+1]);
|
||||
}
|
||||
|
||||
virtual void pack(NetConnection* conn, BitStream *bstream)
|
||||
void RemoteCommandEvent::pack(NetConnection* conn, BitStream *bstream)
|
||||
{
|
||||
bstream->writeInt(mArgc, CommandArgsBits);
|
||||
// write it out reversed... why?
|
||||
|
|
@ -98,12 +85,12 @@ public:
|
|||
conn->packString(bstream, mArgv[i+1]);
|
||||
}
|
||||
|
||||
virtual void write(NetConnection* conn, BitStream *bstream)
|
||||
void RemoteCommandEvent::write(NetConnection* conn, BitStream *bstream)
|
||||
{
|
||||
pack(conn, bstream);
|
||||
}
|
||||
|
||||
virtual void unpack(NetConnection* conn, BitStream *bstream)
|
||||
void RemoteCommandEvent::unpack(NetConnection* conn, BitStream *bstream)
|
||||
{
|
||||
|
||||
mArgc = bstream->readInt(CommandArgsBits);
|
||||
|
|
@ -115,7 +102,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void process(NetConnection *conn)
|
||||
void RemoteCommandEvent::process(NetConnection *conn)
|
||||
{
|
||||
static char idBuf[10];
|
||||
|
||||
|
|
@ -165,8 +152,52 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
DECLARE_CONOBJECT(RemoteCommandEvent);
|
||||
};
|
||||
void RemoteCommandEvent::sendRemoteCommand(NetConnection *conn, S32 argc, const char **argv)
|
||||
{
|
||||
if(U8(argv[0][0]) != StringTagPrefixByte)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::Script, "Remote Command Error - command must be a tag.");
|
||||
return;
|
||||
}
|
||||
S32 i;
|
||||
for(i = argc - 1; i >= 0; i--)
|
||||
{
|
||||
if(argv[i][0] != 0)
|
||||
break;
|
||||
argc = i;
|
||||
}
|
||||
for(i = 0; i < argc; i++)
|
||||
conn->validateSendString(argv[i]);
|
||||
RemoteCommandEvent *cevt = new RemoteCommandEvent(argc, argv, conn);
|
||||
conn->postNetEvent(cevt);
|
||||
}
|
||||
|
||||
const char* RemoteCommandEvent::getTaggedString(const char* tag)
|
||||
{
|
||||
const char *indexPtr = tag;
|
||||
if (*indexPtr == StringTagPrefixByte)
|
||||
indexPtr++;
|
||||
return gNetStringTable->lookupString(dAtoi(indexPtr));
|
||||
}
|
||||
|
||||
void RemoteCommandEvent::removeTaggedString(S32 tag)
|
||||
{
|
||||
if (tag)
|
||||
gNetStringTable->removeString(tag, true);
|
||||
}
|
||||
|
||||
const char* RemoteCommandEvent::addTaggedString(const char* str)
|
||||
{
|
||||
NetStringHandle s(str);
|
||||
gNetStringTable->incStringRefScript(s.getIndex());
|
||||
|
||||
char *ret = Con::getReturnBuffer(10);
|
||||
ret[0] = StringTagPrefixByte;
|
||||
dSprintf(ret + 1, 9, "%d", s.getIndex());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
char RemoteCommandEvent::mBuf[1024];
|
||||
|
||||
IMPLEMENT_CO_NETEVENT_V1(RemoteCommandEvent);
|
||||
|
|
@ -176,30 +207,13 @@ ConsoleDocClass( RemoteCommandEvent,
|
|||
"Not intended for game development, for exposing ConsoleFunctions (such as commandToClient) only.\n\n"
|
||||
"@internal");
|
||||
|
||||
static void sendRemoteCommand(NetConnection *conn, S32 argc, const char **argv)
|
||||
{
|
||||
if(U8(argv[0][0]) != StringTagPrefixByte)
|
||||
{
|
||||
Con::errorf(ConsoleLogEntry::Script, "Remote Command Error - command must be a tag.");
|
||||
return;
|
||||
}
|
||||
S32 i;
|
||||
for(i = argc - 1; i >= 0; i--)
|
||||
{
|
||||
if(argv[i][0] != 0)
|
||||
break;
|
||||
argc = i;
|
||||
}
|
||||
for(i = 0; i < argc; i++)
|
||||
conn->validateSendString(argv[i]);
|
||||
RemoteCommandEvent *cevt = new RemoteCommandEvent(argc, argv, conn);
|
||||
conn->postNetEvent(cevt);
|
||||
}
|
||||
|
||||
|
||||
ConsoleFunctionGroupBegin( Net, "Functions for use with the network; tagged strings and remote commands.");
|
||||
|
||||
|
||||
ConsoleFunction( commandToServer, void, 2, RemoteCommandEvent::MaxRemoteCommandArgs + 1, "(string func, ...)"
|
||||
"@brief Send a command to the server.\n\n"
|
||||
"@brief Send a command to the server.\n\n"
|
||||
|
||||
"@param func Name of the server command being called\n"
|
||||
"@param ... Various parameters being passed to server command\n\n"
|
||||
|
|
@ -237,9 +251,8 @@ ConsoleFunction( commandToServer, void, 2, RemoteCommandEvent::MaxRemoteCommandA
|
|||
NetConnection *conn = NetConnection::getConnectionToServer();
|
||||
if(!conn)
|
||||
return;
|
||||
|
||||
StringStackWrapper args(argc - 1, argv + 1);
|
||||
sendRemoteCommand(conn, args.count(), args);
|
||||
RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
|
||||
}
|
||||
|
||||
ConsoleFunction( commandToClient, void, 3, RemoteCommandEvent::MaxRemoteCommandArgs + 2, "(NetConnection client, string func, ...)"
|
||||
|
|
@ -277,11 +290,14 @@ ConsoleFunction( commandToClient, void, 3, RemoteCommandEvent::MaxRemoteCommandA
|
|||
if(!Sim::findObject(argv[1], conn))
|
||||
return;
|
||||
StringStackWrapper args(argc - 2, argv + 2);
|
||||
sendRemoteCommand(conn, args.count(), args);
|
||||
RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
|
||||
}
|
||||
|
||||
|
||||
ConsoleFunction(removeTaggedString, void, 2, 2, "(int tag)"
|
||||
|
||||
|
||||
|
||||
DefineEngineFunction(removeTaggedString, void, (S32 tag), (-1),
|
||||
"@brief Remove a tagged string from the Net String Table\n\n"
|
||||
|
||||
"@param tag The tag associated with the string\n\n"
|
||||
|
|
@ -290,11 +306,12 @@ ConsoleFunction(removeTaggedString, void, 2, 2, "(int tag)"
|
|||
"@see addTaggedString()\n"
|
||||
"@see getTaggedString()\n"
|
||||
"@ingroup Networking\n")
|
||||
{
|
||||
gNetStringTable->removeString(dAtoi(((const char*)argv[1])+1), true);
|
||||
}
|
||||
{
|
||||
RemoteCommandEvent::removeTaggedString(tag);
|
||||
}
|
||||
|
||||
ConsoleFunction( addTaggedString, const char*, 2, 2, "(string str)"
|
||||
|
||||
DefineEngineFunction(addTaggedString, const char* , (const char* str), (""),
|
||||
"@brief Use the addTaggedString function to tag a new string and add it to the NetStringTable\n\n"
|
||||
|
||||
"@param str The string to be tagged and placed in the NetStringTable. Tagging ignores case, "
|
||||
|
|
@ -306,17 +323,12 @@ ConsoleFunction( addTaggedString, const char*, 2, 2, "(string str)"
|
|||
"@see removeTaggedString()\n"
|
||||
"@see getTaggedString()\n"
|
||||
"@ingroup Networking\n")
|
||||
{
|
||||
NetStringHandle s((const char*)argv[1]);
|
||||
gNetStringTable->incStringRefScript(s.getIndex());
|
||||
{
|
||||
return RemoteCommandEvent::addTaggedString(str);
|
||||
}
|
||||
|
||||
char *ret = Con::getReturnBuffer(10);
|
||||
ret[0] = StringTagPrefixByte;
|
||||
dSprintf(ret + 1, 9, "%d", s.getIndex());
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConsoleFunction( getTaggedString, const char*, 2, 2, "(int tag)"
|
||||
DefineEngineFunction(getTaggedString, const char* , (const char *tag), (""),
|
||||
"@brief Use the getTaggedString function to convert a tag to a string.\n\n"
|
||||
|
||||
"This is not the same as detag() which can only be used within the context "
|
||||
|
|
@ -331,12 +343,11 @@ ConsoleFunction( getTaggedString, const char*, 2, 2, "(int tag)"
|
|||
"@see addTaggedString()\n"
|
||||
"@see removeTaggedString()\n"
|
||||
"@ingroup Networking\n")
|
||||
{
|
||||
const char *indexPtr = argv[1];
|
||||
if (*indexPtr == StringTagPrefixByte)
|
||||
indexPtr++;
|
||||
return gNetStringTable->lookupString(dAtoi(indexPtr));
|
||||
}
|
||||
{
|
||||
return RemoteCommandEvent::getTaggedString(tag);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ConsoleFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)"
|
||||
"@brief Build a string using the specified tagged string format.\n\n"
|
||||
|
|
@ -373,10 +384,11 @@ ConsoleFunction( buildTaggedString, const char*, 2, 11, "(string format, ...)"
|
|||
if (*indexPtr == StringTagPrefixByte)
|
||||
indexPtr++;
|
||||
const char *fmtString = gNetStringTable->lookupString(dAtoi(indexPtr));
|
||||
char *strBuffer = Con::getReturnBuffer(512);
|
||||
static const U32 bufSize = 512;
|
||||
char *strBuffer = Con::getReturnBuffer(bufSize);
|
||||
const char *fmtStrPtr = fmtString;
|
||||
char *strBufPtr = strBuffer;
|
||||
S32 strMaxLength = 511;
|
||||
S32 strMaxLength = bufSize - 1;
|
||||
if (!fmtString)
|
||||
goto done;
|
||||
|
||||
|
|
|
|||
59
Engine/source/app/net/net.h
Normal file
59
Engine/source/app/net/net.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef _NET_H_
|
||||
#define _NET_H_
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "core/dnet.h"
|
||||
#include "core/idGenerator.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "console/simBase.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "sim/netConnection.h"
|
||||
#include "sim/netObject.h"
|
||||
#include "app/net/serverQuery.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
class RemoteCommandEvent : public NetEvent
|
||||
{
|
||||
public:
|
||||
typedef NetEvent Parent;
|
||||
enum {
|
||||
MaxRemoteCommandArgs = 20,
|
||||
CommandArgsBits = 5
|
||||
};
|
||||
|
||||
private:
|
||||
S32 mArgc;
|
||||
char *mArgv[MaxRemoteCommandArgs + 1];
|
||||
NetStringHandle mTagv[MaxRemoteCommandArgs + 1];
|
||||
static char mBuf[1024];
|
||||
|
||||
public:
|
||||
RemoteCommandEvent(S32 argc=0, const char **argv=NULL, NetConnection *conn = NULL);
|
||||
|
||||
#ifdef TORQUE_DEBUG_NET
|
||||
const char *getDebugName();
|
||||
#endif
|
||||
|
||||
~RemoteCommandEvent();
|
||||
|
||||
virtual void pack(NetConnection* conn, BitStream *bstream);
|
||||
|
||||
virtual void write(NetConnection* conn, BitStream *bstream);
|
||||
|
||||
virtual void unpack(NetConnection* conn, BitStream *bstream);
|
||||
|
||||
virtual void process(NetConnection *conn);
|
||||
|
||||
static void sendRemoteCommand(NetConnection *conn, S32 argc, const char **argv);
|
||||
|
||||
static void removeTaggedString(S32);
|
||||
|
||||
static const char* addTaggedString(const char* str);
|
||||
|
||||
static const char* getTaggedString(const char* tag);
|
||||
|
||||
DECLARE_CONOBJECT(RemoteCommandEvent);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#include "platform/platform.h"
|
||||
#include "console/simBase.h"
|
||||
#include "platform/event.h"
|
||||
#include "sim/netConnection.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "sim/netObject.h"
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@
|
|||
#include "app/net/serverQuery.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/event.h"
|
||||
#include "core/dnet.h"
|
||||
#include "core/util/tVector.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@
|
|||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _EVENT_H_
|
||||
#include "platform/event.h"
|
||||
#endif
|
||||
#ifndef _BITSET_H_
|
||||
#include "core/bitSet.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include "app/net/tcpObject.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/event.h"
|
||||
#include "console/simBase.h"
|
||||
#include "console/consoleInternal.h"
|
||||
#include "core/strings/stringUnit.h"
|
||||
|
|
@ -422,7 +421,7 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),,
|
|||
object->send( (const U8*)data, dStrlen(data) );
|
||||
}
|
||||
|
||||
DefineEngineMethod(TCPObject, listen, void, (int port),,
|
||||
DefineEngineMethod(TCPObject, listen, void, (U32 port),,
|
||||
"@brief Start listening on the specified port for connections.\n\n"
|
||||
|
||||
"This method starts a listener which looks for incoming TCP connections to a port. "
|
||||
|
|
|
|||
|
|
@ -25,23 +25,35 @@
|
|||
#include "console/console.h"
|
||||
|
||||
static const U32 csgVersionNumber = TORQUE_GAME_ENGINE;
|
||||
static const U32 appVersionNumber = TORQUE_APP_VERSION;
|
||||
|
||||
U32 getVersionNumber()
|
||||
{
|
||||
return csgVersionNumber;
|
||||
}
|
||||
|
||||
U32 getAppVersionNumber()
|
||||
{
|
||||
return appVersionNumber;
|
||||
}
|
||||
|
||||
const char* getVersionString()
|
||||
{
|
||||
return TORQUE_GAME_ENGINE_VERSION_STRING;
|
||||
}
|
||||
|
||||
const char* getAppVersionString()
|
||||
{
|
||||
return TORQUE_APP_VERSION_STRING;
|
||||
}
|
||||
|
||||
/// TGE 0001
|
||||
/// TGEA 0002
|
||||
/// TGB 0003
|
||||
/// TGEA 360 0004
|
||||
/// TGE WII 0005
|
||||
/// Torque 3D 0006
|
||||
/// Torque 3D MIT 0007
|
||||
|
||||
const char* getEngineProductString()
|
||||
{
|
||||
|
|
@ -62,7 +74,9 @@ const char* getEngineProductString()
|
|||
return "Torque for Wii";
|
||||
case 0006:
|
||||
return "Torque 3D";
|
||||
|
||||
case 0007:
|
||||
return "Torque 3D MIT";
|
||||
|
||||
default:
|
||||
return "Torque Engine";
|
||||
};
|
||||
|
|
@ -77,18 +91,31 @@ const char* getCompileTimeString()
|
|||
|
||||
ConsoleFunctionGroupBegin( CompileInformation, "Functions to get version information about the current executable." );
|
||||
|
||||
ConsoleFunction( getVersionNumber, S32, 1, 1, "Get the version of the build, as a string.\n\n"
|
||||
ConsoleFunction( getVersionNumber, S32, 1, 1, "Get the version of the engine build, as a string.\n\n"
|
||||
"@ingroup Debugging")
|
||||
{
|
||||
return getVersionNumber();
|
||||
}
|
||||
|
||||
ConsoleFunction( getVersionString, const char*, 1, 1, "Get the version of the build, as a string.\n\n"
|
||||
ConsoleFunction( getAppVersionNumber, S32, 1, 1, "Get the version of the application build, as a string.\n\n"
|
||||
"@ingroup Debugging")
|
||||
{
|
||||
return getAppVersionNumber();
|
||||
}
|
||||
|
||||
|
||||
ConsoleFunction( getVersionString, const char*, 1, 1, "Get the version of the engine build, as a human readable string.\n\n"
|
||||
"@ingroup Debugging")
|
||||
{
|
||||
return getVersionString();
|
||||
}
|
||||
|
||||
ConsoleFunction( getAppVersionString, const char*, 1, 1, "Get the version of the aplication, as a human readable string.\n\n"
|
||||
"@ingroup Debugging")
|
||||
{
|
||||
return getAppVersionString();
|
||||
}
|
||||
|
||||
ConsoleFunction( getEngineName, const char*, 1, 1, "Get the name of the engine product that this is running from, as a string.\n\n"
|
||||
"@ingroup Debugging")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,23 +23,41 @@
|
|||
#ifndef _VERSION_H_
|
||||
#define _VERSION_H_
|
||||
|
||||
/// Since we can build different engine "products" out of the same
|
||||
/// base engine source we need a way to differentiate which product
|
||||
/// this particular game is using.
|
||||
///
|
||||
/// TGE 0001
|
||||
/// TGEA 0002
|
||||
/// TGB 0003
|
||||
/// TGEA 360 0004
|
||||
/// TGE WII 0005
|
||||
/// Torque 3D 0006
|
||||
/// Torque 3D MIT 0007
|
||||
#define TORQUE_ENGINE_PRODUCT 0007
|
||||
|
||||
/// This is our global version number for the engine source code that
|
||||
/// we are using. See <game>/source/torqueConfig.h for the game's source
|
||||
/// code version, the game name, and which type of game it is (TGB, TGE, TGEA, etc.).
|
||||
///
|
||||
/// Version number is major * 1000 + minor * 100 + revision * 10.
|
||||
#define TORQUE_GAME_ENGINE 1100
|
||||
#define TORQUE_GAME_ENGINE 3610
|
||||
|
||||
/// Human readable engine version string.
|
||||
#define TORQUE_GAME_ENGINE_VERSION_STRING "2011"
|
||||
#define TORQUE_GAME_ENGINE_VERSION_STRING "3.6.1"
|
||||
|
||||
/// Gets the specified version number. The version number is specified as a global in version.cc
|
||||
/// Gets the engine version number. The version number is specified as a global in version.cc
|
||||
U32 getVersionNumber();
|
||||
/// Gets the version number in string form
|
||||
/// Gets the engine version number in a human readable form
|
||||
const char* getVersionString();
|
||||
/// Gets the engine product name in string form
|
||||
const char* getEngineProductString();
|
||||
/// Gets the compile date and time
|
||||
const char* getCompileTimeString();
|
||||
|
||||
/// Gets the application version number. The version number is specified as a global in torqueConfig.h
|
||||
U32 getAppVersionNumber();
|
||||
/// Gets the human readable application version string.
|
||||
const char* getAppVersionString();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ extern "C" {
|
|||
return so->getClassName();
|
||||
}
|
||||
|
||||
void *SimObject_GetFieldList(SimObject *so, int &outNumFields)
|
||||
void *SimObject_GetFieldList(SimObject *so, S32 &outNumFields)
|
||||
{
|
||||
const AbstractClassRep::FieldList &fl = so->getFieldList();
|
||||
outNumFields = fl.size();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
// External scripting cinterface, suitable for import into any scripting system which support "C" interfaces (C#, Python, Lua, Java, etc)
|
||||
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
#ifdef TORQUE_OS_WIN
|
||||
#include "windowManager/win32/win32Window.h"
|
||||
#include "windowManager/win32/winDispatch.h"
|
||||
#endif
|
||||
|
|
@ -164,7 +164,7 @@ extern "C" {
|
|||
return false;
|
||||
}
|
||||
|
||||
void script_simobject_setfield_int(U32 objectId, const char* fieldName, int v)
|
||||
void script_simobject_setfield_int(U32 objectId, const char* fieldName, S32 v)
|
||||
{
|
||||
SimObject *object = Sim::findObject( objectId );
|
||||
if( object )
|
||||
|
|
@ -223,7 +223,7 @@ extern "C" {
|
|||
{
|
||||
// maxArgs improper on a number of console function/methods
|
||||
if (argc < entry->mMinArgs)// || argc > entry->mMaxArgs)
|
||||
return "";
|
||||
return false;
|
||||
|
||||
SimObject* o = NULL;
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ extern "C" {
|
|||
{
|
||||
o = Sim::findObject(dAtoi(argv[1]));
|
||||
if (!o)
|
||||
return "";
|
||||
return false;
|
||||
}
|
||||
|
||||
StringStackConsoleWrapper args(argc, argv);
|
||||
|
|
@ -296,12 +296,12 @@ extern "C" {
|
|||
entry->cb.mVoidCallbackFunc(o, args.count(), args);
|
||||
}
|
||||
|
||||
int script_simobject_get_id(SimObject* so)
|
||||
S32 script_simobject_get_id(SimObject* so)
|
||||
{
|
||||
return so->getId();
|
||||
}
|
||||
|
||||
int script_simobject_find(const char* classname, const char* name)
|
||||
S32 script_simobject_find(const char* classname, const char* name)
|
||||
{
|
||||
SimObject *object;
|
||||
if( Sim::findObject( name, object ) )
|
||||
|
|
@ -388,9 +388,9 @@ extern "C" {
|
|||
}
|
||||
|
||||
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
#ifdef TORQUE_OS_WIN
|
||||
|
||||
void script_input_event(int type, int value1, int value2)
|
||||
void script_input_event(S32 type, S32 value1, S32 value2)
|
||||
{
|
||||
if (PlatformWindowManager::get() && PlatformWindowManager::get()->getFirstWindow())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "windowManager/platformWindow.h"
|
||||
#include "windowManager/platformWindowMgr.h"
|
||||
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
#ifdef TORQUE_OS_WIN
|
||||
#include "windowManager/win32/win32Window.h"
|
||||
#include "windowManager/win32/winDispatch.h"
|
||||
extern void createFontInit(void);
|
||||
|
|
@ -37,7 +37,7 @@ extern void createFontShutdown(void);
|
|||
#endif
|
||||
|
||||
#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE )
|
||||
extern INT CreateMiniDump(LPEXCEPTION_POINTERS ExceptionInfo);
|
||||
extern S32 CreateMiniDump(LPEXCEPTION_POINTERS ExceptionInfo);
|
||||
#endif
|
||||
|
||||
static HashTable<StringTableEntry,StringTableEntry> gSecureScript;
|
||||
|
|
@ -47,7 +47,7 @@ static HashTable<StringTableEntry,StringTableEntry> gSecureScript;
|
|||
// ObjC hooks for shared library support
|
||||
// See: macMain.mm
|
||||
|
||||
void torque_mac_engineinit(int argc, const char **argv);
|
||||
void torque_mac_engineinit(S32 argc, const char **argv);
|
||||
void torque_mac_enginetick();
|
||||
void torque_mac_engineshutdown();
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// initialize Torque 3D including argument handling
|
||||
int torque_engineinit(S32 argc, const char **argv)
|
||||
S32 torque_engineinit(S32 argc, const char **argv)
|
||||
{
|
||||
|
||||
#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE )
|
||||
|
|
@ -105,7 +105,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// tick Torque 3D's main loop
|
||||
int torque_enginetick()
|
||||
S32 torque_enginetick()
|
||||
{
|
||||
|
||||
#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE )
|
||||
|
|
@ -139,7 +139,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// shutdown the engine
|
||||
int torque_engineshutdown()
|
||||
S32 torque_engineshutdown()
|
||||
{
|
||||
|
||||
#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE )
|
||||
|
|
@ -181,7 +181,7 @@ extern "C" {
|
|||
|
||||
}
|
||||
|
||||
int torque_getconsolebool(const char* name)
|
||||
S32 torque_getconsolebool(const char* name)
|
||||
{
|
||||
return Con::getBoolVariable(name);
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ extern "C" {
|
|||
Namespace::Entry* entry = GetEntry(nameSpace, name);
|
||||
|
||||
if (!entry)
|
||||
return "";
|
||||
return false;
|
||||
|
||||
StringStackConsoleWrapper args(argc, argv);
|
||||
return entry->cb.mBoolCallbackFunc(NULL, args.count(), args);
|
||||
|
|
@ -421,7 +421,7 @@ extern "C" {
|
|||
PlatformWindowManager::get()->getFirstWindow()->setSize(Point2I(width,height));
|
||||
}
|
||||
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
#ifdef TORQUE_OS_WIN
|
||||
// retrieve the hwnd of our render window
|
||||
void* torque_gethwnd()
|
||||
{
|
||||
|
|
@ -474,9 +474,10 @@ ConsoleFunction(testJavaScriptBridge, const char *, 4, 4, "testBridge(arg1, arg2
|
|||
if (dStrcmp(jret,"42"))
|
||||
failed = 3;
|
||||
|
||||
char *ret = Con::getReturnBuffer(256);
|
||||
static const U32 bufSize = 256;
|
||||
char *ret = Con::getReturnBuffer(bufSize);
|
||||
|
||||
dSprintf(ret, 256, "%i", failed);
|
||||
dSprintf(ret, bufSize, "%i", failed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public:
|
|||
}
|
||||
|
||||
// Accessors
|
||||
int getCount() const { return mCount; }
|
||||
S32 getCount() const { return mCount; }
|
||||
F32 getTime() const { return mT; }
|
||||
F32 getMaxHeight() const { return mMaxHeight; }
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ enum ConvexType {
|
|||
TSConvexType,
|
||||
BoxConvexType,
|
||||
TerrainConvexType,
|
||||
InteriorConvexType,
|
||||
ShapeBaseConvexType,
|
||||
TSStaticConvexType,
|
||||
AtlasChunkConvexType, ///< @deprecated
|
||||
|
|
|
|||
|
|
@ -69,21 +69,21 @@ void GjkCollisionState::swap()
|
|||
void GjkCollisionState::compute_det()
|
||||
{
|
||||
// Dot new point with current set
|
||||
for (int i = 0, bit = 1; i < 4; ++i, bit <<=1)
|
||||
for (S32 i = 0, bit = 1; i < 4; ++i, bit <<=1)
|
||||
if (bits & bit)
|
||||
dp[i][last] = dp[last][i] = mDot(y[i], y[last]);
|
||||
dp[last][last] = mDot(y[last], y[last]);
|
||||
|
||||
// Calulate the determinent
|
||||
det[last_bit][last] = 1;
|
||||
for (int j = 0, sj = 1; j < 4; ++j, sj <<= 1) {
|
||||
for (S32 j = 0, sj = 1; j < 4; ++j, sj <<= 1) {
|
||||
if (bits & sj) {
|
||||
int s2 = sj | last_bit;
|
||||
S32 s2 = sj | last_bit;
|
||||
det[s2][j] = dp[last][last] - dp[last][j];
|
||||
det[s2][last] = dp[j][j] - dp[j][last];
|
||||
for (int k = 0, sk = 1; k < j; ++k, sk <<= 1) {
|
||||
for (S32 k = 0, sk = 1; k < j; ++k, sk <<= 1) {
|
||||
if (bits & sk) {
|
||||
int s3 = sk | s2;
|
||||
S32 s3 = sk | s2;
|
||||
det[s3][k] = det[s2][j] * (dp[j][j] - dp[j][k]) +
|
||||
det[s2][last] * (dp[last][j] - dp[last][k]);
|
||||
det[s3][j] = det[sk | last_bit][k] * (dp[k][k] - dp[k][j]) +
|
||||
|
|
@ -114,11 +114,11 @@ void GjkCollisionState::compute_det()
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline void GjkCollisionState::compute_vector(int bits, VectorF& v)
|
||||
inline void GjkCollisionState::compute_vector(S32 bits, VectorF& v)
|
||||
{
|
||||
F32 sum = 0;
|
||||
v.set(0, 0, 0);
|
||||
for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
|
||||
for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
|
||||
if (bits & bit) {
|
||||
sum += det[bits][i];
|
||||
v += y[i] * det[bits][i];
|
||||
|
|
@ -130,9 +130,9 @@ inline void GjkCollisionState::compute_vector(int bits, VectorF& v)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool GjkCollisionState::valid(int s)
|
||||
inline bool GjkCollisionState::valid(S32 s)
|
||||
{
|
||||
for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
|
||||
for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
|
||||
if (all_bits & bit) {
|
||||
if (s & bit) {
|
||||
if (det[s][i] <= 0)
|
||||
|
|
@ -152,7 +152,7 @@ inline bool GjkCollisionState::valid(int s)
|
|||
inline bool GjkCollisionState::closest(VectorF& v)
|
||||
{
|
||||
compute_det();
|
||||
for (int s = bits; s; --s) {
|
||||
for (S32 s = bits; s; --s) {
|
||||
if ((s & bits) == s) {
|
||||
if (valid(s | last_bit)) {
|
||||
bits = s | last_bit;
|
||||
|
|
@ -175,7 +175,7 @@ inline bool GjkCollisionState::closest(VectorF& v)
|
|||
|
||||
inline bool GjkCollisionState::degenerate(const VectorF& w)
|
||||
{
|
||||
for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1)
|
||||
for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1)
|
||||
if ((all_bits & bit) && y[i] == w)
|
||||
return true;
|
||||
return false;
|
||||
|
|
@ -256,7 +256,7 @@ void GjkCollisionState::getClosestPoints(Point3F& p1, Point3F& p2)
|
|||
F32 sum = 0;
|
||||
p1.set(0, 0, 0);
|
||||
p2.set(0, 0, 0);
|
||||
for (int i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
|
||||
for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
|
||||
if (bits & bit) {
|
||||
sum += det[bits][i];
|
||||
p1 += p[i] * det[bits][i];
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue