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); }
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); }
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); }
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; }
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); } }
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, ¤tPos); // 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); }
void AITurretShape::recenterTurret() { mRot.set(0,0,0); _setRotation( mRot ); setMaskBits(TurretUpdateMask); }