Page 1 of 1

OgreMeshTool, LODs and v2 format

Posted: Tue Aug 15, 2017 7:24 pm
by Hrenli
Hi,

I am trying to get autogenerated LODs directly to v2 .mesh file using OgreMeshTool. Everything seems to work fine if I use v1 format. If I try to generate LODs directly into v2 format I am getting this error:
LOD Generation only works on v1 meshes at the moment.
Export it as -v1, run the command again, and re-export it to -v2
If I follow the error's suggestion by running:
OgreMeshTool.exe -autogen file.mesh.xml
OgreMeshTool.exe -v2 file.mesh
LODs seems to get lost from the file during second step no matter what... Is it me doing something stupid or it's not possible to get v2 .mesh file with LODs inside at the moment?

Re: OgreMeshTool, LODs and v2 format

Posted: Tue Aug 15, 2017 11:40 pm
by SolarPortal
Hi, i know this isnt for the OgreMeshTool.exe, but i had troubles when doing it in c++ and generating a manual v2 mesh that needed lods.
The problem stemmed from not being able to set the lod values to the v2 mesh / submesh and save to disk; so i made these changes:

* Add an additional 3 commands to OgreMesh2.cpp at around line 400: ( I only used the last 2 functions )

Code: Select all

    
...   
        const LodValueArray* _getLodValueArray(void) const                      { return &mLodValues; }
        void clearLodValues() { mLodValues.clear(); }
        void setLodValue(Ogre::Real index) { mLodValues.push_back(index); }
...
* Compile and then run in your app with this sort of function:

Code: Select all

void setupLodValues(int numLods, Ogre::MeshPtr mesh)
{
	Ogre::Real distances[5] = { 0, 20, 40, 50, 60 };
	mesh->clearLodValues();
	for (int i = 0; i < numLods; i++){
		mesh->setLodValue(distances[i]);
	}
}
As long as you add the lod vao to the submesh with something similar to this:

Code: Select all

	
	...	
	Ogre::VertexArrayObject* lodvao = vaoManager->createVertexArrayObject(vertexBuffers, indexBuffer, Ogre::OT_TRIANGLE_LIST);
	subMesh->mVao[Ogre::VpNormal].push_back( lodvao );
	subMesh->mVao[Ogre::VpShadow].push_back( lodvao );
	...
then you can add your own lod meshes and it will save to the v2 mesh format and can be read back from the file.

Hope this helps :)

Re: OgreMeshTool, LODs and v2 format

Posted: Wed Aug 16, 2017 2:37 am
by dark_sylinc
I should probably add this to my TODO list. I didn't know it was broken.

Thanks for posting the workaround :)

Re: OgreMeshTool, LODs and v2 format

Posted: Wed Aug 16, 2017 2:33 pm
by SolarPortal
no problem :)

Re: OgreMeshTool, LODs and v2 format

Posted: Thu Aug 17, 2017 11:12 am
by Hrenli
Thanks SolarPortal, I played with loading of different files a bit more and you are right. It seems that mLodValues is the only thing which is really missing. mNumLods is always 1 nowdays for v2 meshes but it seems not to be used at all. And mVao-s for submeshes seem to be loading correctly already with LODs.

Re: OgreMeshTool, LODs and v2 format

Posted: Fri May 22, 2020 12:23 am
by TaaTT4
What's the status of this?
I mean, is it possible to generate LODs for a v1 mesh (using ogremeshtool or ogremeshlod library), import it in a v2 mesh and then have LODs working in the created item?

Re: OgreMeshTool, LODs and v2 format

Posted: Fri May 22, 2020 12:38 am
by dark_sylinc
Honestly I don't remember (probably not fixed)

Re: OgreMeshTool, LODs and v2 format

Posted: Fri May 22, 2020 7:42 am
by Zonder
dark_sylinc wrote:
Fri May 22, 2020 12:38 am
Honestly I don't remember (probably not fixed)
Not quite clear on this. Was it broken and you put a fix in for it?

Re: OgreMeshTool, LODs and v2 format

Posted: Fri May 22, 2020 4:50 pm
by dark_sylinc
I don't remember taking a look at any of the LOD bugs mentioned in this post, hence it's likely that it's not fixed.
But I can't be sure.

Re: OgreMeshTool, LODs and v2 format

Posted: Thu May 28, 2020 4:48 pm
by TaaTT4
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.

Image Image Image Image

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).

Re: OgreMeshTool, LODs and v2 format

Posted: Thu May 28, 2020 5:46 pm
by dark_sylinc
Nice detective work!

It's clear that "artist-friendly" values should be exposed to the user, but internally we should convert those values back and forth to whatever is more efficient for us.
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.
Order-of-execution bugs strike again!
We'll have to do some workaround, because we can't call setRenderPassDescToCurrent() before doing executing the shadow node (well we can... but it'd cost performance), and we need the LODs calculated before running the shadow node. Chicken and egg problem.
Fortunately all the LOD calculations care about is viewport sizes, and that is something we can provide.

I still advocate we use negative values for LOD sorting. It's just that as you pointed out, instead of using 0 for LOD0, we use a large negative value. We need to ensure a 0 doesn't slip through to LOD0 when using Pixel count strategies.