Example #1
0
void GasCellPort::cellDraw( const coordInt2d_t& coord ) const {

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

    // Содержимое ячейки представим в виде меша

    const int i = helper::ic( coord.get<0>(), coord.get<1>(), N, M );
    assert( (i != -1) && "Получена координата за пределами матрицы порта." );
    const GasFD c = content[i];
    if (c.uid == 0) {
        // Вакуум не показываем
        return;
    }

    
#if 0
    // - Медленно. Переписано через биллборды.
    /*
    const std::string name =
        "smoke-pressure-"
      + Ogre::StringConverter::toString( (int)c.pressure );
    */
    const std::string meshName = "sphere.mesh";
    /* - @todo Так ли каждый раз нужна новая сущность?
    const std::string entityName = meshName + ".entity";
    const bool has = sm->hasEntity( entityName );
    Ogre::Entity* image = has ?
        sm->getEntity( entityName ) :
        sm->createEntity( entityName, meshName );
    */
    Ogre::Entity* image = sm->createEntity( meshName );
    auto childScene = sn->createChildSceneNode();
    childScene->attachObject( image );
    // Координаты образа кратны масштабу
    childScene->setPosition(
        (float)coord.get<0>() * scale,
        0.0f,
        (float)coord.get<1>() * scale
    );
    // Образ заполняет ячейку целиком
    //const Ogre::Vector3 fillScale( scale / image->getBoundingRadius() );
    //childScene->setScale( fillScale );
#endif

    // Работаем через биллборды
    // @source http://89.151.96.106/forums/viewtopic.php?f=10&t=60455

    const float S = scale * visualScale;

    // Готовим биллборды при первом обращении к ним
    // @todo Визаулизировать в зависимости от характеристики ячейки и соседей.
    std::string bsName = "GasCellPort-bs";
    Ogre::BillboardSet* bs = nullptr;
    if ( sm->hasBillboardSet( bsName ) ) {
        bs = sm->getBillboardSet( bsName );

    } else {
        // Дым - один образ на всю ячейку
        bs = sm->createBillboardSet( bsName, count() );
        bs->setAutoextend( false );
        const std::string prefixMaterial = "smokeport2d/smoke-";
        const std::string nameMaterial = prefixMaterial + "0";
        bs->setMaterialName( nameMaterial );
        bs->setBillboardType( Ogre::BBT_PERPENDICULAR_COMMON );
        bs->setCommonUpVector( Ogre::Vector3::UNIT_Z );
        bs->setCommonDirection( -Ogre::Vector3::UNIT_Y );
        bs->setBillboardsInWorldSpace( true );
        bs->setBillboardOrigin( Ogre::BBO_CENTER );
        bs->setDefaultDimensions( S, S );
        sn->attachObject( bs );
    }

    // Позиционируем биллборд
    Ogre::Billboard* b = bs->createBillboard(
        (float)coord.get<0>() * S,
        0.0f,
        (float)coord.get<1>() * S
    );
    //b->setRotation( Ogre::Degree( (float)rand() ) );

}
void CellDrawActor< C >::allDraw(
    const AllDrawMessage< C >& m
) {
    // Рисуем только если ещё не было нарисовано
    // или по просьбе "обновлять постоянно"
    const std::string sceneName = "CellDrawActor::allDraw::Scene";
    const std::string bsName = "CellDrawActor::allDraw::BillboardSet";

    // @test
    /*
    try {
        m.sm->getRootSceneNode()->removeAndDestroyChild( sceneName );
    } catch ( ... ) {
    }
    try {
        m.sm->destroyBillboardSet( bsName );
    } catch ( ... ) {
    }
    */

    if ( m.update || !m.sm->hasSceneNode( sceneName ) ) {

        // Каждому образу - свой холст (общая сцена)
        auto scene = m.sm->hasSceneNode( sceneName ) ?
            m.sm->getSceneNode( sceneName ) :
            m.sm->getRootSceneNode()->createChildSceneNode( sceneName );

        // Определяем общее кол-во элементов
        const size_t NM = m.N * m.M;

        // Готовим биллборды

        // Обращаются за отрисовкой первый раз?
        const bool virgin = m.sm->hasBillboardSet( bsName );
        Ogre::BillboardSet* bs = nullptr;
        if ( virgin ) {
            bs = m.sm->getBillboardSet( bsName );

        } else {
            // Один образ для всех ячеек
            // @todo Расширить кол-во образов.
            bs = m.sm->createBillboardSet( bsName, NM );
            bs->setAutoextend( true );
            const std::string nameMaterial = m.prefixMaterial + "0";
            bs->setMaterialName( nameMaterial );
            bs->setBillboardType( Ogre::BBT_PERPENDICULAR_COMMON );
            bs->setCommonUpVector( Ogre::Vector3::UNIT_Z );
            bs->setCommonDirection( -Ogre::Vector3::UNIT_Y );
            bs->setBillboardsInWorldSpace( true );
            bs->setBillboardOrigin( Ogre::BBO_CENTER );
            bs->setDefaultDimensions( m.scale, m.scale );
            bs->setUseAccurateFacing( false );
            scene->attachObject( bs );
        }

        // Визуализируем каждую ячейку

        /* - @todo Можно ускорить отрисовку > http://www.ogre3d.org/forums/viewtopic.php?f=2&t=11134&start=0
        Ogre::Billboard b = Ogre::Billboard( Ogre::Vector3::ZERO, bs );
        b.setColour( Ogre::ColourValue::White );
        b.setRotation( Ogre::Degree( (float)rand() ) );
        */

        //bs->beginBillboards();
        for (size_t z = 0; z < m.M; ++z) {
            for (size_t x = 0; x < m.N; ++x) {
                const coordInt2d_t coord( (int)x, (int)z );

                // Создадим образ ячейки с указанной координатой

                const int i = helper::ic( coord.get<0>(), coord.get<1>(), m.N, m.M );
                assert( (i != -1) && "Получена координата за пределами матрицы порта." );
                const C c = m.content[i];

                // Биллборд уже мог быть создан ранее
                const auto bi = helper::index( *bs, coord, m.scale );
                if (bi != -1) {
                    bs->removeBillboard( bi );
                }

                if (c.uid == 0) {
                    // Вакуум - отсутствие образа
                    continue;
                }
    
#if 0
                // - Медленно. Переписано через биллборды.
                /*
                const std::string name =
                    "smoke-pressure-"
                  + Ogre::StringConverter::toString( (int)c.pressure );
                */
                const std::string meshName = "sphere.mesh";
                /* - @todo Так ли каждый раз нужна новая сущность?
                const std::string entityName = meshName + ".entity";
                const bool has = sm->hasEntity( entityName );
                Ogre::Entity* image = has ?
                    sm->getEntity( entityName ) :
                    sm->createEntity( entityName, meshName );
                */
                Ogre::Entity* image = sm->createEntity( meshName );
                auto childScene = sn->createChildSceneNode();
                childScene->attachObject( image );
                // Координаты образа кратны масштабу
                childScene->setPosition(
                    (float)coord.get<0>() * scale,
                    0.0f,
                    (float)coord.get<1>() * scale
                );
                // Образ заполняет ячейку целиком
                //const Ogre::Vector3 fillScale( scale / image->getBoundingRadius() );
                //childScene->setScale( fillScale );
#endif

                // Работаем через биллборды
                // @source http://89.151.96.106/forums/viewtopic.php?f=10&t=60455

                // @todo Визаулизировать в зависимости от характеристики ячейки и соседей.

                // Позиционируем биллборд

                Ogre::Billboard* b = bs->createBillboard(
                    (float)coord.get<0>() * m.scale,
                    0.0f,
                    (float)coord.get<1>() * m.scale
                );
                b->setRotation( Ogre::Degree( (float)rand() ) );
                /*
                b.setPosition(
                    (float)coord.get<0>() * m.scale,
                    0.0f,
                    (float)coord.get<1>() * m.scale
                );
                bs->injectBillboard( b );
                */
                
                // @test
                //break;

            } // for (size_t x = 0; x < m.N; ++x)

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

        //bs->endBillboards();

    } // if ( m.update || !m.sm->hasSceneNode( sceneName ) )

}