//----------------------------------------------------------------------------------------- bool CBillboardSetEditor::load(bool async) { if(mLoaded->get()) return true; if(CNodeEditor::load()) { mBillboardSetHandle = mOgitorsRoot->GetSceneManager()->createBillboardSet(mName->get()); mHandle->attachObject(mBillboardSetHandle); mBillboardSetHandle->setBillboardType((Ogre::BillboardType)mBillboardType->get()); mBillboardSetHandle->setSortingEnabled(mSorting->get()); mBillboardSetHandle->setBillboardOrigin((Ogre::BillboardOrigin)mOrigin->get()); mBillboardSetHandle->setBillboardRotationType((Ogre::BillboardRotationType)mRotation->get()); mBillboardSetHandle->setDefaultWidth(mDefaultWidth->get()); mBillboardSetHandle->setDefaultHeight(mDefaultHeight->get()); mBillboardSetHandle->setVisibilityFlags(1 << mLayer->get()); if(mMaterial->get() != "") mBillboardSetHandle->setMaterialName(mMaterial->get()); mBillboardSetHandle->setPointRenderingEnabled(mPointRendering->get()); mBillboardSetHandle->setRenderingDistance(mRenderDistance->get()); Ogre::Vector2 v2val; Ogre::Vector3 v3val; Ogre::Vector4 v4val; Ogre::ColourValue cval; Ogre::Real rval; int ival; Ogre::String propname; int count = mBillboardCount->get(); for(int ix = 0;ix < count;ix++) { propname = "billboard" + Ogre::StringConverter::toString(ix); Ogre::Billboard *pBillboard = mBillboardSetHandle->createBillboard(Ogre::Vector3::ZERO); mProperties.getValue(propname + "::position", v3val); pBillboard->setPosition(v3val); mProperties.getValue(propname + "::colour", cval); pBillboard->setColour(cval); mProperties.getValue(propname + "::dimensions", v2val); pBillboard->setDimensions(v2val.x, v2val.y); mProperties.getValue(propname + "::rotation", rval); pBillboard->setRotation(Ogre::Degree(rval)); mProperties.getValue(propname + "::texcoordindex", ival); pBillboard->setTexcoordIndex(ival); mProperties.getValue(propname + "::texrect", v4val); pBillboard->setTexcoordRect(v4val.x, v4val.y, v4val.z, v4val.w); } } else return false; return true; }
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 ) ) }