The good news: the LOD system works even for V2 meshes!. The bad news: the strategies based on pixels count (in my opinion, the most useful ones) are fucked as hell (and you will also experience a crash trying them).
Let's start from the good news.
Code: Select all
LodStrategyManager::getSingleton().setDefaultStrategy(DistanceLodSphereStrategy::getSingletonPtr());
v1::MeshPtr mesh_v1 = v1::MeshManager::getSingleton().load("Sinbad.mesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
LodConfig config(mesh_v1, LodStrategyManager::getSingleton().getDefaultStrategy());
config.createGeneratedLodLevel(10.0f, 0.25f, LodLevel::VRM_PROPORTIONAL);
config.createGeneratedLodLevel(20.0f, 0.50f, LodLevel::VRM_PROPORTIONAL);
config.createGeneratedLodLevel(30.0f, 0.75f, LodLevel::VRM_PROPORTIONAL);
MeshLodGenerator generator;
generator.generateLodLevels(config);
MeshPtr mesh_v2 = MeshManager::getSingleton().createManual("Sinbad_lod.mesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
mesh_v2->importV1(mesh_v1.get(), false, false, true);
Item* item = m_sceneManager->createItem(mesh_v2, SCENE_STATIC);
SceneNode* node = m_sceneManager->getRootSceneNode()->createChildSceneNode(SCENE_STATIC);
node->attachObject(item);
The code here above generates three LOD levels for the v1 Sinbad.mesh:
- at 10.0 units distance, reduce vertices count by 25%
- at 20.0 units distance, reduce vertices count by 50%
- at 30.0 units distance, reduce vertices count by 75%
The v1 mesh is then imported into a v2 mesh and an
Item is created from it. As you can see from the images here below, OGRE correctly picks a different LOD level based on the distance of the camera from the mesh.
Let's move on to the broken things.
First thing first, inside the implementations of the
PixelCountLodStrategyBase::lodUpdateImpl, a
nullptr is returned when you take the
Viewport object from the camera. This happens because the viewport is binded to the camera when
CompositorPass::setRenderPassDescToCurrent is invoked, but this happens AFTER the LODs evaluation step (call to
sceneManager->updateAllLods in
CompositorPassScene::execute). Matias, could you please fix it? It's quite impossible to create a pixels count based strategy without viewport infos.
Secondarily, pixels count based strategies cannot work as the LOD picking code works right now. In
LodStrategy::lodSet which LOD to use is chosen by a
std::lower_bound algorithm which, to work as intended, needs an ascending ordered
vector. This is true for the distance based strategies, while it's not for the pixels count based ones. Indeed, in distance based strategies the distance increases while the camera steps away from the object, while the contrary happens in pixels count based strategies: the pixels count increases while the camera approaches the object. I guess that this discrepancy between the two family of strategies was taken in account in OGRE 1.x (see
here and
here), but the code to handle it has been lost/not ported in OGRE 2.x (
MeshLodUsageList is commented out in v2
Mesh class).
I see two viable solutions. The first is to subtract pixels count from the total of pixels (e.g. instead of "when objects cover
x pixels, reduce vertices count by
y%" do "when objects doesn't cover
total - x pixels, reduce vertices count by
y%"). The second is to negate the pixels count value. In particular, I believe the latter is the solution that OGRE pursues, but it doesn't work as it is right now. This because
MovableObject::mLodMesh always contains a
0.0 value as first element (the LOD value of the original mesh). Probably, sort
MovableObject::mLodMesh here and
here, when the LOD has been generated for a pixels count based strategy, would solve the issue (but I don't know how much is safe to do this).