Page 1 of 1

Using dynamic optimization

Posted: Tue Jan 25, 2022 4:35 pm
by mootools
This article is to be read after : Details on CSceneOptimizer (static optimization)

You may though to use dynamic optimization if you have to modify the optimization ratio multiple time. This can be the case for adjusting the ratio depending on a camera position : the closer the camera to the objet the higher the optimization ratio.
You also have to use dynamic resolution if you plan to use MagicCruncher.

First you must have a scene and prepare it for optimization:

Code: Select all

CSceneImportOptions options;
options.flags = SCENE_IMPORT_GENERATE_UV;
CXString filename = "YOUR_FILENAME_HERE";
C3DIo file(filename, FILE_PARSER_LOADING);
C3DScene *scene = file.Read(&options);
if (!scene)
{
	_tprintf(FormatString(_T("There was an error when reading the file %s\r\n"), (LPCTSTR)filename));
	return 1;
}
	
// Very important !
// Convert scene and use C3DExtObject king of object.
// This type is required for optimizing. If ommit, no optimization is performed
C3DPolygonCruncherObjectCreator cruncherCreator(DEFAULT_OPTIMIZATION_OBJECT);
scene->ConvertToType(NULL, &cruncherCreator);

CSceneOptimizer *optimizer = xNew(CSceneOptimizer);
optimizer->SetFlag(SCENEOPTIMIZER_PROGRESSIVE_RATIO, true); // No matter is trying on the capsule, but it gives better results you have several objects
optimizer->SetScene(*scene, true);
Then you must turn on SCENEOPTIMIZER_TRACK_CHANGES. This is require to be able to get multi resolution objet.
The following code prepare the optimizer and do the optimization computation to the maximum ratio.
Doing that optimization track optimization computation for every meshes from its original state to its maximum optimization.

Code: Select all

optimizer->SetFlag(SCENEOPTIMIZER_TRACK_CHANGES, true); // Turn on dynamic optimization capabilities

#define DEFAULT_OPTIMIZATION_MODE OPTIMIZE_PROTECT_BORDER|OPTIMIZE_VERIFY_PAIRS_MASK|OPTIMIZE_KEEP_MATERIAL_FRONTIER|OPTIMIZE_PROTECT_MATERIAL_FRONTIER|OPTIMIZE_KEEP_UV|OPTIMIZE_PROTECT_UV

// Define some optimization settings
optimizer->SetOptimizeMode(DEFAULT_OPTIMIZATION_MODE, true);

bool cancel;
optimizer->Optimize(0.0f, cancel); // Optimize the whole scene at its maximum ratio.Note: if you use another ratio R (< 1.0), then the dynamic object ratio range will be possible from 1.0 to R only (which might be enough!)
No we have a an optimized scene from which we can get a dynamic scene.

Code: Select all

// Get a dynamic scene which is made of dynamic objects. Each one have the class CMultiresolutionObject.
C3DScene *optimizescene = optimizer->GetScene(OPTIMIZED_MULTIRESOLUTION_SCENE); // Compute the multiresolution scene
if (!optimizescene)
{
	xDelete(optimizer);
	return 1;
}

// at this point the loaded scene is not useful anymore. We have a dynamic copy of it.
// We can delete it to limit memory needs
optimizer->DeleteScene();
Now we have a dynamic scene and we can play with the ratio.
This can be done globally for the whole scene using CSceneOptimizer::SetMultiresolutionRatio

Code: Select all

char key = 0;
while (key != ' ')
{
	key = getch();

	bool predictive = false, magic = false;
	if (key == '+')
		ratio += 0.1f;
	else if (key == '-')
		ratio -= 0.1f;

	optimizer->SetMultiresolutionRatio(ratio, 0, OPTIMIZE_TO_POINT|OPTIMIZE_TO_RATIO);
}
Note that you can also get access to multiresolution meshes individually and set a different ratio for each one:

Code: Select all

// Select all instance of the selected nodes
C3DSceneNode *node;
C3DBaseObject *baseobject;
CMultiresolutionObject *multires = NULL;
C3DNodePos pos = scene->GetFirstNode(OBJECT_GEOM);
while (pos)
{
	node = scene->GetNextNode(baseobject, pos);
	if (!baseobject->IsKindOf(XRUNTIME_CLASS(CMultiresolutionObject)))
		continue;

	multires= (CMultiresolutionObject *)baseobject;
	multires->SetObjectRatio(GetRatioFromDistToCamera(), , OPTIMIZE_TO_POINT|OPTIMIZE_TO_RATIO); // Optimize the object using a condition 
}
You can also use MagicCruncher because using the appropriate ratio might be difficult to determine.
MagicCruncher requires to have a dynamic scene... but all this will be explained in another post.