Intro :
Dans tout moteur 3D il est représenté un objet SceneNode (noeud de scène).
Cet objet sert à identifier une entité sur la scène avec les composantes suivantes : position, rotation, et mise à l’échelle.
Prérequis :
– Savoir initialiser DirectX 10.1
– Savoir qu’il existe une autre classe liée : SceneManager
Explications :
Voici le fichier SceneNode.h :
#ifndef SCENE_NODE_H
#define SCENE_NODE_H
struct AlphaSceneNode
{
MeshSceneNode* m_pNode;
D3DXMATRIX m_concat;
float m_ScreenZ;
// Pour le tri de liste de la STL
bool const operator <(AlphaSceneNode const &other)
{
return m_ScreenZ < other.m_ScreenZ;
}
};
class SceneNode
{
friend class SceneManager;
public:
SceneNode(SceneNode* pParent, const D3DXVECTOR3& position, const D3DXVECTOR3& rotation, const D3DXVECTOR3& scale);
virtual ~SceneNode();
std::string& GetName();
void SetName(const std::string& sName);
bool IsVisible();
void SetVisible(bool bVisible);
unsigned int GetID();
void SetID(unsigned int iID);
void AddChild(SceneNode* pChild);
void RemoveChild(SceneNode* pChild);
void RemoveAll();
D3DXVECTOR3& GetScale();
void SetScale(float x, float y, float z);
D3DXVECTOR3& GetRotation();
void SetRotation(float x, float y, float z);
D3DXVECTOR3& GetPosition();
void SetPosition(const D3DXVECTOR3& position);
void SetPosition(float x, float y, float z);
std::vector<SceneNode*> GetChildren();
void SetParent(SceneNode* pSceneNode);
SceneNode* GetParent();
void RemoveParent();
void Remove();
D3DMATRIX& GetAbsoluteTransformation();
D3DXMATRIX& GetRelativeTransformation();
bool IsReallyVisible() { return true; }
bool IsTransparent();
void SetTransparent(bool bTransparent);
void UpdateRelativeTransformation();
void UpdateAbsoluteTransformation();
virtual void OnRegisterSceneNode() {}
virtual void OnAnimate(float fTimeSinceLastFrame) {}
D3DXVECTOR3 GetAbsolutePosition();
virtual bool OnUpdate(float fTimeSinceLastFrame) { return true; }
protected:
virtual bool OnPreRender(float fTimeSinceLastFrame);
virtual bool OnRender(float fTimeSinceLastFrame) { return true; }
virtual bool OnPostRender(float fTimeSinceLastFrame);
protected:
D3DXVECTOR3 m_RelativeTranslation;
D3DXVECTOR3 m_RelativeRotation;
D3DXVECTOR3 m_RelativeScale;
private:
std::string m_sName;
D3DXMATRIX m_AbsoluteTransformation;
D3DXMATRIX m_RelativeTransformation;
uint32 m_iID;
bool m_bVisible;
SceneNode* m_pParent;
std::vector<SceneNode*> m_children;
bool m_bTransparent;
};
#endif
Voici le fichier SceneNode.cpp :
SceneNode::SceneNode(SceneNode* pParent,
const D3DXVECTOR3& position,
const D3DXVECTOR3& rotation,
const D3DXVECTOR3& scale) :
m_bTransparent(false),
m_bVisible(true),
m_pParent(nullptr),
m_iID(0)
{
m_RelativeTranslation = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_RelativeRotation = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_RelativeScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
D3DXMatrixIdentity(&m_AbsoluteTransformation);
D3DXMatrixIdentity(&m_RelativeTransformation);
UpdateAbsoluteTransformation();
}
SceneNode::~SceneNode()
{
RemoveAll();
}
unsigned int SceneNode::GetID()
{
return m_iID;
}
void SceneNode::SetID(unsigned int iID)
{
m_iID = iID;
}
bool SceneNode::IsVisible()
{
return m_bVisible;
}
void SceneNode::SetVisible(bool bVisible)
{
m_bVisible = bVisible;
}
bool SceneNode::OnPreRender(float fTimeSinceLastFrame)
{
UpdateAbsoluteTransformation();
SCENE_MANAGER->PushAndSetMatrix(m_AbsoluteTransformation);
return true;
}
bool SceneNode::OnPostRender(float fTimeSinceLastFrame)
{
SCENE_MANAGER->PopMatrix();
return true;
}
D3DXVECTOR3& SceneNode::GetPosition()
{
return m_RelativeTranslation;
}
void SceneNode::SetPosition(const D3DXVECTOR3& position)
{
m_RelativeTranslation = position;
UpdateRelativeTransformation();
}
void SceneNode::SetPosition(float x, float y, float z)
{
m_RelativeTranslation = D3DXVECTOR3(x, y, z);
UpdateRelativeTransformation();
}
bool SceneNode::IsTransparent()
{
return m_bTransparent;
}
void SceneNode::SetTransparent(bool bTransparent)
{
m_bTransparent = bTransparent;
}
void SceneNode::UpdateRelativeTransformation()
{
D3DXMATRIX matTrans;
D3DXMatrixTranslation(&matTrans, m_RelativeTranslation.x, m_RelativeTranslation.y, m_RelativeTranslation.z);
D3DXMATRIX matRotX;
D3DXMatrixRotationX(&matRotX, m_RelativeRotation.x);
D3DXMATRIX matRotY;
D3DXMatrixRotationY(&matRotY, m_RelativeRotation.y);
D3DXMATRIX matRotZ;
D3DXMatrixRotationZ(&matRotZ, m_RelativeRotation.z);
D3DXMATRIX matRotation = matRotX * matRotY * matRotZ;
D3DXMATRIX matScale;
D3DXMatrixScaling(&matScale, m_RelativeScale.x, m_RelativeScale.y, m_RelativeScale.z);
// Ordre de la multiplication : S*R*T
m_RelativeTransformation = matScale * matRotation * matTrans;
}
void SceneNode::UpdateAbsoluteTransformation()
{
if (m_pParent)
{
D3DXMATRIX AbsoluteTrans = m_pParent->GetAbsoluteTransformation();
D3DXMATRIX RelativeTrans = GetRelativeTransformation();
D3DXMatrixMultiply(&m_AbsoluteTransformation, &AbsoluteTrans, &RelativeTrans);
}
else
{
m_AbsoluteTransformation = GetRelativeTransformation();
}
}
D3DMATRIX& SceneNode::GetAbsoluteTransformation()
{
UpdateAbsoluteTransformation();
return m_AbsoluteTransformation;
}
D3DXMATRIX& SceneNode::GetRelativeTransformation()
{
UpdateRelativeTransformation();
return m_RelativeTransformation;
}
std::string& SceneNode::GetName()
{
return m_sName;
}
void SceneNode::SetName(const std::string& sName)
{
m_sName = sName;
}
D3DXVECTOR3& SceneNode::GetScale()
{
return m_RelativeScale;
}
void SceneNode::SetScale(float x, float y, float z)
{
m_RelativeScale = D3DXVECTOR3(x, y, z);
UpdateRelativeTransformation();
}
D3DXVECTOR3& SceneNode::GetRotation()
{
return m_RelativeRotation;
}
void SceneNode::SetRotation(float x, float y, float z)
{
m_RelativeRotation = D3DXVECTOR3(x, y, z);
UpdateRelativeTransformation();
}
void SceneNode::AddChild(SceneNode* pChild)
{
if (pChild && (pChild != this))
{
pChild->RemoveParent();
m_children.push_back(pChild);
pChild->SetParent(this);
MeshSceneNode* pChildSceneNode = dynamic_cast<MeshSceneNode*>(pChild);
if (typeid(pChildSceneNode) == typeid(MeshSceneNode*))
{
SCENE_MANAGER->AddSceneNode(pChildSceneNode);
}
}
}
void SceneNode::RemoveChild(SceneNode* pChild)
{
for (auto it = m_children.begin(); it != m_children.end(); it++)
{
SceneNode* pCurrentChild = *it;
if (pCurrentChild == pChild)
{
pCurrentChild->RemoveParent();
m_children.erase(it);
}
}
}
void SceneNode::RemoveAll()
{
for (auto it = m_children.begin(); it != m_children.end(); it++)
{
SceneNode* pCurrentChild = *it;
m_children.erase(it);
}
m_children.clear();
}
void SceneNode::SetParent(SceneNode* pSceneNode)
{
Remove();
m_pParent = pSceneNode;
}
SceneNode* SceneNode::GetParent()
{
return m_pParent;
}
void SceneNode::RemoveParent()
{
m_pParent = nullptr;
}
void SceneNode::Remove()
{
if (m_pParent)
{
m_pParent->RemoveChild(this);
}
}
std::vector<SceneNode*> SceneNode::GetChildren()
{
return m_children;
}
D3DXVECTOR3 SceneNode::GetAbsolutePosition()
{
D3DXVECTOR3 absolutePosition;
absolutePosition.x = m_AbsoluteTransformation._12;
absolutePosition.y = m_AbsoluteTransformation._13;
absolutePosition.z = m_AbsoluteTransformation._14;
return absolutePosition;
}
Résumé :
Nous avons présenté une classe pour gérer les positions, rotations et d’agrandissement de vos entités.
Références :
– Code source d’Irrlicht 3D

