Archives pour la catégorie Conception de moteur 3D

Une classe SceneNode pour représenter vos objets et entités dans la scène

graphe

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