level_of_detail.adoc 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. = Level of Detail (LOD) Optimization
  2. :revnumber: 2.0
  3. :revdate: 2020/07/15
  4. :uri-jme3: https://github.com/jMonkeyEngine/jmonkeyengine/blob/master
  5. A mesh with a high level of detail has lots of polygons and looks good close up. But when the mesh is further away (and the detail is not visible), the high-polygon count slows down performance unnecessarily.
  6. One solution for this problem is to use high-detail meshes for objects close to the camera, and low-detail meshes for objects far from the camera. As the player moves through the scene, you must keep replacing close objects by more detailed meshes, and far objects by less detailed meshes. The goal is to keep few high-quality slow-rendering objects in the foreground, and many low-quality fast-rendering objects in the background. (Experienced users can compare this approach to xref:jme3/advanced/terrain.adoc[JME's TerraMonkey terrain system], which internally uses the specialized GeoMipMapping algorithm to generate a terrain's Levels of Detail.)
  7. You see now why you may want to be able to generate Levels of Detail for complex Geometries automatically. JME3 supports a Java implementation of the Ogre engine's LOD generator (originally by Péter Szücs and Stan Melax): You use link:{uri-jme3}/jme3-core/src/tools/java/jme3tools/optimize/LodGenerator.java[jme3tools.optimize.LodGenerator] in conjunction with link:{uri-jme3}/jme3-core/src/main/java/com/jme3/scene/control/LodControl.java[com.jme3.scene.control.LodControl].
  8. For a demo, run link:{uri-jme3}/jme3-examples/src/main/java/jme3test/stress/TestLodGeneration.java[TestLodGeneration.java] from xref:sdk:sample_code.adoc[JmeTests], then press +/- and spacebar to experiment. The following screenshots show a monkey model with three reduced Levels of Detail:
  9. image::jme3/advanced/jmonkey-lod.gif[jmonkey-lod.gif,width="",height="",align="center"]
  10. == Usage
  11. To activate this optimization:
  12. . Pick a reduction method and values for the Geometry. (Trial and error…)
  13. . Generate LODs for the Geometry, either in the SDK or in code.
  14. . Add an LOD control to the Geometry.
  15. == Pick Reduction Methods and Values
  16. There are several reduction methods to generate a low-polygon version from a high-polygon model. Don't worry, the reduction does not modify the original model.
  17. [cols="35,55,10", options="header"]
  18. |===
  19. a|Reduction Method
  20. a|Description
  21. a|Reduction Value
  22. a|LodGenerator.TriangleReductionMethod.COLLAPSE_COST
  23. a|Collapses polygon vertices from the mesh until the reduction cost (= amount of ugly artifacts caused) exceeds the given threshold.
  24. a|0.0f - 1.0f
  25. a|LodGenerator.TriangleReductionMethod.PROPORTIONAL
  26. a|Removes the given percentage of polygons from the mesh.
  27. a| 0.0f - 1.0f
  28. a|LodGenerator.TriangleReductionMethod.CONSTANT
  29. a|Removes the given number of polygons from the mesh.
  30. a| integer
  31. |===
  32. If you don't know which to choose, experiment. For example start by trying COLLAPSE_COST and .5f-.9f.
  33. == Generate LOD
  34. You must generate and cache several LODs for each mesh, ranging from many to few polygons. The LOD generator algorithm attempts to collaps vertices automatically, while avoiding ugly artifacts. The LOD generator doesn't generate new meshes, it only creates separate reduced index buffers for the more highly reduced levels.
  35. * If you create geometries manually (3D models), use the SDK to generate LODs.
  36. * If you create geometries programmatically, generate LODs from your Java code.
  37. === Generating LODs in the SDK
  38. The SDK contains a user-friendly interface to generate LODs for a model (.j3o file).
  39. . Open the Projects or Files window.
  40. . Select the .j3o file in the `Project Assets/Models` directory.
  41. . Choose `menu:Window[Edit in SceneExplorer]` if the SceneExplorer is not open. Info about the selected model is now displayed in the SceneExplorer.
  42. . btn:[RMB] select the model in SceneExplorer. Choose the `menu:Tools[Generate Levels of Detail]` menu. +
  43. image:jme3/advanced/jme-sdk-generate-lod-menu.png[The Tools Generate LOD context menu in the SceneExplorer,width="300",height="180"]
  44. . The `Generate LOD` settings wizard opens: +
  45. image:jme3/advanced/jme-sdk-generate-lod-window.png[The Generate LOD settings wizard,width="300",height="150"]
  46. . Choose a reduction method and reduction values for one or more levels.
  47. +
  48. [TIP]
  49. ====
  50. Enter higher reduction values for higher levels.
  51. ====
  52. . Click btn:[Finish] to generate the LODs for this model.
  53. The LODs are saved in the .j3o model file.
  54. [TIP]
  55. ====
  56. Choose `menu:Window[Properties]` if the Properties window is not open. Choose the generated LODs from the dropdown in the Properties window, and verify their quality in the SceneComposer.
  57. ====
  58. image::jme3/advanced/jme-sdk-generate-lod-full.png[jme-sdk-generate-lod-full.png,width="",height="",align="center"]
  59. === Generating LODs in Code
  60. The `jme3tools.optimize.LodGenerator` utility class helps you generate LODs for an arbitrary mesh (a Geometry object) programmatically from your Java code. You create and bake one LodGenerator for each Geometry.
  61. [source,java]
  62. ----
  63. LodGenerator lod = new LodGenerator(geometry);
  64. lod.bakeLods(reductionMethod,reductionValue);
  65. ----
  66. The LODs are stored inside the Geometry object.
  67. *Example:* How to generate an LOD of myPrettyGeo's mesh with the same settings as used in the SDK example above:
  68. [source,java]
  69. ----
  70. LodGenerator lod = new LodGenerator(myPrettyGeo);
  71. lod.bakeLods(LodGenerator.TriangleReductionMethod.PROPORTIONAL,0.25, 0.5f, 0.75f);
  72. ----
  73. == Activate the LOD Control
  74. After generating the LODs for the geometry, you create and add a `com.jme3.scene.control.LodControl` to the geometry. Adding the LodControl activates the LOD optimizaton for this geometry.
  75. [source,java]
  76. ----
  77. LodControl lc = new LodControl();
  78. myPrettyGeo.addControl(lc);
  79. rootNode.attachChild(myPrettyGeo);
  80. ----
  81. The LodControl internally gets the camera from the game's viewport to calculate the distance to this geometry. Depending on the distance, the LodControl selects an appropriate level of detail, and passes more (or less) detailed vertex data to the renderer.
  82. == Impact on Quality and Speed
  83. [cols="10,30,20,20,20", options="header"]
  84. |===
  85. a|Level number
  86. a|Purpose
  87. a|Distance
  88. a|Rendering Speed
  89. a|Rendering Quality
  90. a|Level 0
  91. a|The original mesh is used automatically for close-ups, and it's the default if no LODs have been generated.
  92. a|Closest
  93. a|Slowest.
  94. a|Best.
  95. a|Level 1 +
  96. Level 2 +
  97. Level 3
  98. a|If you generated LODs, JME3 uses them automatically as soon as the object moves into the background.
  99. a|The higher the level, +
  100. the further away.
  101. a|The higher the level, +
  102. the faster.
  103. a|The higher the level, +
  104. the lower the quality.
  105. |===
  106. == See also
  107. * link:https://hub.jmonkeyengine.org/t/brand-new-lod-generator/26341[https://hub.jmonkeyengine.org/t/brand-new-lod-generator/26341]
  108. * link:https://github.com/worldforge/ember/tree/master/src/components/ogre/lod[https://github.com/worldforge/ember/tree/master/src/components/ogre/lod]
  109. * link:http://www.melax.com/polychop[http://www.melax.com/polychop]
  110. * xref:jme3/advanced/terrain.adoc[JME3 TerraMonkey Terrain]