Exemple #1
0
	virtual void GetInterpolatedPosition2D(float frameOffset, float& x, float& z, float& rotY)
	{
		if (!m_InWorld)
		{
			LOGERROR(L"CCmpPosition::GetInterpolatedPosition2D called on entity when IsInWorld is false");
			return;
		}

		x = Interpolate(m_LastX.ToFloat(), m_X.ToFloat(), frameOffset);
		z = Interpolate(m_LastZ.ToFloat(), m_Z.ToFloat(), frameOffset);

		rotY = m_InterpolatedRotY;
	}
Exemple #2
0
	virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating)
	{
		if (!m_InWorld)
		{
			LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
			CMatrix3D m;
			m.SetIdentity();
			return m;
		}

		float x, z, rotY;
		GetInterpolatedPosition2D(frameOffset, x, z, rotY);

		float baseY = 0;
		if (m_RelativeToGround)
		{
			CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
			if (cmpTerrain)
				baseY = cmpTerrain->GetExactGroundLevel(x, z);

			if (m_Floating || forceFloating)
			{
				CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
				if (cmpWaterManager)
					baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z));
			}
		}

		float y = baseY + m_YOffset.ToFloat();

		// TODO: do something with m_AnchorType

		CMatrix3D m;
		CMatrix3D mXZ;
		float Cos = cosf(rotY);
		float Sin = sinf(rotY);

		m.SetIdentity();
		m._11 = -Cos;
		m._13 = -Sin;
		m._31 = Sin;
		m._33 = -Cos;

		mXZ.SetIdentity();
		mXZ.SetXRotation(m_RotX.ToFloat());
		mXZ.RotateZ(m_RotZ.ToFloat());
		// TODO: is this all done in the correct order?
		mXZ = m * mXZ;
		mXZ.Translate(CVector3D(x, y, z));

		return mXZ;
	}
Exemple #3
0
	virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
	{
		switch (msg.GetType())
		{
		case MT_RenderSubmit:
		{
			// Don't actually do rendering here, but tell the renderer how to draw water
			if (CRenderer::IsInitialised())
				g_Renderer.GetWaterManager()->m_WaterHeight = m_WaterHeight.ToFloat();
			break;
		}
		}
	}
Exemple #4
0
	virtual CMatrix3D GetInterpolatedTransform(float frameOffset, bool forceFloating)
	{
		if (!m_InWorld)
		{
			LOGERROR(L"CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
			CMatrix3D m;
			m.SetIdentity();
			return m;
		}

		float x, z, rotY;
		GetInterpolatedPosition2D(frameOffset, x, z, rotY);

		float baseY = 0;
		if (m_RelativeToGround)
		{
			CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
			if (cmpTerrain)
				baseY = cmpTerrain->GetExactGroundLevel(x, z);

			if (m_Floating || forceFloating)
			{
				CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
				if (cmpWaterManager)
					baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z));
			}
		}

		float y = baseY + m_YOffset.ToFloat();

		CMatrix3D m;
		
		// linear interpolation is good enough (for RotX/Z). 
		// As you always stay close to zero angle.	
		m.SetXRotation(Interpolate(m_LastInterpolatedRotX, m_InterpolatedRotX, frameOffset));
		m.RotateZ(Interpolate(m_LastInterpolatedRotZ, m_InterpolatedRotZ, frameOffset));
	
		m.RotateY(rotY + (float)M_PI);
		m.Translate(CVector3D(x, y, z));
		
		return m;
	}
Exemple #5
0
	void GetInterpolatedPositions(CVector3D& pos0, CVector3D& pos1)
	{
		float baseY0 = 0;
		float baseY1 = 0;
		float x0 = m_LastX.ToFloat();
		float z0 = m_LastZ.ToFloat();
		float x1 = m_X.ToFloat();
		float z1 = m_Z.ToFloat();
		if (m_RelativeToGround)
		{
			CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
			if (cmpTerrain)
			{
				baseY0 = cmpTerrain->GetExactGroundLevel(x0, z0);
				baseY1 = cmpTerrain->GetExactGroundLevel(x1, z1);
			}

			if (m_Floating || m_ActorFloating)
			{
				CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
				if (cmpWaterManager)
				{
					baseY0 = std::max(baseY0, cmpWaterManager->GetExactWaterLevel(x0, z0));
					baseY1 = std::max(baseY1, cmpWaterManager->GetExactWaterLevel(x1, z1));
				}
			}
		}

		float y0 = baseY0 + m_Y.ToFloat() + m_LastYDifference.ToFloat();
		float y1 = baseY1 + m_Y.ToFloat();

		pos0 = CVector3D(x0, y0, z0);
		pos1 = CVector3D(x1, y1, z1);

		pos0.Y += GetConstructionProgressOffset(pos0);
		pos1.Y += GetConstructionProgressOffset(pos1);
	}
Exemple #6
0
	virtual CMatrix3D GetInterpolatedTransform(float frameOffset)
	{
		if (m_TurretParent != INVALID_ENTITY)
		{
			CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent);
			if (!cmpPosition)
			{
				LOGERROR("Turret with parent without position component");
				CMatrix3D m;
				m.SetIdentity();
				return m;
			}
			if (!cmpPosition->IsInWorld())
			{
				LOGERROR("CCmpPosition::GetInterpolatedTransform called on turret entity when IsInWorld is false");
				CMatrix3D m;
				m.SetIdentity();
				return m;
			}
			else
			{
				CMatrix3D parentTransformMatrix = cmpPosition->GetInterpolatedTransform(frameOffset);
				CMatrix3D ownTransformation = CMatrix3D();
				ownTransformation.SetYRotation(m_InterpolatedRotY);
				ownTransformation.Translate(-m_TurretPosition.X.ToFloat(), m_TurretPosition.Y.ToFloat(), -m_TurretPosition.Z.ToFloat());
				return parentTransformMatrix * ownTransformation;
			}
		}
		if (!m_InWorld)
		{
			LOGERROR("CCmpPosition::GetInterpolatedTransform called on entity when IsInWorld is false");
			CMatrix3D m;
			m.SetIdentity();
			return m;
		}

		float x, z, rotY;
		GetInterpolatedPosition2D(frameOffset, x, z, rotY);


		float baseY = 0;
		if (m_RelativeToGround)
		{
			CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
			if (cmpTerrain)
				baseY = cmpTerrain->GetExactGroundLevel(x, z);

			if (m_Floating || m_ActorFloating)
			{
				CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
				if (cmpWaterManager)
					baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z));
			}
		}

		float y = baseY + m_Y.ToFloat() + Interpolate(-1 * m_LastYDifference.ToFloat(), 0.f, frameOffset);

		CMatrix3D m;

		// linear interpolation is good enough (for RotX/Z).
		// As you always stay close to zero angle.
		m.SetXRotation(Interpolate(m_LastInterpolatedRotX, m_InterpolatedRotX, frameOffset));
		m.RotateZ(Interpolate(m_LastInterpolatedRotZ, m_InterpolatedRotZ, frameOffset));

		CVector3D pos(x, y, z);

		pos.Y += GetConstructionProgressOffset(pos);

		m.RotateY(rotY + (float)M_PI);
		m.Translate(pos);

		return m;
	}
Exemple #7
0
	virtual float GetExactWaterLevel(float UNUSED(x), float UNUSED(z))
	{
		return m_WaterHeight.ToFloat();
	}
Exemple #8
0
    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
    {
        switch (msg.GetType())
        {
        case MT_Interpolate:
        {
            if (!m_Active)
                break;

            const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);

            CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
            if (!cmpPosition || !cmpPosition->IsInWorld())
            {
                // If there's no position (this usually shouldn't happen), destroy the unit immediately
                GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
                break;
            }

            // Compute the depth the first time this is called
            // (This is a bit of an ugly place to do it but at least we'll be sure
            // the actor component was loaded already)
            if (m_TotalSinkDepth < 0.f)
            {
                m_TotalSinkDepth = 1.f; // minimum so we always sink at least a little

                CmpPtr<ICmpVisual> cmpVisual(GetSimContext(), GetEntityId());
                if (cmpVisual)
                {
                    CBoundingBoxAligned bound = cmpVisual->GetBounds();
                    m_TotalSinkDepth = std::max(m_TotalSinkDepth, bound[1].Y - bound[0].Y);
                }

                // If this is a floating unit, we want it to sink all the way under the terrain,
                // so find the difference between its current position and the terrain

                CFixedVector3D pos = cmpPosition->GetPosition();

                CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
                if (cmpTerrain)
                {
                    fixed ground = cmpTerrain->GetGroundLevel(pos.X, pos.Z);
                    m_TotalSinkDepth += std::max(0.f, (pos.Y - ground).ToFloat());
                }

                // Sink it further down if it sinks like a ship, as it will rotate.
                if (m_ShipSink)
                    m_TotalSinkDepth += 10.f;

                // probably 0 in both cases but we'll remember it anyway.
                m_InitialXRotation = cmpPosition->GetRotation().X;
                m_InitialZRotation = cmpPosition->GetRotation().Z;
            }

            m_CurrentTime += msgData.deltaSimTime;

            if (m_CurrentTime >= m_DelayTime)
            {
                float t = m_CurrentTime - m_DelayTime;
                float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);

                if (m_ShipSink)
                {
                    // exponential sinking with tilting
                    float tilt_time = t > 5.f ? 5.f : t;
                    float tiltSink = tilt_time * tilt_time / 5.f;
                    entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5.f - tiltSink)) + (1.5f * tiltSink)) / 5.f);
                    entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3.f - tilt_time)) + (-0.3f * tilt_time)) / 3.f);
                    cmpPosition->SetXZRotation(RotX,RotZ);

                    depth = m_SinkRate * (exp(t - 1.f) - 0.54881163609f) + (m_SinkAccel * exp(t - 4.f) - 0.01831563888f);
                    if (depth < 0.f)
                        depth = 0.f;
                }

                cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));

                if (depth > m_TotalSinkDepth)
                    GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
            }

            break;
        }
        }
    }