Details on CSceneOptimizer (static optimization)

Question and answer about Polygon Cruncher SDK
Post Reply
Site Admin
Posts: 282
Joined: Thu Jul 05, 2007 11:06 am

Details on CSceneOptimizer (static optimization)

Post by mootools » Thu May 04, 2017 10:10 am

CSceneOptimizer class is the heart of optimization.
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.
In this article, we will consider the static optimization case.

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);
Once the scene matches the requirements, you can provide it to CSceneOptimizer

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
Optimization mode

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.
If your scene contains several meshes, a good idea is to use the progressive optimization which deal with different detail level of objects.
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.
Next, we have to choose an optimization mode among the OPTIMIZE_MODE enum.
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
Saying that the code to define the optimization mode could be the following:

Code: Select all


// Define some optimization settings

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

Optimizing in the static optimization case

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);
In this case you use a simple ratio : ie 0.5 will remove 50% of the optimizable faces.
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);
In this case you you specify the polygon budget directly. This is not a ratio but this is a target.
This target can be unreachable if yourPolygonBudget < optimizer->GetInitialRemovableFacesNumber()

Code: Select all

 optimizer->Optimize(yourPointBudget, cancel, OPTIMIZE_TO_NBR|OPTIMIZE_TO_POINT);
Same with a point budget
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);
In the static optimization case resultingScene = scene, so you don't need to delete this scene.
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.
You can continue your reading with Using dynamic optimization

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest