Exemple #1
0
void CTextRenderer::Translate(float x, float y, float z)
{
	CMatrix3D m;
	m.SetTranslation(x, y, z);
	m_Transform = m_Transform * m;
	m_Dirty = true;
}
Exemple #2
0
	// Simplistic implementation of the Scene interface
	virtual void EnumerateObjects(const CFrustum& frustum, SceneCollector* c)
	{
		if (GroundEnabled)
		{
			for (ssize_t pj = 0; pj < Terrain.GetPatchesPerSide(); ++pj)
				for (ssize_t pi = 0; pi < Terrain.GetPatchesPerSide(); ++pi)
					c->Submit(Terrain.GetPatch(pi, pj));
		}

		CmpPtr<ICmpVisual> cmpVisual(Simulation2, Entity);
		if (cmpVisual)
		{
			// add selection box outlines manually
			if (SelectionBoxEnabled)
			{
				SelectionBoxOverlay.m_Color = CColor(35/255.f, 86/255.f, 188/255.f, .75f); // pretty blue
				SelectionBoxOverlay.m_Thickness = 2;

				SimRender::ConstructBoxOutline(cmpVisual->GetSelectionBox(), SelectionBoxOverlay);
				c->Submit(&SelectionBoxOverlay);
			}

			// add origin axis thingy
			if (AxesMarkerEnabled)
			{
				CMatrix3D worldSpaceAxes;
				// offset from the ground a little bit to prevent fighting with the floor texture (also note: SetTranslation
				// sets the identity 3x3 transformation matrix, which are the world axes)
				worldSpaceAxes.SetTranslation(cmpVisual->GetPosition() + CVector3D(0, 0.02f, 0));
				SimRender::ConstructAxesMarker(worldSpaceAxes, AxesMarkerOverlays[0], AxesMarkerOverlays[1], AxesMarkerOverlays[2]);

				c->Submit(&AxesMarkerOverlays[0]);
				c->Submit(&AxesMarkerOverlays[1]);
				c->Submit(&AxesMarkerOverlays[2]);
			}

			// add prop point overlays
			if (PropPointsMode > 0 && Props.size() > 0)
			{
				PropPointOverlays.clear(); // doesn't clear capacity, but should be ok since the number of prop points is usually pretty limited
				for (size_t i = 0; i < Props.size(); ++i)
				{
					CModel::Prop& prop = Props[i];
					if (prop.m_Model) // should always be the case
					{
						// prop point positions are automatically updated during animations etc. by CModel::ValidatePosition
						const CMatrix3D& propCoordSystem = prop.m_Model->GetTransform();
						
						SOverlayLine pointGimbal;
						pointGimbal.m_Color = CColor(1.f, 0.f, 1.f, 1.f);
						SimRender::ConstructGimbal(propCoordSystem.GetTranslation(), 0.05f, pointGimbal);
						PropPointOverlays.push_back(pointGimbal);

						if (PropPointsMode > 1)
						{
							// scale the prop axes coord system down a bit to distinguish them from the main world-space axes markers
							CMatrix3D displayCoordSystem = propCoordSystem;
							displayCoordSystem.Scale(0.5f, 0.5f, 0.5f);
							// revert translation scaling
							displayCoordSystem._14 = propCoordSystem._14;
							displayCoordSystem._24 = propCoordSystem._24;
							displayCoordSystem._34 = propCoordSystem._34;

							// construct an XYZ axes marker for the prop's coordinate system
							SOverlayLine xAxis, yAxis, zAxis;
							SimRender::ConstructAxesMarker(displayCoordSystem, xAxis, yAxis, zAxis);
							PropPointOverlays.push_back(xAxis);
							PropPointOverlays.push_back(yAxis);
							PropPointOverlays.push_back(zAxis);
						}
					}
				}

				for (size_t i = 0; i < PropPointOverlays.size(); ++i)
				{
					c->Submit(&PropPointOverlays[i]);
				}
			}
		}

		// send a RenderSubmit message so the components can submit their visuals to the renderer
		Simulation2.RenderSubmit(*c, frustum, false);
	}
Exemple #3
0
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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);
	}
}