It is the one that allows to optimize a single or a set of meshes.
This can be done in 2 ways:
- Static optimization:
In this scenario meshes are optimized once for all. You define a target ratio, get the result and forget optimization.
This is less consumptive in term of memory requirements, but less convenient to use, particularly if you intend to modify repeatedly the level of details of the scene. - Dynamic optimization
In this scenario meshes optimization is pre-computed. You can then modify the optimization ratio in real time of accordingly to specific needs.
Preparing the input scene to optimize
Whatever the scenario CSceneOptimizer requires an input scene.
This scene contains one or more meshes, converted from your own data format to the SDK node's format.
As only geometric entities are taken into account, you can omit group or even parent relationship.
But, if you intend to use the output format feature of the SDK, you should make a proper and complete conversion of your scene.
CSceneOptimizer has a specific requirements: it can only optimize C3DExtObject.
If you convert you own data you can create directly C3DExtObject instead of using C3DObject.
If you import the data from an external file, the resulting C3DScene will contains C3DObject which has to be converted into C3DExtObject.
In such case, the operation is very easy:
Code: Select all
// CSceneOptimizer needs C3DExtObject to works. Very important !
// These line perform the conversion. You can remove it if you already have C3DExtObject
C3DPolygonCruncherObjectCreator cruncherCreator(DEFAULT_OPTIMIZATION_OBJECT);
scene->ConvertToType(NULL, &cruncherCreator);
Code: Select all
CSceneOptimizer *optimizer = xNew(CSceneOptimizer);
optimizer->SetScene(*scene, true); // The scene will be deleted by the optimizer. Set false if you want to delete it yourself otherwise take care to use xNew
Note that we consider the static optimization case. The following setting must set to off:
Code: Select all
optimizer->SetFlag(SCENEOPTIMIZER_TRACK_CHANGES, false); // Setting this off matches static optimization case, setting it to true means dynamic optimization.
Some object in the scene might have a lot number of faces, some others not. Using progressive optimization will differentiate the optimization ratio for each individual object, instead of applying the same ratio to the whole set of meshes.
Code: Select all
optimizer->SetFlag(SCENEOPTIMIZER_PROGRESSIVE_RATIO, true); // This line has no effect if you have a single mesh.
You may expose these settings to the user. Have a look at Polygon Cruncher and the way it exposed the different setting to the user.
Note that if you omit a setting, you remove the corresponding information in the output scene.
- If you don't set OPTIMIZE_KEEP_UV, the UV will be removed from the input mesh.
- If you don't set OPTIMIZE_KEEP_NORMALS, the normals will be removed from the input mesh
Code: Select all
#define DEFAULT_OPTIMIZATION_MODE OPTIMIZE_PROTECT_BORDER|OPTIMIZE_VERIFY_PAIRS_MASK|OPTIMIZE_KEEP_MATERIAL_FRONTIER|OPTIMIZE_PROTECT_MATERIAL_FRONTIER
// Define some optimization settings
optimizer->LockInitialization();
optimizer->SetOptimizeMode(DEFAULT_OPTIMIZATION_MODE, true);
// These are optionals and depend on the input settings, if there is UV or not, if you optimize taking care of the symmetry...
optimizer->SetUVWTolerance(0.0f);
optimizer->SetSymetryTolerance(0.01f);
optimizer->SetVCTolerance(0.1f);
optimizer->UnlockInitialization();
In case of static optimization, we will directly get a scene at the specified level of details.
We will not have the ability to change this LOD dynamically. Static optimization is the case when SCENEOPTIMIZER_TRACK_CHANGES flag is set to false (default case)
So the important thing is to define the budget ratio you need. There is several way to do this:
Code: Select all
optimizer->Optimize(0.5f, cancel);
Take care, this is not 50% of the total faces number, as some might be not removable.
This is the easiest way to use Optimize, but ratio might give unpredictable number of faces as it is computed on the optimizable number of faces.
Code: Select all
optimizer->Optimize(yourPolygonBudget, cancel, OPTIMIZE_TO_NBR|OPTIMIZE_TO_FACE);
This target can be unreachable if yourPolygonBudget < optimizer->GetInitialRemovableFacesNumber()
Code: Select all
optimizer->Optimize(yourPointBudget, cancel, OPTIMIZE_TO_NBR|OPTIMIZE_TO_POINT);
This target might be unreachable if yourPointBudget < optimizer->GetInitialRemovablePointsNumber()
Get the optimization result
Once optimization is done you have to get back the result:
Code: Select all
C3DScene *resultingScene = optimizer->GetScene(OPTIMIZED_OBJECT_CLEANED);
You can then convert back this scene to your format or save it using one of the available output format.
You then have to free (or not, depending on the CSceneOptimizer::SetScene setting) the SDK scene.
This can be done with:
Code: Select all
xDelete(scene); // By default optimizer delete the scene itself.