void PhysicsBodyComponent::onInitialize() {
    if(! mNode->hasComponent(mMeshComponentName)) {
        Logger::get().error("Node " + mNode->getName() + " has no Component named " +
                            mMeshComponentName + " which is required to create the" +
                            " PhysicsBodyComponent " + mName);
        exit(1);
    }

    auto mesh_component = mNode->findComponent<MeshComponent>(mMeshComponentName);

    BtOgre::StaticMeshToShapeConverter converter(mesh_component->getOgreEntity());
    
    // TODO: CollisionShapes should likely be stored at a central place.
    // Perhaps the PhysicsManager is a good place. It would save a lot of memory
    // for many bodies with the same CollisionShape.
    if(mCollisionShapeType == BOX) {
        Ogre::Vector3 size = mesh_component->getOgreEntity()->getBoundingBox().getSize();
        size /= 2.0;

        mCollisionShape = new btBoxShape(BtOgre::Convert::toBullet(size));
        //mCollisionShape = converter.createBox();
    }
    else if(mCollisionShapeType == CONVEX)
        mCollisionShape = converter.createConvex();
    else if(mCollisionShapeType == SPHERE) {
        mCollisionShape = new btSphereShape(mesh_component->getOgreEntity()->getBoundingRadius());
    }
    else if(mCollisionShapeType == CYLINDER) {
        Ogre::Vector3 size = mesh_component->getOgreEntity()->getBoundingBox().getSize();
        size /= 2.0;
        mCollisionShape = new btCylinderShape(BtOgre::Convert::toBullet(size));
    }
    else if(mCollisionShapeType == TRIMESH)
        mCollisionShape = converter.createTrimesh();

    mCollisionShape->setLocalScaling(BtOgre::Convert::toBullet(this->getNode()->getScale()));
    btVector3 inertia(0, 0, 0);
    //Only the rigidbody's mass doesn't equal to zero is dynamic or some odd phenomenon may appear.
    if(mMass != 0.0f)
        mCollisionShape->calculateLocalInertia(mMass, inertia);

    btDefaultMotionState* state = new btDefaultMotionState(
        btTransform(BtOgre::Convert::toBullet(getNode()->getRotation(Node::SCENE)),
        BtOgre::Convert::toBullet(getNode()->getPosition(Node::SCENE))));

    //Here's the most tricky part. You need to give it 5.0 as its temporary mass.
    //Or you will find your player character keeps falling down no matter there's a ground.
    //Its real mass will be set in OnEnable().
    mBody = new btRigidBody(5.0, state, mCollisionShape, inertia);

    std::cout << mCollisionShape->getLocalScaling().getY() << std::endl;

    // Store pointer to this PhysicsBodyComponent for later retrieval (for
    // collisions, for instance)
    mBody->setFriction(1.0);
    mBody->setUserPointer((void *)(this));
}
Node::NodeSP SceneLoader::__loadMesh(const QDomElement& og_component, Node::NodeSP dt_node)
{
    Node::NodeSP node = dt_node;

    if ( !og_component.isNull() )
    {
        QString name = og_component.attribute(SL_NAME);

        if ( node == nullptr )
        {
            node = mScene->addChildNode(new Node(name + "_node"));

            QDomElement pos = og_component.firstChildElement(SL_POS);
            QDomElement rot = og_component.firstChildElement(SL_ROT);
            QDomElement scale = og_component.firstChildElement(SL_SCALE);

            node->setPosition(pos.attribute(SL_X).toFloat(), pos.attribute(SL_Y).toFloat(),
                pos.attribute(SL_Z).toFloat());
            node->setRotation(Ogre::Quaternion(rot.attribute(SL_QW).toFloat(),
                rot.attribute(SL_QX).toFloat(), rot.attribute(SL_QY).toFloat(), rot.attribute(SL_QZ).toFloat()));
            node->setScale(Ogre::Vector3(scale.attribute(SL_X).toFloat(), scale.attribute(SL_Y).toFloat(),
                scale.attribute(SL_Z).toFloat()));
        }

        QDomElement unknown_mesh = og_component.firstChildElement(SL_SCALE).nextSiblingElement();
        if ( unknown_mesh.nodeName() == SL_MESH_ENTITY )
        {
            const QDomElement& entity = unknown_mesh;

            //add mesh component
            auto mesh = node->addComponent<MeshComponent>(
                new MeshComponent(entity.attribute(SL_MESH_HANDLE), "", entity.attribute(SL_NAME))
                );

            //set entity attributes
            for ( QDomElement mat = entity.firstChildElement(); !mat.isNull(); mat = mat.nextSiblingElement() )
            {
                QString material_handle = mat.attribute(SL_MESH_ENTITY_MATERIAL_NAME);
                uint32_t index = mat.attribute(SL_MESH_ENTITY_INDEX).toUInt();

                mesh->getOgreEntity()->getSubEntity(index)->setMaterialName(material_handle.toStdString());
            }

            QString cast_shadows = entity.attribute(SL_CAST_SHADOWS);
            if ( cast_shadows == SL_TRUE )
            {
                mesh->setCastShadows(true);
            }
            else if ( cast_shadows == SL_FALSE )
            {
                mesh->setCastShadows(false);
            }

            mesh->enable();
        }
        else if ( unknown_mesh.nodeName() == SL_MESH_PLANE )
        {
            const QDomElement& plane = unknown_mesh;
            if ( !plane.isNull() )
            {
                //create plane
                OgreProcedural::PlaneGenerator()
                    .setSizeX(plane.attribute(SL_MESH_PLANE_SIZEX).toFloat())
                    .setSizeY(plane.attribute(SL_MESH_PLANE_SIZEY).toFloat())
                    .setEnableNormals(plane.attribute(SL_MESH_PLANE_ENABLE_NORMALS).toInt())
                    .setNumSegX(plane.attribute(SL_MESH_PLANE_SEGMENTSX).toInt())
                    .setNumSegY(plane.attribute(SL_MESH_PLANE_SEGMENTSY).toInt())
                    .setNumTexCoordSet(plane.attribute(SL_MESH_PLANE_NUMTEXCOORD).toInt())
                    .setUTile(plane.attribute(SL_MESH_PLANE_UTILE).toFloat())
                    .setVTile(plane.attribute(SL_MESH_PLANE_VTILE).toFloat())
                    .setNormal(Ogre::Vector3( plane.firstChildElement(SL_MESH_PLANE_NORMAL).attribute(SL_X).toFloat(),
                    plane.firstChildElement(SL_MESH_PLANE_NORMAL).attribute(SL_Y).toFloat(),
                    plane.firstChildElement(SL_MESH_PLANE_NORMAL).attribute(SL_Z).toFloat()))
                    .realizeMesh(plane.attribute(SL_NAME).toStdString());

                //add mesh component
                auto mesh = node->addComponent<MeshComponent>(
                    new MeshComponent(plane.attribute(SL_NAME), plane.attribute(SL_MESH_PLANE_MATERIAL), plane.attribute(SL_NAME))
                    );

                mesh->enable();
            }
        }
    }

    return node;
}