I am importing an extremely detailed mesh (provided by a client) and it consists of something like 16 million triangles. For rendering performance I've been using the ID3DXMesh interface's Optimize and OptimizeInPlace methods. I'm using GenerateAdjacency with an epsilon of around 0.0025, and there doesn't seem to be much optimizing going on. Even with an epsilon of around 50.0 there's no significant increase in performance.

Am I misunderstanding Optimize? Isn't it supposed to get rid of unused faces based on the adjacency buffer? If that isn't the case, what other methods/algorithms/libraries could I use that would reduce level of detail?

Here's my code:

this->m_pMesh->GenerateAdjacency( 0.0025f, l_ulpAdjacencyBuffer );
this->m_pMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT |D3DXMESHOPT_VERTEXCACHE, l_ulpAdjacencyBuffer, 0, 0, 0);
  • 1
    \$\begingroup\$ Does the model have to have this many triangles in-game? Can't you reduce the polycount offline? \$\endgroup\$
    – knight666
    Jul 27, 2012 at 7:39
  • \$\begingroup\$ Can you count the number of triangles before and after? Did something actually change? \$\endgroup\$
    – Roy T.
    Jul 27, 2012 at 8:57
  • 3
    \$\begingroup\$ One thing or another has to give -- either a maximum polycount for import is agreed with your client, or you do offline processing. Having said that, I hope you find a way to optimise it such that you can avoid the prior choices for now, but this sounds so open-ended to me as to seem as if you're just inviting disaster (problematic imports), whether now or months down the line. In other words, I really think you have to have some kind of upper bound on the input mesh. \$\endgroup\$
    – Engineer
    Jul 27, 2012 at 9:20
  • 1
    \$\begingroup\$ @Jannie if that is the case maybe optimize isn't working or you need to find another way to simplify the mesh. No need to do this offline, just place loading message in your program. Anyway see this question it has a few links: stackoverflow.com/questions/2892690/… \$\endgroup\$
    – Roy T.
    Jul 27, 2012 at 10:00
  • 1
    \$\begingroup\$ Yikes Krom Stern is very protective of this question. Sometimes we all make comment-like answers, it doesn't mean they're not useful and should be down-voted. \$\endgroup\$
    – House
    Jul 27, 2012 at 15:14

2 Answers 2


The short answer is "Poly count is not what Optimize is optimizing".

The D3DXMesh Optimize routine performs the following

(1) It attribute sorts the mesh, which means ensuring all faces sharing the same attributes are grouped together. Any shared vertices that appear in multiple attribute groups are duplicated.

(2) Faces are optimized for the post-transform vertex cache per the algorithm in this paper. This primarily reorders the faces into strips of triangles paying attention to the vertex cache size. This reorders the index buffer.

Hoppe, H.; "Optimization of mesh locality for transparent vertex caching", ACM SIGGRAPH 1999 Proceedings. Link

(3) Vertices are optimized for the pre-transform vertex cache which means the vertex buffer is sorted in order of use by the associated index buffer

BTW, there's a shared-source version of many of these methods available on CodePlex in the DirectXMesh library including the mesh optimization algorithm mentioned above.

No where in here does it 'simplify' the mesh or reduce polygon count. As a side-effect of this optimization, degenerate faces and unused vertices are removed. But that's it. You could use the legacy D3DX9 D3DXSimplfyMesh function which uses vertex and edge decimation, but I don't know how great it will work on your meshes.

For games and other real-time scenarios, most folks build custom level-of-detail models or use a commercial tool like SimplyGon.


It seems you have a contradiction in requirements.

You have not given me much to go, but I'll hazard a guess: you're working with medical or other scientific data that is being supplied in an outrageously inefficient format (as medical or scientific data tends to be).

The client needs to be able to import any model of their choosing in your simulation, whether it's 1,000 or 10,000,000 triangles. This implies that the renderer should be optimized to handle those large polycounts, by chunking or streaming the model or perhaps some other clever hacks.

But the simulation should also run in real-time.

If you are not allowed to touch the client's data, this seems an impossible task. If the client supplies Wavefront .obj's for example, the textual data could run into the hundres of megabytes. All that has to be read and parsed before even being transmitted to the videocard.

A much better solution would be to supply the client with a model converter. This converts their models (.obj) to your format (optimized binary), leaving the client's data intact while you're able to run the simulation in real-time. A good starting point would be to look at Horde3D's binary representation. The engine is open source and the binary model format is really quite good. Bonus: a converter already exist to go from COLLADA to Horde3D.

As for your original question: there are many algorithms that will optimize a model's polycount for you, but they are very context-specific. What works for one situation (triangulated data from voxels) might not work at all for another situation (architectural prototype exported from AutoCAD).

  • \$\begingroup\$ Right now we do have a converter to import their model format and create a D3DXMesh. Due to the high level of detail of the model the polycount is enormous, but we expect Optimize or OptimizeInPlace to reduce the polycount (and when we use a quite large epsilon, reduce it drastically). \$\endgroup\$
    – Jannie
    Jul 27, 2012 at 10:00
  • \$\begingroup\$ Downvoted. This is not an answer to posed question, just an expanded side-note comment. \$\endgroup\$
    – Kromster
    Jul 27, 2012 at 11:15
  • 1
    \$\begingroup\$ @KromStern That's because the OP has given us so little to go on that we are left no choice but to expand the search parameters. If the question was: "How do I drive a nail into my nose?", a valid answer could be "With a hammer." and another equally valid answer is "What are you trying to accomplish by doing that?" That's what makes StackExchange better than Google, because we're a human search engine. \$\endgroup\$
    – knight666
    Jul 27, 2012 at 11:18
  • \$\begingroup\$ @knight666: It's classical "I want to do A to get B", "You don't need A, use C!". But the question was specifically about "Why Optimize does not work?", which is a good question by itself. If you can answer that then it is an answer that is A-correct B-useful for others C-highly relevant. If you go on with commenting it it should stay as a comment. \$\endgroup\$
    – Kromster
    Jul 27, 2012 at 12:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .