コード例 #1
0
//Returns the transpose of the matrix. For orthonormal
//matrices, this is the same is the inverse matrix
CMatrix3D CMatrix3D::GetTranspose() const
{
	return CMatrix3D(
		_11, _21, _31, _41,
		_12, _22, _32, _42,
		_13, _23, _33, _43,
		_14, _24, _34, _44);
コード例 #2
0
void CMatrix3D::SetOrtho (float l, float r, float b, float t, float n, float f)
{
	// Based on OpenGL spec
	*this = CMatrix3D(
		2/(r-l), 0, 0, -(r+l)/(r-l),
		0, 2/(t-b), 0, -(t+b)/(t-b),
		0, 0, -2/(f-n), -(f+n)/(f-n),
		0, 0, 0, 1
	);
コード例 #3
0
ファイル: CCmpPosition.cpp プロジェクト: 2asoft/0ad
	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;
	}
コード例 #4
0
ファイル: Model.cpp プロジェクト: 2asoft/0ad
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ValidatePosition: ensure that current transform and bone matrices are both uptodate
void CModel::ValidatePosition()
{
	if (m_PositionValid)
	{
		ENSURE(!m_Parent || m_Parent->m_PositionValid);
		return;
	}

	if (m_Parent && !m_Parent->m_PositionValid)
	{
		// Make sure we don't base our calculations on
		// a parent animation state that is out of date.
		m_Parent->ValidatePosition();

		// Parent will recursively call our validation.
		ENSURE(m_PositionValid);
		return;
	}

	if (m_Anim && m_BoneMatrices)
	{
//		PROFILE( "generating bone matrices" );

		ENSURE(m_pModelDef->GetNumBones() == m_Anim->m_AnimDef->GetNumKeys());

		m_Anim->m_AnimDef->BuildBoneMatrices(m_AnimTime, m_BoneMatrices, !(m_Flags & MODELFLAG_NOLOOPANIMATION));
	}
	else if (m_BoneMatrices)
	{
		// Bones but no animation - probably a buggy actor forgot to set up the animation,
		// so just render it in its bind pose

		for (size_t i = 0; i < m_pModelDef->GetNumBones(); i++)
		{
			m_BoneMatrices[i].SetIdentity();
			m_BoneMatrices[i].Rotate(m_pModelDef->GetBones()[i].m_Rotation);
			m_BoneMatrices[i].Translate(m_pModelDef->GetBones()[i].m_Translation);
		}
	}

	// For CPU skinning, we precompute as much as possible so that the only
	// per-vertex work is a single matrix*vec multiplication.
	// For GPU skinning, we try to minimise CPU work by doing most computation
	// in the vertex shader instead.
	// Using g_Renderer.m_Options to detect CPU vs GPU is a bit hacky,
	// and this doesn't allow the setting to change at runtime, but there isn't
	// an obvious cleaner way to determine what data needs to be computed,
	// and GPU skinning is a rarely-used experimental feature anyway.
	bool worldSpaceBoneMatrices = !g_Renderer.m_Options.m_GPUSkinning;
	bool computeBlendMatrices = !g_Renderer.m_Options.m_GPUSkinning;

	if (m_BoneMatrices && worldSpaceBoneMatrices)
	{
		// add world-space transformation to m_BoneMatrices
		const CMatrix3D transform = GetTransform();
		for (size_t i = 0; i < m_pModelDef->GetNumBones(); i++)
			m_BoneMatrices[i].Concatenate(transform);
	}

	// our own position is now valid; now we can safely update our props' positions without fearing
	// that doing so will cause a revalidation of this model (see recursion above).
	m_PositionValid = true;

	// re-position and validate all props
	for (size_t j = 0; j < m_Props.size(); ++j)
	{
		const Prop& prop=m_Props[j];

		CMatrix3D proptransform = prop.m_Point->m_Transform;

		if (prop.m_Point->m_BoneIndex != 0xff)
		{
			CMatrix3D boneMatrix = m_BoneMatrices[prop.m_Point->m_BoneIndex];
			if (!worldSpaceBoneMatrices)
				boneMatrix.Concatenate(GetTransform());
			proptransform.Concatenate(boneMatrix);
		}
		else
		{
			// not relative to any bone; just apply world-space transformation (i.e. relative to object-space origin)
			proptransform.Concatenate(m_Transform);
		}

		// Adjust prop height to terrain level when needed
		if (prop.m_MaxHeight != 0.f || prop.m_MinHeight != 0.f)
		{
			CVector3D propTranslation = proptransform.GetTranslation();
			CVector3D objTranslation = m_Transform.GetTranslation();

			CmpPtr<ICmpTerrain> cmpTerrain(m_Simulation, SYSTEM_ENTITY);
			if (cmpTerrain)
			{
				float objTerrain = cmpTerrain->GetExactGroundLevel(objTranslation.X, objTranslation.Z);
				float propTerrain = cmpTerrain->GetExactGroundLevel(propTranslation.X, propTranslation.Z);
				float translateHeight = std::min(prop.m_MaxHeight,
				                                 std::max(prop.m_MinHeight, propTerrain - objTerrain));
				CMatrix3D translate = CMatrix3D();
				translate.SetTranslation(0.f, translateHeight, 0.f);
				proptransform.Concatenate(translate);
			}
		}

		prop.m_Model->SetTransform(proptransform);
		prop.m_Model->ValidatePosition();
	}

	if (m_BoneMatrices)
	{
		for (size_t i = 0; i < m_pModelDef->GetNumBones(); i++)
		{
			m_BoneMatrices[i] = m_BoneMatrices[i] * m_pModelDef->GetInverseBindBoneMatrices()[i];
		}

		// Note: there is a special case of joint influence, in which the vertex
		//	is influenced by the bind-shape transform instead of a particular bone,
		//	which we indicate with the blending bone ID set to the total number
		//	of bones. But since we're skinning in world space, we use the model's
		//	world space transform and store that matrix in this special index.
		//	(see http://trac.wildfiregames.com/ticket/1012)
		m_BoneMatrices[m_pModelDef->GetNumBones()] = m_Transform;

		if (computeBlendMatrices)
			m_pModelDef->BlendBoneMatrices(m_BoneMatrices);
	}
}