Example #1
0
void Rotation::setValue(const Vector3d & rotateFrom, const Vector3d & rotateTo)
{
    Vector3d u(rotateFrom); u.Normalize();
    Vector3d v(rotateTo); v.Normalize();

    // The vector from x to is the roatation axis because it's the normal of the plane defined by (0,u,v) 
    const double dot = u * v;
    Vector3d w = u % v;
    const double wlen = w.Length();

    if (wlen == 0.0) { // Parallel vectors
        // Check if they are pointing in the same direction.
        if (dot > 0.0) {
            this->setValue(0.0, 0.0, 0.0, 1.0);
        }
        else {
            // We can use any axis perpendicular to u (and v)
            Vector3d t = u % Vector3d(1.0, 0.0, 0.0);
            if(t.Length() < FLT_EPSILON) 
                t = u % Vector3d(0.0, 1.0, 0.0);
            this->setValue(t.x, t.y, t.z, 0.0);
        }
    }
    else { // Vectors are not parallel
        // Note: A quaternion is not well-defined by specifying a point and its transformed point.
        // Every quaternion with a rotation axis having the same angle to the vectors of both points is okay.
        double angle = (double)acos(dot);
        this->setValue(w, angle);
    }
}
// This is a "perceptually tuned predictive filter", which means that it is optimized
// for improvements in the VR experience, rather than pure error.  In particular,
// jitter is more perceptible at lower speeds whereas latency is more perceptible
// after a high-speed motion.  Therefore, the prediction interval is dynamically
// adjusted based on speed.  Significant more research is needed to further improve
// this family of filters.
static Pose<double> calcPredictedPose(const PoseState<double>& poseState, double predictionDt)
{
	Pose<double> pose = poseState.ThePose;
	const double linearCoef = 1.0;
	Vector3d angularVelocity = poseState.AngularVelocity;
	double angularSpeed = angularVelocity.Length();

	// This could be tuned so that linear and angular are combined with different coefficients
	double speed = angularSpeed + linearCoef * poseState.LinearVelocity.Length();

	const double slope = 0.2; // The rate at which the dynamic prediction interval varies
	double candidateDt = slope * speed; // TODO: Replace with smoothstep function

	double dynamicDt = predictionDt;

	// Choose the candidate if it is shorter, to improve stability
	if (candidateDt < predictionDt)
	{
		dynamicDt = candidateDt;
	}

	if (angularSpeed > 0.001)
	{
		pose.Rotation = pose.Rotation * Quatd(angularVelocity, angularSpeed * dynamicDt);
	}

	pose.Translation += poseState.LinearVelocity * dynamicDt;

	return pose;
}
Example #3
0
void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
	if (m_InvulnerableTicks > 0)
	{
		m_InvulnerableTicks--;
	}

	if (m_AttachedTo != NULL)
	{
		Vector3d DeltaPos = m_Pos - m_AttachedTo->GetPosition();
		if (DeltaPos.Length() > 0.5)
		{
			SetPosition(m_AttachedTo->GetPosition());

			if (IsPlayer())
			{
				cPlayer * Player = (cPlayer *)this;
				Player->UpdateMovementStats(DeltaPos);
			}
		}
	}
	else
	{
		if (!a_Chunk.IsValid())
		{
			return;
		}

		// Position changed -> super::Tick() called
		GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, POSX_TOINT, POSZ_TOINT)

		TickBurning(*NextChunk);

		if (GetPosY() < VOID_BOUNDARY)
		{
			TickInVoid(*NextChunk);
		}
		else
		{
			m_TicksSinceLastVoidDamage = 0;
		}

		if (IsMob() || IsPlayer() || IsPickup() || IsExpOrb())
		{
			DetectCacti();
		}
		if (IsMob() || IsPlayer())
		{
			// Set swimming state
			SetSwimState(*NextChunk);

			// Handle drowning
			HandleAir();
		}

		// None of the above functions change position, we remain in the chunk of NextChunk
		HandlePhysics(a_Dt, *NextChunk);
	}
}
Example #4
0
void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos)
{
	StatValue Value = (StatValue)floor(a_DeltaPos.Length() * 100 + 0.5);

	if (m_AttachedTo == NULL)
	{
		if (IsClimbing())
		{
			if (a_DeltaPos.y > 0.0)  // Going up
			{
				m_Stats.AddValue(statDistClimbed, (StatValue)floor(a_DeltaPos.y * 100 + 0.5));
			}
		}
		else if (IsSubmerged())
		{
			m_Stats.AddValue(statDistDove, Value);
			AddFoodExhaustion(0.00015 * (double)Value);
		}
		else if (IsSwimming())
		{
			m_Stats.AddValue(statDistSwum, Value);
			AddFoodExhaustion(0.00015 * (double)Value);
		}
		else if (IsOnGround())
		{
			m_Stats.AddValue(statDistWalked, Value);
			AddFoodExhaustion((m_IsSprinting ? 0.001 : 0.0001) * (double)Value);
		}
		else
		{
			if (Value >= 25)  // Ignore small/slow movement
			{
				m_Stats.AddValue(statDistFlown, Value);
			}
		}
	}
	else
	{
		switch (m_AttachedTo->GetEntityType())
		{
			case cEntity::etMinecart: m_Stats.AddValue(statDistMinecart, Value); break;
			case cEntity::etBoat:     m_Stats.AddValue(statDistBoat,     Value); break;
			case cEntity::etMonster:
			{
				cMonster * Monster = (cMonster *)m_AttachedTo;
				switch (Monster->GetMobType())
				{
					case cMonster::mtPig:   m_Stats.AddValue(statDistPig,   Value); break;
					case cMonster::mtHorse: m_Stats.AddValue(statDistHorse, Value); break;
					default: break;
				}
				break;
			}
			default: break;
		}
	}
}
Example #5
0
	virtual bool Item(cPlayer * a_Player) override
	{
		// Don't check players who are in creative gamemode
		if (a_Player->IsGameModeCreative())
		{
			return false;
		}
		
		Vector3d Direction = m_EndermanPos - a_Player->GetPosition();
		
		// Don't check players who are more then SightDistance (64) blocks away
		if (Direction.Length() > m_SightDistance)
		{
			return false;
		}
		
		// Don't check if the player has a pumpkin on his head
		if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN)
		{
			return false;
		}

		
		Vector3d LookVector = a_Player->GetLookVector();
		double dot = Direction.Dot(LookVector);
		
		// 0.09 rad ~ 5 degrees
		// If the player's crosshair is within 5 degrees of the enderman, it counts as looking
		if (dot <= cos(0.09))
		{
			return false;
		}
		
		cTracer LineOfSight(a_Player->GetWorld());
		if (LineOfSight.Trace(m_EndermanPos, Direction, static_cast<int>(Direction.Length())))
		{
			// No direct line of sight
			return false;
		}

		m_Player = a_Player;
		return true;
	}
void ModelRenderInstance::SetPosition(const Vector3d& vPos, double dViewAngle)
{
   m_dViewAngle = dViewAngle;

   if (m_bFirstPosInit)
   {
      m_vPos = vPos;
      m_bFirstPosInit = false;
      return;
   }

   // check if new distance is "too far" and we should "correct"
   if (!m_bCorrectPos)
   {
      Vector3d vDist = m_vPos - vPos;
      double dMaxDist = 0.5;
      bool bTooFar = vDist.Length() > dMaxDist;

      if (bTooFar)
      {
         // start correcting
         m_bCorrectPos = true;
         m_timerCorrect.Start();
 
         m_vCorrectStart = m_vPos;
         m_vCorrectTarget = vPos;
      }
      else
      {
         // just use new coordinate
         m_vPos = vPos;
      }
   }
   else
   {
      // already correcting

      bool bFinishedCorrecting = m_timerCorrect.Elapsed() >= c_dCorrectTimeRange;

      if (!bFinishedCorrecting)
      {
         // still too far
         m_vCorrectTarget = vPos;
      }
      else
      {
         // correction finished
         m_timerCorrect.Stop();
         m_bCorrectPos = false;

         m_vPos = vPos;
      }
   }
}
void PerspectiveCamera::SetPositionLookAt(const Vector3d& vPos, const Vector3d& vLookAt)
{
   Vector3d vDir = vLookAt - vPos;
   if (vDir.Length() < 1e-6)
      vDir = Vector3d(0.0, 0.0, 1.0);

   double dAngleDirection = Rad2Deg(atan2(vDir.X(), -vDir.Z()));
   double dAngleUp = Rad2Deg(atan2(vDir.Y(), -vDir.Z()));

   SetPosition(vPos, dAngleDirection, dAngleUp);
}
        // This is a simple predictive filter based only on extrapolating the smoothed, current angular velocity.
        // Note that both QP (the predicted future orientation) and Q (the current orientation) are both maintained.
Quatf       SensorFusion::GetPredictedOrientation()
{		
	Lock::Locker lockScope(Handler.GetHandlerLock());
	Quatf qP = QUncorrected;
	if (EnablePrediction) {
#if 1
	    Vector3f angVelF  = FAngV.SavitzkyGolaySmooth8();
        float    angVelFL = angVelF.Length();
            
        if (angVelFL > 0.001f)
        {
            Vector3f    rotAxisP      = angVelF / angVelFL;  
            float       halfRotAngleP = angVelFL * PredictionDT * 0.5f;
            float       sinaHRAP      = sin(halfRotAngleP);
		    Quatf       deltaQP(rotAxisP.x*sinaHRAP, rotAxisP.y*sinaHRAP,
                                rotAxisP.z*sinaHRAP, cos(halfRotAngleP));
            qP = QUncorrected * deltaQP;
        }
#else
        Quatd qpd = Quatd(Q.x,Q.y,Q.z,Q.w);
        int predictionStages = (int)(PredictionDT / DeltaT);
        Vector3f  aa = FAngV.SavitzkyGolayDerivative12();
        Vector3d  aad     = Vector3d(aa.x,aa.y,aa.z);
        Vector3f angVelF  = FAngV.SavitzkyGolaySmooth8();
        Vector3d  avkd    = Vector3d(angVelF.x,angVelF.y,angVelF.z);
        for (int i = 0; i < predictionStages; i++)
        {
            double angVelLengthd = avkd.Length();
            Vector3d rotAxisd      = avkd / angVelLengthd;
            double halfRotAngled = angVelLengthd * DeltaT * 0.5;
            double sinHRAd       = sin(halfRotAngled);
            Quatd  deltaQd       = Quatd(rotAxisd.x*sinHRAd, rotAxisd.y*sinHRAd, rotAxisd.z*sinHRAd,
                                         cos(halfRotAngled));
            qpd =  qpd * deltaQd;
            // Update vel
            avkd += aad;
        }
        qP = Quatf((float)qpd.x,(float)qpd.y,(float)qpd.z,(float)qpd.w);
#endif
	}
    return qP;
}    
void SelectionList::Update(const Vector3d& vCurrentPos, const ObjectMap& objMap, double dMaxDistance)
{
   // remember last selected id
   ObjectId lastObjId = GetSelected();

   m_vecSelectionList.clear();

   ObjectMap::const_iterator iter = objMap.GetMap().begin();
   ObjectMap::const_iterator stop = objMap.GetMap().end();

   size_t uiLastSelected = std::numeric_limits<size_t>::max();
   for (; iter != stop; --iter)
   {
      ATLASSERT(iter->second != NULL);

      const ObjectId& objId = iter->first;

      // check length
      const Object& obj = *(iter->second);
      Vector3d vDist = vCurrentPos - obj.Pos();
      if (vDist.Length() > dMaxDistance)
         continue;

      if (objId == lastObjId)
         uiLastSelected = m_vecSelectionList.size();

      m_vecSelectionList.push_back(objId);
   }

   // TODO sort by nearest

   if (uiLastSelected < m_vecSelectionList.size())
      m_iterSelected = m_vecSelectionList.begin() + uiLastSelected;
   else
      m_iterSelected = m_vecSelectionList.end();
}