Component based system

Mar 23, 2013 at 11:31 PM
Edited Mar 23, 2013 at 11:35 PM
I want to implement a component based system.

I did it before inside Hiroglyph 3 but i have to modificate alot of classes for this.

I did it inside the Entity class.

so i can do something like:
TransformComponent* transformComponent = myEntity->GetComponent<TransformComponent>();
transformComponent ->Position() = Vector3f(0, 100, 0);

for custom data i can add components as well.

My question is if i dont want to modificate the engine so hard, should i make a subclass of Actor and make there the components?

The modificated version of Hiroglyph with the Component system inside the Entity class works very well but it breaks the engine and i want to have benefits of using unmodified code of Hiroglyph 3 to update the library when something changed.
Coordinator
Mar 23, 2013 at 11:42 PM
That's great that you were able to modify the engine that way - I would be interested to hear more about your solution. In general, you could probably create a separate entity system that is possible to replace the existing entity3d class. It would depend on how you implemented it, but the renderer is designed such that it doesn't explicitly rely on the entity system... This is accomplished by the rendering being performed with the transformation information being passed into the renderer by the parameter manager. So if you want to use totally different entity classes, it should be possible.

Can you describe in more detail what you have implemented? Or even post some additional code? This would give me a better idea of what would be needed to accommodate your changes, and I can give you better advice then.
Mar 23, 2013 at 11:50 PM
Edited Mar 23, 2013 at 11:58 PM
I can post the component modification of the Entity3D class:

A lot of code: the header is full because of the templates.


Entity3D.h
//--------------------------------------------------------------------------------
// This file is a portion of the Hieroglyph 3 Rendering Engine.  It is distributed
// under the MIT License, available in the root of this distribution and 
// at the following URL:
//
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright (c) Jason Zink 
//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
// Entity3D
//
//--------------------------------------------------------------------------------
#ifndef Entity3D_h
#define Entity3D_h
//--------------------------------------------------------------------------------
#include "PCH.h"

#include "Component.h"

#include "Sphere3f.h"

#include "Ray3f.h"
#include "Frustum3f.h"
#include "RendererDX11.h"
#include "PickRecord.h"
#include "MaterialDX11.h"
#include "IController.h"
#include "CompositeShape.h"
#include "EntityRenderParams.h"
#include "ParameterContainer.h"

#include "IEventListener.h"
#include "EventSystem\EventDispatcher.h"

#include <string>
#include <vector>
#include <map>
//--------------------------------------------------------------------------------
namespace Glyph3
{

    struct ComponentConstructor {
        virtual Component* Construct() = 0;
    };

    typedef std::map<std::string, ComponentConstructor*> ComponentMap;

    template<class T>
    struct Constructor : ComponentConstructor {
        Component* Construct() {
            return new T();
        }
    };

    class TransformComponent;
    class MeshRendererComponent;

    class Entity3D : public IEventListener, public EventDispatcher
    {

        friend class TransformComponent;
        friend class MeshRendererComponent;

    public:
        Entity3D( );
        virtual ~Entity3D( );

        //@IEventListener
        virtual bool HandleEvent( EventPtr pEvent );
        virtual std::wstring GetName() { return L""; }

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////
    public:
        int id;

        virtual void Update( float time );

    protected:
        typedef std::map<std::string, Component*> components;
        ComponentMap supportedComponents;

        components _components;

    private:
        //build-in
        TransformComponent* _transformComponent;
        MeshRendererComponent* _meshRendererComponent;

    public:
        TransformComponent* GetTransformComponent();
        MeshRendererComponent* GetMeshRendererComponent();

        std::map<std::string, Component*>& GetComponentMap();


    public:
        /*
        * Attaches the giving Component to the Entity
        * Usage: entity->attachComponent<ComponentName>()
        * Return: void
        */
        template<class T>
        Component* attachComponent() {
            if(isComponentAttached<T>()) return 0;

            const char* name = typeid(T).name();

            ComponentMap::iterator i = supportedComponents.find(name);

            //if there is no component of the type T create a new one.
            if(i == supportedComponents.end()) {
                supportedComponents[name] = new Constructor<T>();
            }

            //create Component.
            ComponentMap::iterator c;

            c = supportedComponents.find(name);
            Component* component = c->second->Construct();
            component->_parent = this;
            component->initNeededComponents();

            _components[name] = component;

            return component;
        }

        /*
        * Attaches the giving Component Instance to the Entity
        * Usage: entity->attachComponent<ComponentName>()
        * Return: void
        */
        template<class T>
        Component* attachComponent(Component* component){
            //TODO: if(isComponentAttached<T>()) return 0;

            const char* name = typeid(T).name();

            ComponentMap::iterator i = supportedComponents.find(name);

            //if there is no component of the type T create a new one.
            if(i == supportedComponents.end()) {
                supportedComponents[name] = new Constructor<T>();
            }

            component->setParent(this);
            component->initNeededComponents();

            _components[name] = component;

            //SCRIPT
            component->configLuaObject(_L);

            return component;
        }

        /*
        * For get a component by string a component must be registered.
        * Example:
        * GameObject::AddAvailableComponent<DisplayObjectComponent>();
        * attachComponent("class DisplayObjectComponent");
        */
        Component* attachComponent(Component* component);

        template<class T>
        T* detachComponent() {
            const char* name = typeid(T).name();

            components::iterator iter = _components.find(name);
            if(iter == _components.end()) {
                return 0;
            } else {
                ComponentMap::iterator iter2 = supportedComponents.find(name);
                if(iter2 == supportedComponents.end()) {

                } else {
                    supportedComponents.erase(iter2);
                }

                T* obj = (T*)iter->second;
                _components.erase(iter);

                return obj;
            }
        }

        /*
        * Gets the giving Component from the entity
        * Usage: entity->getComponent<ComponentName>()
        * returns the full Component class
        */
        template<class T>
        T* getComponent() {
            const char* name = typeid(T).name();

            components::iterator i = _components.find(name);
            if(i == _components.end()) {
                return 0;
            } else {
                return (T*)i->second;
            }
        }

        Component* getComponentById(std::string id);

        /*
        * Checks to see if the giving Component is attached to the entity.
        * Usage: entity->isComponentAttached<ComponentName>()
        * Return: Returns true if the component is attached and false if it isn't
        */
        template<class T>
        bool isComponentAttached() {
            const char* name = typeid(T).name();

            components::iterator i = _components.find(name);
            if(i == _components.end()) {
                return false;
            } else {
                return true;
            }
        }

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////

        virtual void PreRender( RendererDX11* pRenderer, VIEWTYPE view );
        virtual void Render( PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager, VIEWTYPE view );

        // Various entity properties are accessed here.

        int GetEntityID( );

        bool IsHidden( );
        void Hide( bool bHide );

        // Controller support is added here.  There can be multiple controllers which
        // will be updated in the order that they are added to the entity.

        void AttachController( IController* pController );
        IController* GetController( unsigned int index );

        virtual std::string toString( );


        // Static entity population variables

        static int m_iEntityCount;
        static Entity3D* m_pRoot;

        // Scene graph support is added by the following functions.  The graph is enforced
        // by allowing only a single parent, and only Entity3D will be leaf nodes.

        Entity3D* GetParent( );
        Entity3D* GetRoot( );

        void AttachParent( Entity3D* Parent );
        void DetachParent( );

        // Some simple graph structure information is available through these recursive
        // function calls.

        bool IsRelated( Entity3D* Entity );
        int GraphDepth( );

        // The pick record is the correct way to build a list of the entities that are 
        // intersecting the ray.  The other two methods are just as valid, but perform
        // a different type of query than the pick record.

        virtual void BuildPickRecord( Ray3f& ray, std::vector<PickRecord>& record );
        virtual void GetIntersectingEntities( std::vector< Entity3D* >& set, Sphere3f& bounds );
        virtual void GetIntersectingEntities( std::vector< Entity3D* >& set, Frustum3f& bounds );
        virtual void GetEntities( std::vector< Entity3D* >& set );
        
        // The composite shape consists of multiple shapes to represent the entity.
        // It is currently used for ray picking, but will eventually be added to visibility
        // tests, and possibly used to drive the physics shape generation.

        void SetCompositeShape( CompositeShape* pShape );
        CompositeShape* GetCompositeShape( );


    protected:
        // Entity flags
        bool m_bHidden;
    
        Entity3D* m_pParent;
        int m_iEntityID;
        std::vector< IController* > m_Controllers;

    public:
        Sphere3f m_ModelBoundingSphere;
        Sphere3f m_WorldBoundingSphere;

        CompositeShape* m_pComposite;

        friend IController;

    };
};
//--------------------------------------------------------------------------------
#endif // Entity3D_h
Mar 23, 2013 at 11:51 PM
Edited Mar 23, 2013 at 11:58 PM
Entity3D.cpp:
//--------------------------------------------------------------------------------
// This file is a portion of the Hieroglyph 3 Rendering Engine.  It is distributed
// under the MIT License, available in the root of this distribution and 
// at the following URL:
//
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright (c) Jason Zink 
//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
#include "PCH.h"
#include "Entity3D.h"
#include "Log.h"
#include "GeometryDX11.h"
#include "IntrRay3fSphere3f.h"
#include "RenderParameterDX11.h"
#include "IParameterManager.h"

#include "Components\TransformComponent.h"
#include "Components\MeshRendererComponent.h"

//--------------------------------------------------------------------------------
using namespace Glyph3;
//--------------------------------------------------------------------------------
int Entity3D::m_iEntityCount = 0;
Entity3D* Entity3D::m_pRoot = NULL;
//--------------------------------------------------------------------------------
Entity3D::Entity3D()
{
    id = -1;

    // Remember who is the first created - this should always be the root node!!!
    if ( Entity3D::m_pRoot == NULL )
        Entity3D::m_pRoot = this;

    // Record the entity ID
    m_iEntityID = Entity3D::m_iEntityCount++;

    m_pParent = 0;

    m_ModelBoundingSphere.Center.MakeZero();
    m_ModelBoundingSphere.Radius = 1.0f;
    m_WorldBoundingSphere.Radius = 1.0f;

    m_pComposite = new CompositeShape();

    m_bHidden = false;

    //default Components.
    _transformComponent = (TransformComponent*)this->attachComponent<TransformComponent>();
    _meshRendererComponent = (MeshRendererComponent*)this->attachComponent<MeshRendererComponent>();
}
//--------------------------------------------------------------------------------
Entity3D::~Entity3D()
{
    for ( auto pController : m_Controllers )
        delete pController;

    if ( m_pComposite )
        delete m_pComposite;
}

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////

TransformComponent* Entity3D::GetTransformComponent() {
    return _transformComponent;
}

MeshRendererComponent* Entity3D::GetMeshRendererComponent() {
    return _meshRendererComponent;
}

std::map<std::string, Component*>& Entity3D::GetComponentMap() {
    return _components;
}

bool Entity3D::IsHidden()
{
    return( m_bHidden );
}
//--------------------------------------------------------------------------------
int Entity3D::GetEntityID()
{
    return( m_iEntityID );
}
//--------------------------------------------------------------------------------
Entity3D* Entity3D::GetParent()
{
    return( m_pParent );
}
//--------------------------------------------------------------------------------
Entity3D* Entity3D::GetRoot( )
{
    if ( m_pParent )
        return( m_pParent->GetRoot() );
    else
        return( this );
}
//--------------------------------------------------------------------------------
void Entity3D::AttachParent( Entity3D* Parent )
{
    m_pParent = Parent;
}
//--------------------------------------------------------------------------------
void Entity3D::DetachParent( )
{
    m_pParent = NULL;
}
//--------------------------------------------------------------------------------
bool Entity3D::IsRelated( Entity3D* Entity )
{
    if (m_pParent == Entity)
        return(true);
    else
    {
        if (m_pParent)
            if (m_pParent->IsRelated(Entity))
                return(true);
    }
    return(false);
}
//--------------------------------------------------------------------------------
/*
* Update all components.
*/
void Entity3D::Update(float time) {//void GameObject::update(const double fTime, const float fElapsedTime) {
    std::map<std::string, Component*>::iterator iter;
    for(iter = _components.begin(); iter != _components.end(); iter++) {
        if((iter->second)->active) {
            (iter->second)->Update(time);
        }
    }
}

void Entity3D::PreRender( RendererDX11* pRenderer, VIEWTYPE view )
{
    this->_meshRendererComponent->PreRender(pRenderer, view );
}
//--------------------------------------------------------------------------------
void Entity3D::Render( PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager, VIEWTYPE view )
{
    //if(this->_meshRendererComponent != 0) {
        this->_meshRendererComponent->Render(pPipelineManager, pParamManager, view );
    //}
}
//--------------------------------------------------------------------------------
void Entity3D::Hide( bool bHide )
{
    m_bHidden = bHide;
}
//--------------------------------------------------------------------------------
void Entity3D::GetIntersectingEntities( std::vector< Entity3D* >& set, Frustum3f& bounds )
{
    if ( bounds.Intersects( m_WorldBoundingSphere ) )
        set.push_back( this );
}
//--------------------------------------------------------------------------------
void Entity3D::GetIntersectingEntities( std::vector< Entity3D* >& set, Sphere3f& bounds )
{
    if ( bounds.Intersects( m_WorldBoundingSphere ) )
        set.push_back( this );
}
//--------------------------------------------------------------------------------
int Entity3D::GraphDepth( )
{
    if ( m_pParent == NULL )
        return( 0 );
    else
        return( m_pParent->GraphDepth() + 1 );
}
//--------------------------------------------------------------------------------
std::string Entity3D::toString( )
{
    std::stringstream objString;

    for ( int i = 0; i < GraphDepth(); i++ )
    {
        if ( i < GraphDepth() - 1 )
            objString << "| ";
        else
            objString << "+-";
    }

    objString << "Entity3D : ID : " << m_iEntityID << "\n";

    return( objString.str() );
}
//--------------------------------------------------------------------------------
void Entity3D::BuildPickRecord( Ray3f& ray, std::vector<PickRecord>& record )
{
    // If the entity has a composite shape then use it, otherwise simply use
    // the world bounding sphere to check for a hit.

    if ( m_pComposite && ( m_pComposite->GetNumberOfShapes() > 0 ) )
    {
        Matrix4f InvWorld = this->GetTransformComponent()->m_mWorld.Inverse();
        Vector4f position = Vector4f( ray.Origin.x, ray.Origin.y, ray.Origin.z, 1.0f );
        Vector4f direction = Vector4f( ray.Direction.x, ray.Direction.y, ray.Direction.z, 0.0f );
        
        position = InvWorld * position;
        direction = InvWorld * direction;

        Ray3f ObjectRay;
        ObjectRay.Origin.x = position.x;
        ObjectRay.Origin.y = position.y;
        ObjectRay.Origin.z = position.z;
        ObjectRay.Direction.x = direction.x;
        ObjectRay.Direction.y = direction.y;
        ObjectRay.Direction.z = direction.z;

        float fT = 10000000000.0f;
        if ( m_pComposite->RayIntersection( ObjectRay, &fT ) )
        {
            PickRecord Record;
            Record.pEntity = this;
            Record.fDistance = fT;
            record.push_back( Record );
        }
    }
    else
    {
        IntrRay3fSphere3f Intersector( ray, m_WorldBoundingSphere );
        if ( Intersector.Find() )
        {
            PickRecord Record;
            Record.pEntity = this;
            //Record.fDistance = std::min( Intersector.m_afRayT[0], Intersector.m_afRayT[1] ); 
            Record.fDistance = min( Intersector.m_afRayT[0], Intersector.m_afRayT[1] ); 
            record.push_back( Record );
        }
    }
}
//--------------------------------------------------------------------------------
void Entity3D::AttachController( IController* pController )
{
    if ( pController )
    {
        m_Controllers.push_back( pController );
        pController->SetEntity( this );
    }
}
//--------------------------------------------------------------------------------
IController* Entity3D::GetController( unsigned int index )
{
    if ( m_Controllers.size() <= index )
        return( nullptr );

    return( m_Controllers[index] );
}
//--------------------------------------------------------------------------------
void Entity3D::SetCompositeShape( CompositeShape* pShape )
{
    // Delete the existing shape before setting the new one.

    if ( m_pComposite )
        delete m_pComposite;

    m_pComposite = pShape;
}
//--------------------------------------------------------------------------------
CompositeShape* Entity3D::GetCompositeShape( )
{
    return( m_pComposite );
}
//--------------------------------------------------------------------------------
void Entity3D::GetEntities( std::vector< Entity3D* >& set )
{
    set.push_back( this );
}
//--------------------------------------------------------------------------------
bool Entity3D::HandleEvent( EventPtr pEvent ) { 
    std::map<std::string, Component*>::iterator iter;

    //itereate through all components of the gameObject to find the gameObject by name.
    for(iter = _components.begin(); iter != _components.end(); iter++) {
        Component* component = iter->second;

        bool ok = component->HandleEvent(pEvent);
        if(!ok) return false; 
    }

    return true;
}
Mar 23, 2013 at 11:54 PM
Edited Mar 23, 2013 at 11:56 PM
I have did something like this with that
SpriteSheet* spriteSheet = new SpriteSheet(); //Entity3D subclass (inside the Effect will be setuped)

    spriteSheet->GetEffect().Columns() = 4;
    spriteSheet->GetEffect().Rows() = 11;
    spriteSheet->GetEffect().SetDiffuseTexture( std::wstring( L"spritesheets/hulk/hulk_diffuse_960x2640.png" ) );
    spriteSheet->GetEffect().SetNormalTexture( std::wstring( L"spritesheets/hulk/hulk_normal_960x2640.png" ) );
    spriteSheet->GetEffect().SetSpecularTexture( std::wstring( L"spritesheets/hulk/hulk_normal_960x2640.png" ) );
    spriteSheet->GetEffect().SetEmissiveTexture( std::wstring( L"spritesheets/hulk/hulk_normal_960x2640.png" ) );
    spriteSheet->GetEffect().Update(0);

    spriteSheet->GetTransformComponent()->Position() = Vector3f( 0.0f, 0.0f, 0.0f );
    spriteSheet->GetTransformComponent()->Scale() = 0.5;
    spriteSheet->GetTransformComponent()->Pivot() = Vector3f( -128.0f, -128.0f, 0.0f );
    Matrix3f rotation2;
    rotation2.RotationZ( ToRadian(-12.5f) );
    spriteSheet->GetTransformComponent()->Rotation() = rotation2;

    TimelineComponent* timelineComponent = (TimelineComponent*)spriteSheet->attachComponent<TimelineComponent>();
    timelineComponent->AddFrameListener(&spriteSheet->GetEffect());
    timelineComponent->Play();

    Actor* m_pActor_box = new Actor();
    m_pActor_box->GetNode()->AttachChild(spriteSheet);

    m_pScene->AddActor( m_pActor_box );
Mar 23, 2013 at 11:59 PM
Edited Mar 24, 2013 at 12:02 AM
A lot of stuff ...

here is the Component class i forgett it:

Component.h:
/*
*
*/
#pragma once

#ifndef _COMPONENT_H
#define _COMPONENT_H

#include <string>
#include "IEventListener.h"


namespace Glyph3
{
class Entity3D;

class Component {
    friend class Entity3D;

public:
    Component();
    virtual ~Component(void);

    bool active;
    std::string id;

    virtual void Update(float time) = 0;
    virtual void fixedUpdate() = 0;
    virtual void initNeededComponents() = 0;

    virtual bool HandleEvent( EventPtr pEvent ) { return true; }

private:
    Entity3D* _parent;

public:
    Entity3D& GetParent();
    bool HasParent();

};

};

#endif // _COMPONENT_H
Component.cpp:
#include "PCH.h"
#include "Component.h"

#include "Entity3D.h"

using namespace Glyph3;

Component::Component() {
    active = true;
    id = "";

    _parent = 0;
}

Component::~Component(void) {

}

Entity3D& Component::GetParent() {
    return *_parent;
}

bool Component::HasParent() {
    return (_parent != 0);
}
Die TransformComponent und MeshComponent is missing. They are only data representations. I can post it too if you want
Coordinator
Mar 24, 2013 at 12:05 AM
Very interesting - let me take a look through all the code, and I'll get back to you about the required changes. Thanks for posting!
Mar 24, 2013 at 12:24 AM
Edited Mar 24, 2013 at 12:25 AM
The component implementation is mixed with your entity3D code (i seperated the data and functionality of the transformation (TransformComponent) and rendering data (MeshRendererComponent))... so its seems to be a lot of code ..but its more of your code than the component system.
I post the two main components too:

TransformComponent.h
#pragma once

#ifndef _COMPONENT_TRANSFORM_H
#define _COMPONENT_TRANSFORM_H

#include "PCH.h"

//
#include "Vector3f.h"
#include "Vector4f.h"
#include "Matrix3f.h"
#include "Matrix4f.h"
//

#include "..\Component.h"

namespace Glyph3
{
class Entity3D;

class TransformComponent : public Component {
    friend class Entity3D;
    friend class Editor;

public:
    TransformComponent();
    ~TransformComponent(void);

    virtual void Update(float time);
    virtual void fixedUpdate();
    virtual void initNeededComponents();

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////
    protected:
        Vector3f m_vTranslation;    // The translation and rotation varaibles are updated
        Matrix3f m_mRotation;       // during the update phase and used to generate the
        float    m_fScale;          // local matrix.  Then, the world matrix is updated
        
        Vector3f m_vPivot;

        Matrix4f m_mWorld;          // with the new local matrix and the entity's parent
        Matrix4f m_mLocal;          // world matrix.

    public:
        Vector3f& Position( );
        Matrix3f& Rotation( );
        float& Scale( );

        Vector3f& Pivot( );

        virtual void UpdateLocal( float time );
        virtual void UpdateWorld( );

        Matrix4f& LocalMatrix( );
        Matrix4f& WorldMatrix( );
        Matrix4f GetView( );

    public:
        bool m_bCalcLocal;

        void SetLocalMatrixCalculation( bool bCalc );

    public:
        Vector3f LocalToGlobal(Vector3f point);
        Vector3f GlobalToLocal(Vector3f point);
        Vector3f LocalToLocal(Vector3f point, TransformComponent* transformComponent);

    };

};

#endif // _COMPONENT_TRANSFORM_H
TransformComponent.cpp
#include "PCH.h"

#include "TransformComponent.h"
#include "MeshRendererComponent.h"

#include "Entity3D.h"

using namespace Glyph3;

TransformComponent::TransformComponent() {
    id = typeid(*this).name(); //id = "TransformComponent";
    //id = id.substr(6, id.length()-1);

    m_vTranslation.MakeZero();
    m_mRotation.MakeIdentity();
    m_fScale = 1.0f;

    m_vPivot.MakeZero();

    m_mWorld.MakeIdentity();
    m_mLocal.MakeIdentity();

    m_bCalcLocal = true;
}

TransformComponent::~TransformComponent(void) {
    
}

void TransformComponent::Update( float time )
{
    this->UpdateLocal( time );
    this->UpdateWorld( );

    GetParent().GetMeshRendererComponent()->m_sParams.WorldMatrix = this->m_mWorld;
}

void TransformComponent::fixedUpdate(){

}

void TransformComponent::initNeededComponents() {
    
}

//--------------------------------------------------------------------------------
Vector3f& TransformComponent::Pivot()
{
    return( m_vPivot );
}

//--------------------------------------------------------------------------------
Vector3f& TransformComponent::Position()
{
    return( m_vTranslation );
}
//--------------------------------------------------------------------------------
Matrix3f& TransformComponent::Rotation()
{
    return( m_mRotation );
}
//--------------------------------------------------------------------------------
float& TransformComponent::Scale( )
{
    return( m_fScale );
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
void TransformComponent::UpdateLocal( float fTime )
{
    // Update the controllers that are attached to this entity.
    for ( auto pController : GetParent().m_Controllers )
        pController->Update( fTime );

    // Load the local space matrix with the rotation and translation components.
    if ( m_bCalcLocal )
    {
        /* old
        Matrix4f scale;
        scale.Scale( m_fScale );
        
        this->m_mLocal.MakeIdentity();
        this->m_mLocal.SetRotation( this->m_mRotation );
        this->m_mLocal.SetTranslation( this->m_vTranslation);
        this->m_mLocal = scale * this->m_mLocal;
        */

        bool invert = false;

        Matrix4f rotation;
        rotation.MakeIdentity();
        rotation.SetRotation( this->m_mRotation );

        Matrix4f translation;
        translation.MakeIdentity();
        if(invert) {
            translation.SetTranslation( this->m_vTranslation * Vector3f(1, -1, 1));
        } else {
            translation.SetTranslation( this->m_vTranslation);
        }

        Matrix4f scalation;
        scalation.MakeIdentity();
        scalation.Scale( this->m_fScale );

        Matrix4f pivot;
        pivot.MakeIdentity();
        
        if(invert) {
            pivot.SetTranslation( this->m_vPivot * Vector3f(-1, 1, 1) );
        } else {
            pivot.SetTranslation( this->m_vPivot);
        }

        this->m_mLocal = rotation * pivot * scalation * translation; //first make a rotation, than move the vertices by the pivot, scale them and than move it to the right position.
    }
}
//--------------------------------------------------------------------------------
void TransformComponent::UpdateWorld( )
{
    // If the entity has a parent, then update its world matrix accordingly.
    if (GetParent().m_pParent)
        this->m_mWorld = this->m_mLocal * GetParent().m_pParent->GetTransformComponent()->WorldMatrix();
    else
        this->m_mWorld = this->m_mLocal;

    // Update bounding sphere with the new world space position and orientation.
    // TODO: The shape classes should be transformed via matrix functions instead
    //       of manual manipulation like this!

    Vector3f center = GetParent().m_ModelBoundingSphere.Center;
    Vector4f modelposition = Vector4f( center.x, center.y, center.z, 1.0f );
    Vector4f worldposition = this->m_mWorld * modelposition;
    GetParent().m_WorldBoundingSphere.Center = Vector3f( worldposition.x, worldposition.y, worldposition.z );
}
//--------------------------------------------------------------------------------
Matrix4f& TransformComponent::WorldMatrix()
{
    return( this->m_mWorld );
}
//--------------------------------------------------------------------------------
Matrix4f& TransformComponent::LocalMatrix()
{
    return( this->m_mLocal );
}
//--------------------------------------------------------------------------------
Matrix4f TransformComponent::GetView()
{
    Vector3f Eye;
    Vector3f At;
    Vector3f Up;

    Eye = m_mWorld.GetTranslation();
    At = m_mWorld.GetTranslation() + m_mWorld.GetBasisZ();
    Up = m_mWorld.GetBasisY();

    return( Matrix4f::LookAtLHMatrix( Eye, At, Up ) );
}
//--------------------------------------------------------------------------------
void TransformComponent::SetLocalMatrixCalculation( bool bCalc )
{
    m_bCalcLocal = bCalc;
}
//--------------------------------------------------------------------------------
/*
* Transforms the specified x and y position from the coordinate space of the display object
* to the global (stage) coordinate space.
*/
Vector3f TransformComponent::LocalToGlobal(Vector3f point) {
    Vector4f result = this->m_mWorld * Vector4f(point, 1.0f);
    return Vector3f(result.x, result.y, result.z);
}

/*
* Transforms the specified x and y position from the global (stage) coordinate space to the
* coordinate space of the display object.
*/
Vector3f TransformComponent::GlobalToLocal(Vector3f point) {
    Vector4f result = this->m_mWorld.Inverse() * Vector4f(point, 1.0f);
    return Vector3f(result.x, result.y, result.z);
}

/*
* Transforms the specified x and y position from the coordinate space of this display object to the
* coordinate space of the target display object.
*/
Vector3f TransformComponent::LocalToLocal(Vector3f point, TransformComponent* transformComponent) {
    Vector3f result = LocalToGlobal(point);
    return transformComponent->GlobalToLocal(result);
}
Mar 24, 2013 at 12:26 AM
MeshRendererComponent.h:
#pragma once

#ifndef _COMPONENT_MESH_RENDERER_H
#define _COMPONENT_MESH_RENDERER_H

#include "PCH.h"
#include "..\Component.h"

//
#include "EntityRenderParams.h"
#include "ParameterContainer.h"


//

namespace Glyph3 
{
class Entity3D;

class MeshRendererComponent : public Component {
    friend class Entity3D;
    friend class Editor;

public:
    MeshRendererComponent();
    virtual ~MeshRendererComponent(void);

    virtual void Update(float time);
    virtual void fixedUpdate();
    virtual void initNeededComponents();

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////
public:
    void SetMaterial( MaterialPtr pMaterial );
    MaterialPtr GetMaterial( );

    void SetGeometry( ExecutorPtr pExecutor );
    ExecutorPtr GetGeometry( );

public:
    EntityRenderParams m_sParams;
    ParameterContainer Parameters;

public:
    void SetRenderParams( IParameterManager* pParamManager );

    void PreRender( RendererDX11* pRenderer, VIEWTYPE view );
    void Render( PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager, VIEWTYPE view );

//private:
    //void RenderCommand(PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager, VIEWTYPE view);

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////
public:
    void SetMaterial2( MaterialDX11* pMaterial ) {
        //pMaterial
    }

    MaterialDX11* GetMaterial2( ) {
        return m_sParams.Material.get();
    }
    /*
    void SetGeometry2( ExecutorPtr pExecutor );
    ExecutorPtr GetGeometry2( );
    */

};

};

#endif // _COMPONENT_MESH_RENDERER_H
MeshRendererComponent.cpp
#include "PCH.h"

#include "MeshRendererComponent.h"

#include "Entity3D.h"

using namespace Glyph3;

MeshRendererComponent::MeshRendererComponent() {
    id = typeid(*this).name(); //id = "DisplayObjectComponent";
    //id = id.substr(6, id.length()-1);

}

MeshRendererComponent::~MeshRendererComponent(void) {

}

///////////////////////////////////////////////////////////////////////////////////////////////
//                                    COMPONENT SYSTEM                                       //
///////////////////////////////////////////////////////////////////////////////////////////////

void MeshRendererComponent::Update(float time) {

}

void MeshRendererComponent::fixedUpdate(){

}

void MeshRendererComponent::initNeededComponents() {
    
}

///////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                           //
///////////////////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
void MeshRendererComponent::SetMaterial( MaterialPtr pMaterial )
{
    m_sParams.Material = pMaterial;

    // TODO: This could probably be moved to another class, possibly to the 
    //       EntityRenderParams class...  That would avoid duplicating it, and
    //       would put the functionality in the location that it is needed...

    if ( m_sParams.Material != nullptr && m_sParams.Executor != nullptr )
    {
        std::vector<int> idlist;
        m_sParams.Material->GetAllVertexShaderIDs( idlist );

        for ( auto ID : idlist ) {
            m_sParams.Executor->GenerateInputLayout( ID );
        }
    }
}
//--------------------------------------------------------------------------------
MaterialPtr MeshRendererComponent::GetMaterial( )
{
    return( m_sParams.Material );
}
//--------------------------------------------------------------------------------
void MeshRendererComponent::SetGeometry( ExecutorPtr pExecutor )
{
    m_sParams.Executor = pExecutor;

    // TODO: This could probably be moved to another class, possibly to the 
    //       EntityRenderParams class...  That would avoid duplicating it, and
    //       would put the functionality in the location that it is needed...

    if ( m_sParams.Material != nullptr && m_sParams.Executor != nullptr )
    {
        std::vector<int> idlist;
        m_sParams.Material->GetAllVertexShaderIDs( idlist );

        for ( auto ID : idlist ) {
            m_sParams.Executor->GenerateInputLayout( ID );
        }
    }
}
//--------------------------------------------------------------------------------
ExecutorPtr MeshRendererComponent::GetGeometry( )
{
    return( m_sParams.Executor );
}
//--------------------------------------------------------------------------------
void MeshRendererComponent::SetRenderParams( IParameterManager* pParamManager )
{
    // Set the world matrix
    pParamManager->SetWorldMatrixParameter( &m_sParams.WorldMatrix );
    
    // Scroll through each parameter and set it in the renderer
    Parameters.SetRenderParams( pParamManager );
}

void MeshRendererComponent::PreRender( RendererDX11* pRenderer, VIEWTYPE view )
{
    // Perform the pre-render function only if the material has been set
    if ( m_sParams.Material != NULL )
        m_sParams.Material->PreRender( pRenderer, view );
}
//--------------------------------------------------------------------------------
void MeshRendererComponent::Render( PipelineManagerDX11* pPipelineManager, IParameterManager* pParamManager, VIEWTYPE view )
{
    // Test if the entity contains any geometry, and it has a material
    if ( ( m_sParams.Executor != NULL ) && ( m_sParams.Material != NULL ) )
    {
        // Only render if the material indicates that you should
        if ( m_sParams.Material->Params[view].bRender )
        {
            // Set the material render parameters.  This is done before the entity
            // render parameters so that unique values can be set by the individual
            // entities, and still allow the material to set parameters for any
            // entities that don't specialize the parameters.
            m_sParams.Material->SetRenderParams( pParamManager, view );

            // Set the entity render parameters
            this->SetRenderParams( pParamManager );

            // Configure the pipeline with the render effect supplied by the material.
            pPipelineManager->ClearPipelineResources();
            m_sParams.Material->Params[view].pEffect->ConfigurePipeline( pPipelineManager, pParamManager );
            pPipelineManager->ApplyPipelineResources();

            // Let the geometry execute its drawing operation.  This includes 
            // configuring the input to the pipeline, plus calling an appropriate
            // draw call.
            m_sParams.Executor->Execute( pPipelineManager, pParamManager );
        }
    }
}
Mar 24, 2013 at 12:38 AM
Edited Mar 24, 2013 at 5:18 AM
Last words:

I had to change code in all classes that have access to functionality of the entity3D.

The data and functionality are now inside the both components (TransformCompoent, MeshRenderComponent).

For Example instead of:
entity3D->UpdateLocal( time );

change it to:
entity3D->GetTransformComponent()->UpdateLocal( time );

now I can use it and attach and detach data or/and functionality to a entity on runtime. Make a object to a physical object or what ever. Componentsystems are great. (Optimal the TransformComponent should be the only Component that is fix implemented inside the Entity3D class, the MeshRendererComponent should be loose as a custom component(perhaps a definied interface for that))

I will try to make a component system without changing your libraray. I think its not quiet the same. Because i have to write wrapers for the meshRenderComponent and TransformComponent instead of putting the necessary data directly in the Compoents.