예제 #1
0
void TurretShape::updateMove(const Move* move)
{
   PROFILE_SCOPE( TurretShape_UpdateMove );

   if (!move)
      return;

   Point3F vec, pos;

   // Update orientation
   mTurretDelta.rotVec = mRot;

   VectorF rotVec(0, 0, 0);
   if (getAllowManualRotation())
   {
      if (mPitchAllowed)
      {
         rotVec.x = move->pitch * 2.0f;   // Assume that our -2PI to 2PI range was clamped to -PI to PI in script;
         if (mPitchRate > 0)
         {
            rotVec.x *= mPitchRate * TickSec;
         }
      }
      if (mHeadingAllowed)
      {
         rotVec.z = move->yaw * 2.0f;     // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
         if (mHeadingRate > 0)
         {
            rotVec.z *= mHeadingRate * TickSec;
         }
      }
   }

   mRot.x += rotVec.x;
   mRot.z += rotVec.z;
   _applyLimits(mRot);

   if (isServerObject())
   {
      // As this ends up animating shape nodes, we have no sense of a transform and
      // render transform.  Therefore we treat this as the true transform and leave the
      // client shape node changes to interpolateTick() as the render transform.  Otherwise
      // on the client we'll have this node change from processTick() and then backstepping
      // and catching up to the true node change in interpolateTick(), which causes the
      // turret to stutter.
      _setRotation( mRot );
   }
   else
   {
      // If on the client, calc delta for backstepping
      mTurretDelta.rot = mRot;
      mTurretDelta.rotVec = mTurretDelta.rotVec - mTurretDelta.rot;
   }

   setMaskBits(TurretUpdateMask);
}
예제 #2
0
void TurretShape::readPacketData(GameConnection *connection, BitStream *stream)
{
   Parent::readPacketData(connection, stream);

   Point3F rot(0.0f, 0.0f, 0.0f);
   stream->read(&rot.x);
   stream->read(&rot.z);

   _setRotation(rot);

   mTurretDelta.rot = rot;
   mTurretDelta.rotVec.set(0.0f, 0.0f, 0.0f);
}
예제 #3
0
void TurretShape::interpolateTick(F32 dt)
{
   Parent::interpolateTick(dt);

   if (isMounted()) {
      MatrixF mat;
      mMount.object->getRenderMountTransform( dt, mMount.node, mMount.xfm, &mat );
      ShapeBase::setRenderTransform(mat);
   }

   // Orientation
   Point3F rot = mTurretDelta.rot + mTurretDelta.rotVec * dt;

   // Make sure we don't interpolate past the limits
   _applyLimits(rot);

   _setRotation(rot);
}
예제 #4
0
bool PrefabWithMesh_Plant::setAttribute( const wstring & attribute, const wstring & value )
{
	wstring name = elements.top();

	if (name == PrefabWithMesh_Plant::mesh)
	{
		_setMeshName(attribute, value);
	} else if (name == PrefabWithMesh_Plant::scale)
	{
		_setScale(attribute, value);
	}
	else if (name == PrefabWithMesh_Plant::rotation)
	{
		_setRotation(attribute, value);
	} else
	{
		return false;
	}
	return true;
}
예제 #5
0
void TurretShape::unpackUpdate(NetConnection *connection, BitStream *stream)
{
   Parent::unpackUpdate(connection,stream);

   // InitialUpdateMask
   if (stream->readFlag()) {
      mRespawn = stream->readFlag();
   }

   // Item::RotationMask
   if ( stream->readFlag() )
   {
      QuatF rot;
      mathRead( *stream, &rot );

      Point3F pos = mObjToWorld.getPosition();
      rot.setMatrix( &mObjToWorld );
      mObjToWorld.setPosition( pos );
   }

   // controlled by the client?
   if(stream->readFlag())
      return;

   // TurretUpdateMask
   if (stream->readFlag())
   {
      Point3F rot(0.0f, 0.0f, 0.0f);
      stream->read(&rot.x);
      stream->read(&rot.z);
      _setRotation(rot);

      // New delta for client side interpolation
      mTurretDelta.rot = rot;
      mTurretDelta.rotVec = VectorF(0.0f, 0.0f, 0.0f);

      stream->read(&allowManualRotation);
      stream->read(&allowManualFire);
   }
}
예제 #6
0
void AITurretShape::_trackTarget(F32 dt)
{
   // Only on server
   if (isClientObject())
      return;

   // We can only track a target if we have one
   if (!mTarget.isValid())
      return;

   Point3F targetPos = mTarget.target->getBoxCenter();

   // Can we see the target?
   MatrixF aimMat;
   getAimTransform(aimMat);
   Point3F start;
   aimMat.getColumn(3, &start);
   RayInfo ri;

   Point3F sightPoint;

   disableCollision();
   bool los = _testTargetLineOfSight(start, mTarget.target, sightPoint);
   enableCollision();

   if (!los)
   {
      // Target is blocked.  Should we try to track from its last
      // known position and velocity?
      SimTime curTime = Sim::getCurrentTime();
      if ( (curTime - mTarget.lastSightTime) > (mDataBlock->trackLostTargetTime * 1000.0f) )
      {
         // Time's up.  Stop tracking.
         _cleanupTargetAndTurret();
         return;
      }
      
      // Use last known information to attempt to
      // continue to track target for a while.
      targetPos = mTarget.lastPos + mTarget.lastVel * F32(curTime - mTarget.lastSightTime) / 1000.0f;
   }
   else
   {
      // Target is visible

      // We only track targets that are alive
      if (mTarget.target->getDamageState() != Enabled)
      {
         // We can't track any more
         _cleanupTargetAndTurret();
         return;
      }

      targetPos = sightPoint;

      // Store latest target info
      mTarget.lastPos = targetPos;
      mTarget.lastVel = mTarget.target->getVelocity();
      mTarget.lastSightTime = Sim::getCurrentTime();
   }

   // Calculate angles to face the target, specifically the part that we can see
   VectorF toTarget;
   MatrixF mat;
   S32 node = mDataBlock->aimNode;
   if (node != -1)
   {
      // Get the current position of our node
      MatrixF* nodeTrans = &mShapeInstance->mNodeTransforms[node];
      Point3F currentPos;
      nodeTrans->getColumn(3, &currentPos);

      // Turn this into a matrix we can use to put the target
      // position into our space.
      MatrixF nodeMat(true);
      nodeMat.setColumn(3, currentPos);
      mat.mul(mObjToWorld, nodeMat);
      mat.affineInverse();
   }
   else
   {
      mat = mWorldToObj;
   }
   mat.mulP(targetPos, &toTarget);

   // lead the target
   F32 timeToTargetSquared = (mWeaponLeadVelocitySquared > 0) ? toTarget.lenSquared() / mWeaponLeadVelocitySquared : 0;
   if (timeToTargetSquared > 1.0)
   {
      targetPos = targetPos + (mTarget.lastVel * mSqrt(timeToTargetSquared));
      mat.mulP(targetPos, &toTarget);
   }

   F32 yaw, pitch;
   MathUtils::getAnglesFromVector(toTarget, yaw, pitch);
   if (yaw > M_PI_F)
      yaw = yaw - M_2PI_F;
   //if (pitch > M_PI_F)
   //   pitch = -(pitch - M_2PI_F);

   Point3F rot(-pitch, 0.0f, yaw);

   // If we have a rotation rate make sure we follow it
   if (mHeadingRate > 0)
   {
      F32 rate = mHeadingRate * dt;
      F32 rateCheck = mFabs(rot.z - mRot.z);
      if (rateCheck > rate)
      {
         // This will clamp the new value to the rate regardless if it
         // is increasing or decreasing.
         rot.z = mClampF(rot.z, mRot.z-rate, mRot.z+rate);
      }
   }
   if (mPitchRate > 0)
   {
      F32 rate = mPitchRate * dt;
      F32 rateCheck = mFabs(rot.x - mRot.x);
      if (rateCheck > rate)
      {
         // This will clamp the new value to the rate regardless if it
         // is increasing or decreasing.
         rot.x = mClampF(rot.x, mRot.x-rate, mRot.x+rate);
      }
   }

   // Test if the rotation to the target is outside of our limits
   if (_outsideLimits(rot))
   {
      // We can't track any more
      _cleanupTargetAndTurret();
      return;
   }

   // Test if the target is out of weapons range
   if (toTarget.lenSquared() > mWeaponRangeSquared)
   {
      // We can't track any more
      _cleanupTargetAndTurret();
      return;
   }

   mRot = rot;

   _setRotation( mRot );
   setMaskBits(TurretUpdateMask);
}
예제 #7
0
void AITurretShape::recenterTurret()
{
   mRot.set(0,0,0);
   _setRotation( mRot );
   setMaskBits(TurretUpdateMask);
}