//-------------------------------------------------------------------------
	void Sound::init()
	{
		mBstElemHandle = BST::NULL_HANDLE;
		m3D = false;
		mVolume = 1;
		mEnabled = true;
		mSoundMaxDistance = Math::POS_INFINITY;
		mSoundBoundingBox.setInfinite();
		mSoundBoundingBoxInLocalSpace = true;
		mInVolumeSmoothingTime = 0;
		mOutVolumeSmoothingTime = 0;
		mNumPlayed = 0;
		mPriority = Priority::LOWEST;
		mDestroyOnEnd = false;
		mLoopMode = SoundLoopMode::PLAY_ONCE;
		mMinDelay = 0;
		mMinDelayLengthMultiplier = 0;
		mMaxDelay = 0;
		mMaxDelayLengthMultiplier = 0;
		mSoundGroupEntry = nullptr;
		mSoundPlayInfo = nullptr;
		mSoundScene = nullptr;

		setCastShadows(false);
		setQueryFlags(0);
		setVisibilityFlags(0);
	}
Beispiel #2
0
void Layer::trendDraw(
    Ogre::SceneManager* sm,
    Ogre::SceneNode* sn,
    const trend2d_t& tr
) const {

    assert( (tr.size() > 1) && "Координаты трендов не получены, образ не может быть создан." );

    // Отмечаем тренды
    for (auto itr = tr.cbegin(); itr != tr.cend(); ++itr) {
        auto tbImage = sm->createManualObject();
        int i = 0;
        tbImage->begin( "landscape25/white", Ogre::RenderOperation::OT_LINE_STRIP );

        // @see box2d_t
        const coord2d_t p1 = itr->first;
        const coord2d_t p2 = itr->second;
        tbImage->position( p1.get<0>(),  0.0f,  p1.get<1>() );
        tbImage->index( i ); ++i;
        tbImage->position( p1.get<0>(),  0.0f,  p2.get<1>() );
        tbImage->index( i ); ++i;
        tbImage->position( p2.get<0>(),  0.0f,  p2.get<1>() );
        tbImage->index( i ); ++i;
        tbImage->position( p2.get<0>(),  0.0f,  p1.get<1>() );
        tbImage->index( i );
        tbImage->index( 0 );

        tbImage->end();
        tbImage->setCastShadows( false );
        sn->attachObject( tbImage );
    }
    
}
Beispiel #3
0
 InstancedSponge::InstancedSponge(unsigned recursion, QList<string>& attributes) {
     bufferCount = 1;
     makeSponge(recursion, {0, 0, 0}, 1.0f);
     setMesh(MeshLoader::load(attributes, "cube.obj"));
     calculateBufferSize();
     setCastShadows(false);
 }
Beispiel #4
0
    WireAabb::WireAabb( IdType id, ObjectMemoryManager *objectMemoryManager, SceneManager *manager) :
        MovableObject( id, objectMemoryManager, manager, 0 ),
        Renderable(),
        mTrackedObject( 0 )
    {
        Aabb aabb( Vector3::ZERO, Vector3::UNIT_SCALE );
        mObjectData.mLocalAabb->setFromAabb( aabb, mObjectData.mIndex );
        mObjectData.mWorldAabb->setFromAabb( aabb, mObjectData.mIndex );
        mObjectData.mLocalRadius[mObjectData.mIndex] = aabb.getRadius();
        mObjectData.mWorldRadius[mObjectData.mIndex] = aabb.getRadius();

        createBuffers();

        setCastShadows( false );
        mRenderables.push_back( this );

        this->setDatablock( Root::getSingleton().getHlmsManager()->
                            getHlms( HLMS_UNLIT )->getDefaultDatablock() );
    }
Beispiel #5
0
void Layer::gradientPointDraw(
    Ogre::SceneManager* sm,
    Ogre::SceneNode* sn,
    const surface2d_t& gp
) const {

    assert( (gp.size() > 1) && "Точки перепада не получены." );
    assert( (gp.size() == feature.countGradient)
        && "Количество полученных точек перепада не соотв. ожидаемому." );

    // Создаём образ

    // Каждую точку представим в виде меша
    for (auto itr = gp.cbegin(); itr != gp.cend(); ++itr) {
        const coord2d_t coord = *itr;
        auto point = sm->createEntity( "sphere.mesh" );
        auto childScene = sn->createChildSceneNode();
        childScene->attachObject( point );
        childScene->setPosition( coord.get<0>(),  0.0f,  coord.get<1>() );
    }


    // Соединим точки
    auto image = sm->createManualObject();
    int i = 0;

    image->begin( "landscape25/red", Ogre::RenderOperation::OT_LINE_STRIP );
    for (auto itr = gp.cbegin(); itr != gp.cend(); ++itr) {
        const coord2d_t coord = *itr;
        image->position( coord.get<0>(),  0.0f,  coord.get<1>() );
        image->index( i ); ++i;
    }
    image->end();

    image->setCastShadows( false );

    sn->createChildSceneNode()->attachObject( image );

}
Beispiel #6
0
// Whirler constructor
Whirler::Whirler(String name, Player *player, SceneManager *sceneMgr, String mesh, Vector3 pos, bool managed) : MovingObject(name, sceneMgr, mesh, pos, managed) {
	mType = OTYPE_WHIRLER;
	mRotationSpeed = 3;
	mCurrentSpeed.x = Math::RangeRandom(-10, 10);
	mCurrentSpeed.y = Math::RangeRandom(-10, 10);
	mCurrentSpeed.z = 0;
	mPlayer = player;

	// Flare
	mFlareNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(name + "FlareNode");
	mFlareNode->setPosition(getPosition());
	Entity *ent = mSceneMgr->createEntity(name + "FlareEntity", "Plane.mesh");
	ent->setRenderQueueGroup(Ogre::RENDER_QUEUE_2);
	ent->setCastShadows(false);
	ent->setMaterialName("WhirlerFlare");
	mFlareNode->setScale(10, 10, 10);
	mFlareNode->attachObject(ent);

	setSpeed(65.0f);
	setCastShadows(false);

	// Create the beam trail
    NameValuePairList pairList;
	pairList["numberOfChains"] = "1";
	pairList["maxElements"] = "12";
	mTrail = static_cast<RibbonTrail*>(mSceneMgr->createMovableObject(mName + "Trail", "RibbonTrail", &pairList));
    mTrail->setMaterialName("WhirlerBeamTrail");
	mTrail->setTrailLength(15);
	mTrail->setRenderQueueGroup(Ogre::RENDER_QUEUE_2);

	mSceneMgr->getRootSceneNode()->createChildSceneNode(mName + "TrailNode")->attachObject(mTrail);
	
	mTrail->setInitialColour(0, 1, 0.8f, 0.1f);
	mTrail->setColourChange(0, 4.5f, 5.5f, 4.5f, 0);
	mTrail->setInitialWidth(0, 2);
	mTrail->setWidthChange(0, 2.5f);
	mTrail->addNode(mNode);
}
void Vizi3DWorld::drawNext() {

    // @init load()
    if ( drawItr.empty() ) {
        return;
    }

    // Наносим на холст сразу всю битовую карту текущего элемента

    // Чудесный метод предоставляет нам всю необходимую информацию
    const auto info = *get( drawItr );

    // Пробел - всегда отсутствие элемента
    if (info.signElement != ' ') {

        // Оформлять будем как стат. геометрию
        const std::string signInString = std::string( &info.signElement, 1 );
        Ogre::StaticGeometry* staticScene =
            sm->createStaticGeometry( signInString + "::Vizi3DWorld" );
        //staticScene->setRegionDimensions( ... );


        // Создаём элемент
        const std::string meshName = info.noteElement.form + ".mesh";
        auto e = sm->createEntity( meshName );

        // Фикс для прозрачных материалов
        // @see http://ogre3d.org/forums/viewtopic.php?f=2&t=32172&start=0
        e->setRenderQueueGroup( Ogre::RENDER_QUEUE_9 );

        const std::string materialName = info.noteElement.material;
        if ( !materialName.empty() ) {
            // Заменяем материал по умолчанию
            const auto material = Ogre::MaterialManager::getSingleton().getByName( materialName );

#ifdef TEST_TRANSPARENT_CELL
            // @test Добавляем прозрачность всем материалам
            const auto mt = static_cast< Ogre::Material* >( material.get() );
            mt->setSceneBlending( Ogre::SBT_TRANSPARENT_COLOUR );
            //mt->setParameter( "set_alpha_rejection", "greater 128" );
            mt->setDepthWriteEnabled( false );
            mt->setDepthCheckEnabled( true );
#endif

            e->setMaterial( material );
            e->setCastShadows( true );

        } // if ( !materialName.empty() )
    

        // Размер области
        const size_t N = info.bitContent.size().get<0>();
        const size_t M = info.bitContent.size().get<1>();
        const size_t L = info.bitContent.size().get<2>();

        // Позиционируем область в мировом пространстве
        const float halfN = (float)N / 2.0f;
        const float halfM = (float)M / 2.0f;
        const float halfL = (float)L / 2.0f;
        staticScene->setOrigin( Ogre::Vector3(
            info.coord.get<0>() * info.scaleWorld - halfN * info.scale,
            info.coord.get<1>() * info.scaleWorld - halfM * info.scale,
            info.coord.get<2>() * info.scaleWorld - halfL * info.scale
        ) );


                                                                                                                        /* - Заменено на предварительную подготовку образа в load(). См. ниже.
    // Добавляем элемент в *область*, определяя его расположение благодаря
    // битовой карте области
    for (size_t l = 0; l < L; ++l) {
        for (size_t m = 0; m < M; ++m) {
            for (size_t n = 0; n < N; ++n) {
                // 3D-указатель для определения положения элемента
                const auto c = d::coordInt3d_t( n, m, l );
                // Каждый установленный бит - признак наличия элемента в области
                // @todo optimize Быстрый доступ по 1D-указателю
                if ( info.bitContent.test( c ) ) {
                    staticScene->addEntity(
                        e,
                        // положение элемента, центрируем блок позже
                        Ogre::Vector3(
                            (float)c.get<0>(),
                            (float)c.get<1>(),
                            (float)c.get<2>()
                        ) * info.scale,
                        Ogre::Quaternion::ZERO,
                        Ogre::Vector3( info.scale )
                    );
                }

            } // for (size_t n = 0; n < N; ++n)

        } // for (size_t m = 0; m < M; ++m

    } // for (size_t l = 0; l < L; ++l)
    */

        // Не все элементы требуют отрисовки
        // @see prepareVisualBitImage()
        const auto content = *drawItr.mapElement()->second;
        const auto& alphaBI = *drawItr.tinyMap()->second.visualContent.alphaTypeBitImage;
        const auto& solidBI = *drawItr.tinyMap()->second.visualContent.solidTypeBitImage;
        assert( (alphaBI.raw().size() == solidBI.raw().size()) && "Размеры битовых образов должны совпадать." );
        for (size_t l = 0; l < L; ++l) {
            for (size_t m = 0; m < M; ++m) {
                for (size_t n = 0; n < N; ++n) {
                    // 3D-указатель для определения положения элемента
                    const auto c = d::coordInt3d_t( n, m, l );
                    // Каждый установленный бит - признак наличия элемента в области
                    // @todo optimize Быстрый доступ по 1D-указателю
                    if ( content.test( c )
                      && ( solidBI.test( c ) || alphaBI.test( c ) )
                    ) {
                        staticScene->addEntity(
                            e,
                            // положение элемента в статическом блоке (блок
                            // центрировали раньше)
                            Ogre::Vector3(
                                ((float)c.get<0>() - (float)halfN),
                               -((float)c.get<1>() - (float)halfM),
                               -((float)c.get<2>() - (float)halfL)
                            ) * info.scale,
                            Ogre::Quaternion::ZERO,
#ifdef TEST_VISUAL_CELL
                            Ogre::Vector3( info.scale / 1.80f )
#else
                            Ogre::Vector3( info.scale )
#endif
                        );
                    }

                } // for (size_t n = 0; n < N; ++n)

            } // for (size_t m = 0; m < M; ++m

        } // for (size_t l = 0; l < L; ++l)

        
        // Строим!
        staticScene->build();

    } // if (info.signElement != ' ')


    // Переводим итератор на след. элемент
    ++drawItr;

}
Beispiel #8
0
void Layer::surfaceLineDraw(
    Ogre::SceneManager* sm,
    Ogre::SceneNode* sn,
    const surface2d_t& sl
) const {

    assert( (sl.size() > 1) && "Линия поверхности не получена, образ не может быть создан." );

    // Рисуем образ линии поверхности
    auto slImage = sm->createManualObject();
    int i = 0;


    // Подготавливаем и накладываем текстуру
    // @see http://www.gamedev.ru/code/articles/?id=4191\
    // @see Тест-блоки ниже.
    // Достаточно указать текстурные координаты для каждой вершины. Наложение
    // размазано по построению вершин. См. ниже.

    // @todo Текстура должна заполнять поверхность. Получается - только границы поверхности.

    // Размер объекта, по крайним координатам
    const box2d_t slBox = calcBox( sl );
    const size2d_t slSize = calcSize( slBox );

    // Размер текстуры (материала)
    const std::string materialName = "landscape25/test";
    const size2d_t texture( 1024.0f, 1024.0f );
    // Накладываем 1 текстуру на 1 объект: вычисляем масштаб
    const scale2d_t ts = ONE2D / slSize;

    // Текстурные координаты для вершин
    coord2d_t uv( 0.0f, 0.0f );


    // Рисуем поверхность
    slImage->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_STRIP );
    //slImage->begin( materialName, Ogre::RenderOperation::OT_TRIANGLE_FAN );
    //slImage->begin( materialName, Ogre::RenderOperation::OT_TRIANGLE_STRIP );
    const int firstIndexSL = i;

    /* @test
    slImage->position( 0.0f,    0.0f,  0.0f   ); slImage->index( i ); ++i;
    slImage->position( 100.0f,  0.0f,  0.0f   ); slImage->index( i ); ++i;
    slImage->position( 100.0f,  0.0f, -200.0f ); slImage->index( i ); ++i;
    slImage->position( 0.0f,    0.0f, -200.0f ); slImage->index( i ); ++i;
    slImage->index( 0 );
    */

    /*
    // Создаём текстуру для слоя
    // @source http://www.ogre3d.ru/forum/viewtopic.php?f=8&t=4345
    Ogre::ColourValue diffuse;
    diffuse.a = 0.5f;
    Ogre::MaterialPtr materialPtr =
        Ogre::MaterialManager::getSingleton().create( "Red", "General" );
    Ogre::TextureUnitState* Texture =
        materialPtr->getTechnique(0)->getPass(0)->createTextureUnitState();
    // Задаём параметры отображения текстуры, цвет
    Texture->setColourOperationEx(
        Ogre::LBX_SOURCE1, 
        Ogre::LBS_MANUAL,
        Ogre::LBS_CURRENT, 
        Ogre::ColourValue::Red
    );
    // Режим прозрачности
    materialPtr->getTechnique(0)->getPass(0)->setSceneBlending( Ogre::SBT_TRANSPARENT_ALPHA );
    materialPtr->getTechnique(0)->getPass(0)->setDepthWriteEnabled( false );
    materialPtr->getTechnique(0)->getPass(0)->setDiffuse( diffuse );
    */

    // Получаем координаты крайних точек
    //const coord2d_t first = sl.front();
    //const coord2d_t last = sl.back();
    //const size2d_t size = calcSize( std::make_pair( last, first ) );

    // Рисуем полученную выше линию поверхности
    for (auto itr = sl.cbegin(); itr != sl.cend(); ++itr) {
        const coord2d_t coord = *itr;
        slImage->position( coord.get<0>(), 0.0f, coord.get<1>() );
        slImage->index( i ); ++i;
        // Текстура
        uv = coord * ts;
        slImage->textureCoord( uv.get<0>(), uv.get<1>() );
    }


    // Замыкаем образ внизу по крайним точкам 'sl'
    const coord2d_t lastCoord = sl.back();
    const coord2d_t firstCoord = sl.front();
    const int bottomSpace = 500;
    //const coord2d_t bottomCoord = std::min( lastCoord.get<1>(), firstCoord.get<1>() );
    //const float bottomCoordZ = min<1>( sl ) - bottomSpace;
    // Стабильная нижняя координата смотрится красивее скачущего слоя
    const float bottomCoordZ = -bottomSpace;
    slImage->position(
        lastCoord.get<0>(),
        0.0f,
        bottomCoordZ
    );
    slImage->index( i ); ++i;
    uv = lastCoord * ts;
    slImage->textureCoord( uv.get<0>(), uv.get<1>() );

    slImage->position(
        firstCoord.get<0>(),
        0.0f,
        bottomCoordZ
    );
    slImage->index( i ); ++i;
    uv = firstCoord * ts;
    slImage->textureCoord( uv.get<0>(), uv.get<1>() );

    slImage->index( firstIndexSL );


    // Завершаем построение
    slImage->end();
    slImage->setCastShadows( false );


    const std::string meshName = sn->getName() + "-layer.mesh";
    auto mesh = slImage->convertToMesh( meshName );

    
    // Помещаем объект на сцену
    auto e = sm->createEntity( meshName );
    //e->setMaterialName( "landscape25/test" );
    sn->attachObject( e );



    // <@test>
    // @source http://www.packtpub.com/article/materials-ogre-3d
    /*{
    auto manual = sm->createManualObject( "Quad" );
    manual->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST );
    manual->position( 50.0, 0.0, 0.0 );
    manual->textureCoord( 0, 2 );
    manual->position( -50.0, 0.0, 100.0 );
    manual->textureCoord( 2, 0 );
    manual->position( -50.0, 0.0, 0.0 );
    manual->textureCoord( 2, 2 );
    manual->position( 50.0, 0.0, 100.0 );
    manual->textureCoord( 0, 0 );

    manual->index( 0 );
    manual->index( 1 );
    manual->index( 2 );

    manual->index( 0 );
    manual->index( 3 );
    manual->index( 1 );

    manual->end();

    manual->convertToMesh( "Quad" );

    auto e = sm->createEntity( "Quad" );
    e->setMaterialName( "landscape25/test" );
    //auto node = sn->createChildSceneNode();
    auto node = sm->getRootSceneNode()->createChildSceneNode( "Node1" );
    node->showBoundingBox( true );
    //const Ogre::Quaternion rx( Ogre::Degree( -90 ), Ogre::Vector3::UNIT_X ); 
    //node->rotate( rx );
    node->attachObject( e );
    }*/
    // </@test>


    // <@test>
    // @example http://pastebin.com/MZVQDENZ
    /*{
    const std::string name = "Test2";
    try {
        sm->destroyManualObject( name );
        sm->destroyEntity( name );
        sm->destroySceneNode( name );
    } catch ( ... ) {
    }
    auto m = sm->createManualObject( name );
    m->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_STRIP );
    m->position(   0.0f,  0.0f,    0.0f );  m->textureCoord( 0, 0 );
    m->position(   0.0f,  0.0f, -200.0f );  m->textureCoord( 0, 1 );    
    m->position( 100.0f,  0.0f,    0.0f );  m->textureCoord( 1, 0 );
    m->position( 100.0f,  0.0f, -200.0f );  m->textureCoord( 1, 1 );
    m->index( 0 );  m->index( 1 ); m->index( 2 );
    m->index( 1 );  m->index( 3 ); m->index( 2 );
    m->end();
    auto mesh = m->convertToMesh( name );
    auto e = sm->createEntity( name );
    e->setMaterialName( "landscape25/test" );
    auto node = sm->getRootSceneNode()->createChildSceneNode( name );
    node->showBoundingBox( true );
    node->attachObject( e );
    }*/
    // <@test>


    // <@test>
    // 1 треугольник
    /*{
    const std::string name = "Test3";
    try {
        sm->destroyManualObject( name );
        sm->destroyEntity( name );
        sm->destroySceneNode( name );
    } catch ( ... ) {
    }

    // @source http://www.gamedev.ru/code/articles/?id=4191
    // Вершины треугольника в плоскости XZ
    const coord2d_t a(   0.0f, 0.0f );
    const coord2d_t b(   0.0f, 300.0f );
    const coord2d_t c( 100.0f, 200.0f );

    // Размер объекта, по крайним координатам
    const size2d_t object( 100.0f, 300.0f );

    // Размер текстуры
    const size2d_t texture( 1024.0f, 1024.0f );

    // Накладываем текстуру на объект целиком: вычисляем масштаб
    //const scale2d_t s = texture / object;

    // Размер текселя
    //const size2d_t texel( 1.0f, 1.0f );

    // Рисуем объект, вычисляя текстурные координаты грани
    coord2d_t uv( 0.0f, 0.0f );
    auto m = sm->createManualObject( name );
    m->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST );

    m->position( a.get<0>(), 0.0f, a.get<1>() );
    uv = a / object;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->position( b.get<0>(), 0.0f, b.get<1>() );
    uv = b / object;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->position( c.get<0>(), 0.0f, c.get<1>() );
    uv = c / object;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->triangle( 1, 0, 2 );
    m->end();
    auto mesh = m->convertToMesh( name );
    auto e = sm->createEntity( name );
    e->setMaterialName( "landscape25/test" );
    auto node = sm->getRootSceneNode()->createChildSceneNode( name );
    node->showBoundingBox( true );
    node->attachObject( e );
    }*/
    // <@test>


    // <@test>
    // Фигура из 3 треугольников
    /*{
    const std::string name = "Test3-3";
    try {
        sm->destroyManualObject( name );
        sm->destroyEntity( name );
        sm->destroySceneNode( name );
    } catch ( ... ) {
    }

    // @source http://www.gamedev.ru/code/articles/?id=4191
    // Вершины треугольника в плоскости XZ
    const coord2d_t a(   0.0f,   0.0f );
    const coord2d_t b(   0.0f, 300.0f );
    const coord2d_t c( 100.0f, 200.0f );
    const coord2d_t d( 400.0f, 200.0f );
    const coord2d_t e( 400.0f,   0.0f );

    // Размер объекта, по крайним координатам
    const size2d_t object( 400.0f, 300.0f );

    // Размер текстуры
    const size2d_t texture( 1024.0f, 1024.0f );

    // Накладываем 1 текстуру на 1 объект: вычисляем масштаб
    const scale2d_t s = ONE2D / object;

    // Размер текселя
    //const size2d_t texel( 1.0f, 1.0f );

    // Рисуем объект, вычисляя текстурные координаты грани
    coord2d_t uv( 0.0f, 0.0f );
    auto m = sm->createManualObject( name );
    m->begin( "BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_FAN );
    int i = 0;

    // 1-й треугольник
    m->position( a.get<0>(), 0.0f, a.get<1>() );
    m->index( i );  ++i;
    uv = a * s;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->position( b.get<0>(), 0.0f, b.get<1>() );
    m->index( i );  ++i;
    uv = b * s;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->position( c.get<0>(), 0.0f, c.get<1>() );
    m->index( i );  ++i;
    uv = c * s;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->index( 0 );  m->index( 2 ); m->index( 1 );

    // 2-й треугольник
    m->position( d.get<0>(), 0.0f, d.get<1>() );
    m->index( i );  ++i;
    uv = d * s;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->index( 0 );  m->index( 3 ); m->index( 2 );

    // 3-й треугольник
    m->position( e.get<0>(), 0.0f, e.get<1>() );
    m->index( i );  ++i;
    uv = e * s;
    m->textureCoord( uv.get<0>(), uv.get<1>() );

    m->index( 0 );  m->index( 4 ); m->index( 3 );

    m->end();

    auto mesh = m->convertToMesh( name );
    auto entity = sm->createEntity( name );
    entity->setMaterialName( "landscape25/test" );
    auto node = sm->getRootSceneNode()->createChildSceneNode( name );
    node->showBoundingBox( true );
    node->attachObject( entity );
    }*/
    // <@test>


    


    /* - ?
    unsigned short src, dest;
    if (!mesh->suggestTangentVectorBuildParams( Ogre::VES_TANGENT, src, dest) ) {
        mesh->buildTangentVectors( Ogre::VES_TANGENT, src, dest );
    }
    */

}
Node::NodeSP SceneLoader::__loadLight(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 dir = og_component.firstChildElement(SL_LIGHT_DIRECTION);

            node->setPosition(pos.attribute(SL_X).toFloat(), pos.attribute(SL_Y).toFloat(),
                pos.attribute(SL_Z).toFloat());
            node->setDirection(Ogre::Vector3(dir.attribute(SL_X).toFloat(),
                dir.attribute(SL_Y).toFloat(), dir.attribute(SL_Z).toFloat()));
        }

        //add light component
        auto light = node->addComponent<LightComponent>(new LightComponent(name));
        auto og_light = light->getOgreLight();
        QDomElement colour_diffuse = og_component.firstChildElement(SL_LIGHT_DIFFUSE);
        QDomElement colour_specular = og_component.firstChildElement(SL_LIGHT_SPECULAR);
        QDomElement light_attenuation = og_component.firstChildElement(SL_LIGHT_ATTENUATION);

        //set light attributes
        og_light->setDiffuseColour(colour_diffuse.attribute(SL_COLOUR_R).toFloat(),
            colour_diffuse.attribute(SL_COLOUR_G).toFloat(),
            colour_diffuse.attribute(SL_COLOUR_B).toFloat());
        og_light->setSpecularColour(colour_specular.attribute(SL_COLOUR_R).toFloat(),
            colour_specular.attribute(SL_COLOUR_G).toFloat(),
            colour_specular.attribute(SL_COLOUR_B).toFloat());
        og_light->setAttenuation(light_attenuation.attribute(SL_LIGHT_ATTENUATION_RANGE).toFloat(),
            light_attenuation.attribute(SL_LIGHT_ATTENUATION_CONSTANT).toFloat(),
            light_attenuation.attribute(SL_LIGHT_ATTENUATION_LINEAR).toFloat(),
            light_attenuation.attribute(SL_LIGHT_ATTENUATION_QUADRATIC).toFloat());

        QString light_type = og_component.attribute(SL_LIGHT_TYPE);
        if ( light_type == SL_LIGHT_TYPE_POINT )
        {
            og_light->setType(Ogre::Light::LT_POINT);
        }
        else if ( light_type == SL_LIGHT_TYPE_DIRECTIONAL )
        {
            og_light->setType(Ogre::Light::LT_DIRECTIONAL);
        }
        else if ( light_type == SL_LIGHT_TYPE_SPOT )
        {
            og_light->setType(Ogre::Light::LT_SPOTLIGHT);

            QDomElement light_range = og_component.firstChildElement(SL_LIGHT_RANGE);

            og_light->setSpotlightRange(Ogre::Radian(light_range.attribute(SL_LIGHT_RANGE_INNER).toFloat()),
                Ogre::Radian(light_range.attribute(SL_LIGHT_RANGE_OUTER).toFloat()),
                light_range.attribute(SL_LIGHT_RANGE_FALLOFF).toFloat());
        }

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

        light->enable();
    }

    return node;
}
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;
}