-
Notifications
You must be signed in to change notification settings - Fork 152
OptimizeFaces
DirectXMesh |
---|
Reorders faces to improve post-transform vertex cache reuse using the Hoppe algorithm.
HRESULT OptimizeFaces(
const uint16_t* indices, size_t nFaces,
const uint32_t* adjacency,
uint32_t* faceRemap,
uint32_t vertexCache = OPTFACES_V_DEFAULT,
uint32_t restart = OPTFACES_R_DEFAULT );
HRESULT OptimizeFacesEx(
const uint16_t* indices, size_t nFaces,
const uint32_t* adjacency, const uint32_t* attributes,
uint32_t* faceRemap,
uint32_t vertexCache = OPTFACES_V_DEFAULT,
uint32_t restart = OPTFACES_R_DEFAULT );
HRESULT OptimizeFaces(
const uint32_t* indices, size_t nFaces,
const uint32_t* adjacency,
uint32_t* faceRemap,
uint32_t vertexCache = OPTFACES_V_DEFAULT,
uint32_t restart = OPTFACES_R_DEFAULT );
HRESULT OptimizeFacesEx(
const uint32_t* indices, size_t nFaces,
const uint32_t* adjacency, const uint32_t* attributes,
uint32_t* faceRemap,
uint32_t vertexCache = OPTFACES_V_DEFAULT,
uint32_t restart = OPTFACES_R_DEFAULT );
See also OptimizeFacesLRU
faceRemap is an array describing the reordering, and must have nFaces entries: oldLoc = faceRemap[newLoc]
. See ReorderIB and ReorderIBAndAdjacency for details.
Note this matches the D3DXMesh::Optimize method and D3DXOptimizeFaces function definitions of the face remap array.
vertexCache is the size of the vertex cache to assume for the optimization. If OPTFACES_STRIPORDER
is provided, then the vertex cache simulation is not used and the faces are put in "strip order". This number should typically range from 0 to 32.
restart is a threshold used to control when strips are restarted based. This number must be less than or equal to vertexCache, and is ignored for OPTFACES_STRIPORDER
.
This implements the same algorithm as D3DX with explicit control over the simulated vertex cache size. OPTFACES_V_DEFAULT
/ OPTFACES_R_DEFAULT
is the same value that D3DXOptimizeFaces
used (.e. D3DXMESHOPT_DEVICEINDEPENDENT
).
Some vendors support a Direct3D 9 query D3DQUERYTYPE_VCACHE
that reports the vertex cache optimization settings that are device specific. If OptMethod is 0, use OPTFACES_STRIPORDER
, otherwise pass CacheSize as vertexCache and MagicNumber as restart. For some example code for checking this query, see vcache.cpp.
Note that optimizing for a vertexCache larger than is present on the hardware can result in poorer performance than the original mesh, so this value should be picked either for a known fixed device or conservatively.
Degenerate and 'unused' faces are skipped by the optimization, so they do not appear in the remap order.
There are models where the optimization fails to produce a faster ordering. For this reason, you should evaluate the original and optimized models with ComputeVertexCacheMissRate. If the new model is worse, use the original.
Note that D3DXOptimizeFaces
generated adjacency internally, but was low quality as it lacks access to the vertex position. Explicitly generating with GenerateAdjacencyAndPointReps
and then optimizing faces is more accurate and provides more programmer control.
auto mesh = std::make_unique<WaveFrontReader<uint16_t>>();
if ( FAILED( mesh->Load( L"test.obj" ) ) )
// Error
size_t nFaces = mesh->indices.size() / 3;
size_t nVerts = mesh->vertices.size();
auto pos = std::make_unique<XMFLOAT3[]>(nVerts);
for( size_t j = 0; j < nVerts; ++j )
pos[ j ] = mesh->vertices[ j ].position;
auto adj = std::make_unique<uint32_t[]>(mesh->indices.size());
if ( FAILED( GenerateAdjacencyAndPointReps( mesh->indices.data(), nFaces,
pos.get(), nVerts, 0.f, nullptr, adj.get() ) ) )
// Error
auto faceRemap = std::make_unique<uint32_t[]>(nFaces);
if ( FAILED( OptimizeFaces( mesh->indices.data(), nFaces, adj.get(),
faceRemap.get() ) ) )
// Error
auto newIndices = std::make_unique<uint16_t[]>(nFaces * 3);
if ( FAILED( ReorderIB( mesh->indices.data(), nFaces, faceRemap.get(),
newIndices.get() ) ) )
// Error
Hoppe, H.; "Optimization of mesh locality for transparent vertex caching", ACM SIGGRAPH 1999 Proceedings link
All content and source code for this package are subject to the terms of the MIT License.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
- Universal Windows Platform apps
- Windows desktop apps
- Windows 11
- Windows 10
- Windows 8.1
- Xbox One
- Xbox Series X|S
- Windows Subsystem for Linux
- x86
- x64
- ARM64
- Visual Studio 2022
- Visual Studio 2019 (16.11)
- clang/LLVM v12 - v18
- GCC 10.5, 11.4, 12.3
- MinGW 12.2, 13.2
- CMake 3.20
DirectX Tool Kit for DirectX 11